PhpNativeTypeCaster incorrectly casts string "false" and "0" to true
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 85/100
Research direction
Start in PhpNativeTypeCaster at the bool branch of the second pass, then inspect the existing 'string-to-bool' coverage in HydratorTest. Add coverage for string values 'false', 'true', '0', and '1', and verify that hydration returns the expected booleans without changing existing integer behavior.
Written by the indexing model from the issue text.
Description
Problem
PhpNativeTypeCaster casts scalar values to bool using native PHP cast (bool) $value.
This produces incorrect results for common HTTP input values.
HTTP query parameters and form data are always strings. When hydrating a DTO property
typed as bool, values such as "false" and "0" are cast to true instead of false.
Steps to reproduce
use Yiisoft\Hydrator\ArrayData;
use Yiisoft\Hydrator\Hydrator;
final class Input
{
public bool $active = false;
}
$hydrator = new Hydrator();
$input = $hydrator->create(Input::class, new ArrayData(['active' => 'false']));
var_dump($input->active); // bool(true), expected bool(false)
The same issue occurs for query-string input in applications using yiisoft/input-http
with #[FromQuery] / #[FromBody] attributes.
Actual behavior
| Input value | Cast result |
|---|---|
"false" |
true |
"true" |
true |
"0" |
true |
"1" |
true |
"" |
false |
0 |
false |
1 |
true |
Expected behavior
String representations of boolean values should be parsed explicitly, similar to
how integer and float strings are handled via NumericHelper::normalize():
| Input value | Expected result |
|---|---|
"false" |
false |
"true" |
true |
"0" |
false |
"1" |
true |
Root cause
In PhpNativeTypeCaster, the bool branch of the second pass uses unconditional
native cast:
case 'bool':
if (is_scalar($value) || $value === null || is_array($value) || is_object($value)) {
return Result::success((bool) $value);
}
break;
In PHP, any non-empty string is truthy when cast to bool:
(bool) 'false'; // true
(bool) '0'; // true
Context
- The current test suite only covers
'string-to-bool'with input'1'(HydratorTest).
Cases'false','true', and'0'are not covered. - The official typecasting guide demonstrates bool hydration with integer
1,
not string"false". yiisoft/validatorprovidesBooleanValuerule for validation, but it does not
transform raw values during hydration. Even when validation passes,PhpNativeTypeCaster
still applies the incorrect cast afterward.
Suggested fix
For string and Stringable values, parse boolean keywords explicitly before
falling back to native cast. For example, filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE)
may be used for string input, with null mapped to Result::fail().
Suggested test cases
'false'->false'true'->true'0'->false'1'->true
Impact
Any application hydrating bool properties from HTTP input (query string, form data)
may silently receive inverted boolean values. This is especially dangerous for
filtering, feature flags, and opt-out parameters where false is the intended value.
- Dominant language
- PHP
- Stars
- 34
- Forks
- 6
- Avg merge
- 17m
- Merged PRs (30d)
- 4
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from yiisoft/hydrator
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
-
status:ready for adoption type:feature
-
type:test
Difficulty 4/5 3-5 days Newbie friendliness 25/100
-
status:under discussion type:task
Difficulty 2/5 1-3 hours Newbie friendliness 35/100
-
status:under discussion
Difficulty 4/5 3-5 days Newbie friendliness 25/100
All issues in yiisoft/hydrator
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
getgrav/grav-plugin-api#45 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
RSS-Bridge/rss-bridge#5098 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
phingofficial/phing#2025 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
silverstripe/developer-docs#911 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100