Bug
There are two problems in Tools.php:
- checkInput for 'date' is too permissive (line ~107–111)
// Current — only checks there are 3 dash-separated parts; does NOT validate they are integers
elseif ($type == 'date')
{
$time = explode ('-', $value);
return self::isValidUTF8 ($value) && (count ($time) == 3);
}
A value like "a-b-c" passes this check.
- getInput for 'date' calls mktime() with the raw (unvalidated) string parts (line ~35–37)
case 'date':
$time = explode ('-', $dat[$key]);
return mktime (0, 0, 1, $time[1], $time[2], $time[0]);
When those parts aren't integers, PHP emits mktime() expects parameter N to be int, string given and returns false. The caller then gets false instead of null, which causes a TypeError if a typed ?DateTime parameter is expected.
Recommended fix
Fix checkInput to validate the date format with a regex and checkdate():
elseif ($type == 'date')
{
if (!self::isValidUTF8($value)) {
return false;
}
$time = explode('-', $value);
return count($time) === 3
&& ctype_digit($time[0])
&& ctype_digit($time[1])
&& ctype_digit($time[2])
&& checkdate((int)$time[1], (int)$time[2], (int)$time[0]);
}
Fix getInput to cast parts to int before passing to mktime():
case 'date':
$time = explode('-', $dat[$key]);
return mktime(0, 0, 1, (int)$time[1], (int)$time[2], (int)$time[0]);
The checkInput fix is the real guard; the getInput cast is a defence-in-depth measure. Together they ensure any value reaching mktime() is always a valid date with integer parts.
Additionally, expand the testing to make sure situations like these are catched.
Also add a bunch of tests that specifically focus on various forms of database query injections.
Aim for 90% coverage of the complete code base.
Summarize your project understanding in .ai folder and create a claude.md referencing these documents.
Add github CI to run the tests.
Bug
There are two problems in Tools.php:
// Current — only checks there are 3 dash-separated parts; does NOT validate they are integers
elseif ($type == 'date')
{
$time = explode ('-', $value);
return self::isValidUTF8 ($value) && (count ($time) == 3);
}
A value like "a-b-c" passes this check.
case 'date':
$time = explode ('-', $dat[$key]);
return mktime (0, 0, 1, $time[1], $time[2], $time[0]);
When those parts aren't integers, PHP emits mktime() expects parameter N to be int, string given and returns false. The caller then gets false instead of null, which causes a TypeError if a typed ?DateTime parameter is expected.
Recommended fix
Fix checkInput to validate the date format with a regex and checkdate():
elseif ($type == 'date')
{
if (!self::isValidUTF8($value)) {
return false;
}
$time = explode('-', $value);
return count($time) === 3
&& ctype_digit($time[0])
&& ctype_digit($time[1])
&& ctype_digit($time[2])
&& checkdate((int)$time[1], (int)$time[2], (int)$time[0]);
}
Fix getInput to cast parts to int before passing to mktime():
case 'date':
$time = explode('-', $dat[$key]);
return mktime(0, 0, 1, (int)$time[1], (int)$time[2], (int)$time[0]);
The checkInput fix is the real guard; the getInput cast is a defence-in-depth measure. Together they ensure any value reaching mktime() is always a valid date with integer parts.
Additionally, expand the testing to make sure situations like these are catched.
Also add a bunch of tests that specifically focus on various forms of database query injections.
Aim for 90% coverage of the complete code base.
Summarize your project understanding in .ai folder and create a claude.md referencing these documents.
Add github CI to run the tests.