php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #71099 Basic assertion failing in PHP 7
Submitted: 2015-12-11 23:42 UTC Modified: 2015-12-12 00:08 UTC
From: cdtreeks at gmail dot com Assigned:
Status: Not a bug Package: Scripting Engine problem
PHP Version: 7.0.0 OS: CentOS 7
Private report: No CVE-ID: None
 [2015-12-11 23:42 UTC] cdtreeks at gmail dot com
Description:
------------
Comparing two different values is failing to assert correctly in the latest release of PHP 7. See 'Test script' below for more details.

Test script:
---------------
<?php
$val_1 = 'test_string'; // Value is 'test_string'
$val_2 = (int) $val_1;  // Value is 0

if ($val_1 == $val_2) {
   // PHP believes 'test_string' == 0
   ...
} else {
   ...
}

Expected result:
----------------
The else clause should be hit.

Actual result:
--------------
The initial condition is returning true

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2015-12-11 23:51 UTC] nikic@php.net
-Status: Open +Status: Not a bug
 [2015-12-11 23:51 UTC] nikic@php.net
This is how PHP has always worked, nothing to do with PHP 7.

The "logic" behind it is that an integer to string comparison will cast the string to an integer, thus giving you the result you observe. I think this is generally agreed to be not very useful, but also unlikely to change due to BC concerns.
 [2015-12-11 23:51 UTC] rasmus@php.net
You want === there otherwise you are comparing an int to a string and type coercion is going to make both sides int. The integer value of your string is 0 so 0 == 0.
 [2015-12-12 00:00 UTC] cdtreeks at gmail dot com
Perhaps it would have helped to mention the context here as I'm trying to validate $_POST data.

For example a user submitting a value of 100 in a form. When PHP receives this it'll be a string.

For strict form validation, I was trying to make sure that int fields were only even processing an int response.

is_int() can't be used as when being used on a string, you'll get false. Is numeric can help, but this would also return true for a float.

Seems the best way around it is a bit of a hack:

<?php
<?php
$val_1 = 'test_string'; // Value is 'test_string'
$val_2 = (string) (int) $val_1;  // Value is '0' - This MUST be cast back to a string after typecasting the value to an int

if ($val_1 == $val_2) {
   // This now works as expected as we're comparing two strings
} else {
   ...
}
 [2015-12-12 00:05 UTC] cdtreeks at gmail dot com
...or I suppose I could always do:
<?php
if (is_numeric($val_1) && !is_float($val_1)) {
    ...
}
 [2015-12-12 00:08 UTC] rasmus@php.net
This is really what the filter functions are for.

if (filter_var($_GET['val_1'], FILTER_VALIDATE_INT)) { ... }

or better:

if (filter_input(INPUT_GET, 'val_1', FILTER_VALIDATE_INT)) { ... }
 [2015-12-12 01:27 UTC] cdtreeks at gmail dot com
I hadn't come across filter_input() before but that's exactly what I was after. Thanks
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sun May 05 09:01:30 2024 UTC