php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #52899 Incorrect array key cast (string to integer) when key > PHP_INT_MAX
Submitted: 2010-09-21 11:50 UTC Modified: 2010-09-29 17:37 UTC
Votes:2
Avg. Score:3.0 ± 0.0
Reproduced:0 of 1 (0.0%)
From: thorn at slonik dot sk Assigned:
Status: Duplicate Package: Scripting Engine problem
PHP Version: 5.2.14 OS: Linux 32-bit
Private report: No CVE-ID: None
 [2010-09-21 11:50 UTC] thorn at slonik dot sk
Description:
------------
When using string as an array's key which looks like integer - the key is converted to integer. That is ok for integers not bigger than PHP_INT_MAX.

But when the key is: PHP_INT_MAX < key < 3000000000 (on 32-bit system)
the key is converted to incorrect integer (it overflows :)

The key should remain string and not be converted to incorrect int.

See test script, expected and actual results.

Doc:
http://www.php.net/manual/en/language.types.array.php
A key may be either an integer or a string. If a key is the standard representation of an integer, it will be interpreted as such (i.e. "8" will be interpreted as 8, while "08" will be interpreted as "08").

Related bugs:
#51430
#48254
#52025

Test script:
---------------
$array['2000000000'] = 1; // ok
$array['2147483647'] = 2; // ok
$array['2147483648'] = 3; // incorrect
$array['2999999999'] = 4; // incorrect
$array['3000000000'] = 5; // ok again
var_dump($array);



Expected result:
----------------
array(5) {
  [2000000000]=>
  int(1)
  [2147483647]=>
  int(2)
  ["2147483648"]=>
  int(3)
  ["2999999999"]=>
  int(4)
  ["3000000000"]=>
  int(5)
}


Actual result:
--------------
array(5) {
  [2000000000]=>
  int(1)
  [2147483647]=>
  int(2)
  [-2147483648]=> // int key overflow
  int(3)
  [-1294967297]=> // int key overflow
  int(4)
  ["3000000000"]=>
  int(5)
}


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2010-09-21 13:54 UTC] cataphract@php.net
Can you give more details about your system? Are you using distro binaries?

I can't reproduce this:

root@router:~# php
<?php
$array['2147483648'] = 3;
var_dump($array);
var_dump(PHP_INT_MAX);
array(1) {
  ["2147483648"]=>
  int(3)
}
int(2147483647)
root@router:~# php -v
PHP 5.2.14 (cli) (built: Aug 18 2010 17:16:15)
Copyright (c) 1997-2010 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2010 Zend Technologies
root@router:~# uname -a
Linux router 2.4.36 #340 Sun Jul 27 20:07:55 CEST 2008 mips unknown
 [2010-09-21 15:54 UTC] thorn at slonik dot sk
I'm using gentoo linux (no distro binaries)
$ php -v
PHP 5.2.14-pl0-gentoo (cli) (built: Sep 17 2010 12:47:23) 
Copyright (c) 1997-2010 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2010 Zend Technologies
$ uname -a
Linux gloriosa 2.6.35-tuxonice-r1 #1 SMP Wed Sep 1 08:59:13 CEST 2010 i686 Intel(R) Pentium(R) 4 CPU 2.80GHz GenuineIntel GNU/Linux
 [2010-09-21 17:41 UTC] cataphract@php.net
-Status: Open +Status: Feedback
 [2010-09-21 17:41 UTC] cataphract@php.net
Can you try with a vanilla version of PHP 5.2.14?

By inspection, I don't see how this can happen. Most likely it's due to a Gentoo patch.
 [2010-09-22 09:08 UTC] thorn at slonik dot sk
-Status: Feedback +Status: Open
 [2010-09-22 09:08 UTC] thorn at slonik dot sk
I opened a gentoo bug:
http://bugs.gentoo.org/show_bug.cgi?id=338280

I tried my test script on same machine with windows and it works correctly.

I'm compiling 5.3.3 now to see if it's any different.
Will post results later.
 [2010-09-22 13:28 UTC] thorn at slonik dot sk
I tried 5.3.3 but the results are same as with 5.2.14.
 [2010-09-24 09:09 UTC] thorn at slonik dot sk
-Status: Open +Status: Closed
 [2010-09-24 09:09 UTC] thorn at slonik dot sk
Since you cannot reproduce it and I don't have access to other 32-bit machine with linux & php I close this bug.

I'd conclude with: It seems to be gentoo specific bug.
Even though they could not help as of yet. :(
 [2010-09-29 17:37 UTC] cataphract@php.net
-Status: Closed +Status: Duplicate
 [2010-09-29 17:37 UTC] cataphract@php.net
The relevant code is here:

http://lxr.php.net/xref/PHP_TRUNK/Zend/zend_hash.h#ZEND_HANDLE_NUMERIC_EX

It's not the most beautiful thing and it actually relies on undefined behavior, namely that an integer overflow will result in a wrap-around (signed integer overflow has undefined behavior as per the C standard). It relies on getting a negative number to detect the overflow.

However, it explicitly tests for the sign of the result, so it would appear it could never allow a negative number without the string starting with "-". But apparently, that check is optimized away, depending on compiler flags.

Duplicate of bug #51008.

The Debian patch is probably the way to go.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Nov 22 00:01:30 2024 UTC