php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #45068 Large integer immediates are read incorrectly
Submitted: 2008-05-22 19:34 UTC Modified: 2008-10-27 13:57 UTC
From: philipm at sybase dot com Assigned:
Status: Not a bug Package: Compile Failure
PHP Version: 5.2.6 OS: Linux (32-bit only)
Private report: No CVE-ID:
 [2008-05-22 19:34 UTC] philipm at sybase dot com
Description:
------------
Entering a large integer immediate (i.e. bigger than INT_MAX) will result in INT_MAX being used.  The issue is that these numbers cannot be treated as integers in the zval, but for some reason the parser is attempting to do so.  However, the various operators convert the large number to a float, so they work okay.

For example, entering:

3000000000 gives 2147483647
3000000000 + 1 gives 2147483648
3000000000.0 + 1 gives 3000000001

This issue was introduced in PHP 5.2.1 and has not been addressed as of 5.2.6.  5.2.0 and earlier worked as expected.  It also appears to work properly on Windows.

Reproduce code:
---------------
# the output should be the same as the input
print 3000000000 . "\n";

# these two should be the same
print 3000000000 + 1 . "\n";
print 3000000000.0 + 1 ."\n";


Expected result:
----------------
3000000000
3000000001
3000000001


Actual result:
--------------
2147483647
2147483648
3000000001

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-05-25 14:41 UTC] mattwil@php.net
This would seem to be caused by SIZEOF_LONG not being defined correctly (e.g. 8 when it should be 4 on 32-bit)... I'm the one who made the changes in 5.2.1 so most of the overhead to check for integer overflow could be eliminated, etc. It didn't cause any tests to fail, and this is the first issue I've heard. Also, I would expect numeric strings to fail in the same way: '3000000000' + 0 ?

Is the result the same if you use an 11-digit number? Any more details about your Linux system, in case there's something unique, might help the Linux experts (not me) figure something else out. I'm not sure what sets SIZEOF_LONG..... Oh wait, I was just looking at the configure script, and noticed bits about "cross compiling" where SIZEOF_LONG is defined -- do you know, is that something that applies in your configuration?
 [2008-05-26 16:00 UTC] philipm at sybase dot com
This 32-bit PHP executable was built on a 64-bit Red Hat Linux machine.  In order to build as 32-bit I set CFLAGS="-m32" then run configure.

Larger numbers (even those that require a 64-bit data type) also end up coming out as INT_MAX.  Note that even if SIZEOF_LONG is being set incorrectly, it does seem strange that everything is coming out as INT_MAX.  If the high-order bits were getting lost, I would expect to see the low-order bits coming out...but in this case I'm only seeing this number that is completely unrelated to the input value.

It may be that the configure script is messing up SIZEOF_LONG, as you mentioned.  This is, I suppose, technically "cross-compiling" since the host machine is 64-bit and I'm compiling for 32-bit.  I can't find the note in the configure script that you mentioned, however.

I did a grep for SIZEOF_LONG and got this:
main/php_config.h ...
#define SIZEOF_LONG 8
include/php/main/php_config.h ...
#define SIZEOF_LONG 8

So....indeed, the configure script does seem to have gotten confused.
 [2008-10-27 13:57 UTC] jani@php.net
Cross compiling is not supported.
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Sun Apr 20 01:02:05 2014 UTC