php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #66682 FILTER_VALIDATE_INT fails on strings starting with zero.
Submitted: 2014-02-10 05:40 UTC Modified: 2014-02-17 04:09 UTC
From: alex dot howansky at gmail dot com Assigned:
Status: Not a bug Package: Filter related
PHP Version: 5.5.9 OS: Linux 2.6 64
Private report: No CVE-ID: None
 [2014-02-10 05:40 UTC] alex dot howansky at gmail dot com
Description:
------------
FILTER_VALIDATE_INT fails on '01'. I can understand that opinions might be divided on whether this should return 1 or false -- however, in either case, the behavior of FILTER_VALIDATE_FLOAT should match, and it doesn't.

Test script:
---------------
var_dump(filter_var('01', FILTER_VALIDATE_INT));
var_dump(filter_var('01', FILTER_VALIDATE_FLOAT));


Expected result:
----------------
int(1)
double(1)

or:

bool(false)
bool(false)

Actual result:
--------------
bool(false)
double(1)

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-02-16 06:15 UTC] yohgaki@php.net
-Status: Open +Status: Analyzed
 [2014-02-16 06:15 UTC] yohgaki@php.net
This is because php_fileter_int() treats leading 0 as hex/octal numbers.
I'm not sure which one int or float should be fixed. Possible fix is 

https://github.com/yohgaki/php-src/compare/PHP-5.4-bug66682
 [2014-02-16 06:24 UTC] yohgaki@php.net
php_filter_parse_int() does not allow leading 0
 [2014-02-16 11:55 UTC] derick@php.net
-Status: Analyzed +Status: Not a bug
 [2014-02-16 11:55 UTC] derick@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

This is by design.
 [2014-02-16 16:23 UTC] alex dot howansky at gmail dot com
> Please double-check the documentation

I'm unable to find any documentation that contradicts my evaluation or explains this behavior. Can you please link to the specific page you're referring to?

I'm confused by the hex/oct comment -- whether or not "01" is interpreted as octal or hex doesn't change the fact that it's still a valid value for an integer. I.e., "01" octal is a valid int, "01" hex is a valid int, and "01" decimal is a valid int.

Also, if I plug "01" into any other function that expects an integer, it will work just fine. Consider this:

var_dump(abs('01'));
var_dump(intval('01'));
var_dump(octdec('01'));
var_dump(hexdec('01'));
var_dump(filter_var('01' + '0.0', FILTER_VALIDATE_INT));
var_dump(filter_var('01', FILTER_VALIDATE_INT));

Returns:

int(1)
int(1)
int(1)
int(1)
int(1)
bool(false)

Don't you think that output is rather contradictory?
 [2014-02-16 18:52 UTC] alex dot howansky at gmail dot com
Also, consider this:

var_dump(filter_var('0', FILTER_VALIDATE_INT));
var_dump(filter_var('00', FILTER_VALIDATE_INT));

Returns:

int(0)
bool(false)

That's incredibly counter-intuitive.
 [2014-02-16 19:17 UTC] rasmus@php.net
By definition an integer with a leading zero is octal notation so 00 is octal 0. There is a flag to explicitly allow octal integers which should also tell you that validate_int validates integers written in decimal notation by default.
 [2014-02-16 21:38 UTC] alex dot howansky at gmail dot com
OK, understood. Unfortunately, this leaves an odd hole when working with strings that start with zero and contain an eight or nine. For example, intval() only performs octal validation if you explicitly override the base parameter's default value of 10. As a result, intval('09') gives you exactly what you'd expect -- int(9). Likewise, '09' + 1 works just as expected, in base 10. However, regardless of flags, FILTER_VALIDATE_INT can never return true for string '09'. Given that '09' is perfectly acceptable input for other cases which require an int, this seems inconsistent. Perhaps a new option should be added to this filter, named "base" or similar, which functions like the optional "base" argument of intval().
 [2014-02-16 21:57 UTC] yohgaki@php.net
Hi Derick,

I'm not sure if this behavior is documented somewhere, but it seems strange. Tests do not cover "01.23" nor "01" also, for example. I found this note http://jp2.php.net/manual/en/filter.filters.validate.php but nothing else.

Note:
As of PHP 5.4.11, the numbers +0 and -0 validate as both integers as well as floats (using FILTER_VALIDATE_FLOAT and FILTER_VALIDATE_INT). Before PHP 5.4.11 they only validated as floats (using FILTER_VALIDATE_FLOAT).
When default is set to option, default's value is used if value is not validated.

If we are not going to fix this, this behavior should be documented if it's not already there. So make this a documentation problem?

BTW, I haven't test much, but the patch in github invalidates "01", "01.123", etc.
 [2014-02-16 22:16 UTC] yohgaki@php.net
Isn't it easier with validate them for each? 
php_filter_int()
php_filter_octal()
php_filter_hex()
Perhaps?

BTW, if it could return string. It would be nice. Databases may have much higher precision.
 [2014-02-17 04:09 UTC] rasmus@php.net
Alex, you are mixing up two different things though. Intval() is a decimal cast operation. Same for applying math operators. A forced cast has nothing to do with a string validator. The string validator has a number of options, including whether or not you want to consider octal or hex notations valid. If you simply want the PHP integer value of a string, just cast it. If you want to check if something is a valid-looking integer for interacting with other systems, use the validator. Something like '00' and '09' are both problematic since they are not decimal integers in standard form and this could cause problems when passed to other systems. How PHP treats '00' and '09' internally is completely irrelevant since PHP is only one possible target for such data.
 
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Sat Dec 04 05:03:37 2021 UTC