|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2009-09-09 11:25 UTC] m dot kurzyna at crystalpoint dot pl
Description:
------------
filter_var() when validating (boolean)false with FILTER_NULL_ON_FAILURE returns null instead of false.
Reproduce code:
---------------
var_dump(
filter_var(false, FILTER_VALIDATE_BOOLEAN,
array("flags" => FILTER_NULL_ON_FAILURE)
)
);
Expected result:
----------------
false
Actual result:
--------------
null
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Fri Oct 24 07:00:01 2025 UTC |
If this is, as you say, intended behaviour then sorry, but it's broken by design. Although because of BC it'll never get fixed unfortunately so i'll just vent my frustration. In current state you have no way to use filters to *validate* boolean input (note that this is filter_validate_boolean not filter_sanitize_boolean - there is no such). As a sanitizer it's also broken though because real boolean values can't be used (or distinguished from error values when FILTER_NULL_ON_FAILURE is given) so you'd have to first check whether value is boolean and if not try to sanitize it to boolean using validating filter. It even sound broken. Also it's internally inconsistent. It works as expected for plain filtering: var_dump( filter_var(true,FILTER_VALIDATE_BOOLEAN), // true filter_var("true",FILTER_VALIDATE_BOOLEAN), // true filter_var(1,FILTER_VALIDATE_BOOLEAN), // true filter_var("1",FILTER_VALIDATE_BOOLEAN), // true filter_var("on",FILTER_VALIDATE_BOOLEAN), // true filter_var("yes",FILTER_VALIDATE_BOOLEAN) // true ); var_dump( filter_var(false,FILTER_VALIDATE_BOOLEAN), // false filter_var("false",FILTER_VALIDATE_BOOLEAN), // false filter_var(0,FILTER_VALIDATE_BOOLEAN), // false filter_var("0",FILTER_VALIDATE_BOOLEAN), // false filter_var("off",FILTER_VALIDATE_BOOLEAN), // false filter_var("no",FILTER_VALIDATE_BOOLEAN) // false ); var_dump( filter_var(7,FILTER_VALIDATE_BOOLEAN), // false filter_var("garbage",FILTER_VALIDATE_BOOLEAN) // false ); But fails to keep consistency when i try to distinguish whether value is "boolean" or not witch should be the sole role of *VALIDATE* filter: var_dump( filter_var(true,FILTER_VALIDATE_BOOLEAN,array('flags'=>FILTER_NULL_ON_FAILURE)), // got true, expected true filter_var("true",FILTER_VALIDATE_BOOLEAN,array('flags'=>FILTER_NULL_ON_FAILURE)), // got true, expected true filter_var(1,FILTER_VALIDATE_BOOLEAN,array('flags'=>FILTER_NULL_ON_FAILURE)), // got true, expected true filter_var("1",FILTER_VALIDATE_BOOLEAN,array('flags'=>FILTER_NULL_ON_FAILURE)), // got true, expected true filter_var("on",FILTER_VALIDATE_BOOLEAN,array('flags'=>FILTER_NULL_ON_FAILURE)), // got true, expected true filter_var("yes",FILTER_VALIDATE_BOOLEAN,array('flags'=>FILTER_NULL_ON_FAILURE)) // got true, expected true ); var_dump( filter_var(false,FILTER_VALIDATE_BOOLEAN,array('flags'=>FILTER_NULL_ON_FAILURE)), // got NULL, expected false filter_var("false",FILTER_VALIDATE_BOOLEAN,array('flags'=>FILTER_NULL_ON_FAILURE)), // got false, expected false filter_var(0,FILTER_VALIDATE_BOOLEAN,array('flags'=>FILTER_NULL_ON_FAILURE)), // got false, expected false filter_var("0",FILTER_VALIDATE_BOOLEAN,array('flags'=>FILTER_NULL_ON_FAILURE)), // got false, expected false filter_var("off",FILTER_VALIDATE_BOOLEAN,array('flags'=>FILTER_NULL_ON_FAILURE)), // got false, expected false filter_var("no",FILTER_VALIDATE_BOOLEAN,array('flags'=>FILTER_NULL_ON_FAILURE)) // got false, expected false ); var_dump( filter_var(7,FILTER_VALIDATE_BOOLEAN,array('flags'=>FILTER_NULL_ON_FAILURE)), // got null, expected null filter_var("garbage",FILTER_VALIDATE_BOOLEAN,array('flags'=>FILTER_NULL_ON_FAILURE)) // got null, expected null ); See that validating true works as expected so dunno why false should work differently. Also the "little bit confusing" part of false being non boolean is just plain wrong. In summary - please rethink this behaviour or at least fix the documentation by a) giving above example of all results (to show what is really to be expected) and b) state this is a validate filter by mistake but will stay like this because of BC concerns.This case sounds wrong: filter_var(false,FILTER_VALIDATE_BOOLEAN,array('flags'=>FILTER_NULL_ON_FAILURE)), // got NULL, expected false I have to check back the code, but this case does not make sense to me.Actually it is broken even more then i initially reported because it also returns NULL for empty string: filter_var('',FILTER_VALIDATE_BOOLEAN,array('flags'=>FILTER_NULL_ON_FAILURE)) // got NULL, expected false The problem is in ext/filter/logical_filters.c(233) - the check is done by using string representation of zval being checked. For false value it's an empty string and the switch from line 244 doesn't cover this case (hence same result for false and empty string). Something along the lines of following patch should fix the problem: --- logical_filters.c 2009-06-10 21:01:17.000000000 +0200 +++ logical_filters.fixed.c 2009-09-10 10:48:59.953675880 +0200 @@ -242,6 +242,10 @@ * returns false for "0", "false", "off", "no", and "" * null otherwise. */ switch (len) { + case 0: + ret = 0; + break; + case 1: if (*str == '1') { ret = 1; On the side note: i was always wondering why (string)false == '' and not '0'?As much as i'd like to have empty string be invalid false cast i have to disagree with you for consistency reasons. If (boolean)'' == false then filter_var('','boolean') should also return false. Both in general and in case of FILTER_NULL_ON_FAILURE (just like the documentation states). Also, because i can't stress it enough, this is a VALIDATOR not a SANITIZER so using it as a strict caster is secondary to it's validation purpose and as such it currently fails both on implied and explicit behavior. The ideal solution would be to have FILTER_VALIDATE_BOOLEAN roughly equal to current behavior with FILTER_NULL_ON_FAILURE and a *seperate* FILTER_SANITIZE_BOOLEAN similar to current behavior w/o the null failure flag. This however probably is impossible due to BC.filter_var(false,FILTER_VALIDATE_BOOLEAN,FILTER_NULL_ON_FAILURE) // got NULL, expected false That does not make sense at all! Further on, I have to agree with m.kurzyna that since false === (bool)"" filter_var("",FILTER_VALIDATE_BOOLEAN,FILTER_NULL_ON_FAILURE) should return FALSE and not NULL. Basically, as implemented, getting FALSE from filter_var(false,FILTER_VALIDATE_BOOLEAN) means that validation failed. It appears to be a design problem since filter_var() as specified will return FALSE if the filter fails making it impossible to distinguish if filter failed or valid FALSE value is returned. Therefore, instead returning FALSE if filter fails perhaps warning could be issued or even better exception thrown. On addition when voting I've wrongly selected that I am not using the same version and the same operating system. Correct ones are: PHP Version => 5.3.2-1ubuntu4.2 System => Linux schkovich 2.6.32-24-generic #42-Ubuntu SMP Fri Aug 20 14:21:58 UTC 2010 x86_64