Another integer overflow/underflow logic fix.
[pkg-php/php.git] / debian / patches / zend_int_overflow.patch
1 Author: Sean Finney <seanius@debian.org>
2 Description: Another integer overflow/underflow logic fix.
3  Once again, don't rely on undefined behavior and instead detect
4  the overflow/underflow conditions intelligently.
5 Bug: http://bugs.php.net/bug.php?id=51008
6 Bug-Debian: http://bugs.debian.org/570144
7 --- php.orig/Zend/zend_hash.h
8 +++ php/Zend/zend_hash.h
9 @@ -306,9 +306,11 @@ END_EXTERN_C()
10  
11  #define ZEND_HANDLE_NUMERIC(key, length, func) do {                                                    \
12         register const char *tmp = key;                                                                                 \
13 +       int negative = 0;                                                                                       \
14                                                                                                                                                         \
15         if (*tmp == '-') {                                                                                                              \
16                 tmp++;                                                                                                                          \
17 +               negative = 1;                                                                                                                           \
18         }                                                                                                                                               \
19         if (*tmp >= '0' && *tmp <= '9') { /* possibly a numeric index */                \
20                 const char *end = key + length - 1;                                                                     \
21 @@ -322,19 +324,19 @@ END_EXTERN_C()
22                      *tmp > '2')) { /* overflow */                                                                      \
23                         break;                                                                                                                  \
24                 }                                                                                                                                       \
25 -               idx = (*tmp - '0');                                                                                                     \
26 +               idx = ((negative)?-1:1) * (*tmp - '0');                                                                                                 \
27                 while (++tmp != end && *tmp >= '0' && *tmp <= '9') {                            \
28 -                       idx = (idx * 10) + (*tmp - '0');                                                                \
29 +                       int digit = (*tmp - '0');                                                               \
30 +                       if ( (!negative) && idx <= (LONG_MAX-digit)/10 ) {                                      \
31 +                               idx = (idx * 10) + digit;                                                               \
32 +                       } else if ( (negative) && idx >= (LONG_MIN+digit)/10 ) {                                \
33 +                               idx = (idx * 10) - digit;                                                               \
34 +                       } else {                                                                                                                                \
35 +                               --tmp; /* overflow or underflow, make sure tmp != end */                        \
36 +                               break;                                                                                                                          \
37 +                       }                                                                                                                               \
38                 }                                                                                                                                       \
39                 if (tmp == end) {                                                                                                       \
40 -                       if (*key == '-') {                                                                                              \
41 -                               idx = -idx;                                                                                                     \
42 -                               if (idx > 0) { /* overflow */                                                           \
43 -                                       break;                                                                                                  \
44 -                               }                                                                                                                       \
45 -                       } else if (idx < 0) { /* overflow */                                                    \
46 -                               break;                                                                                                          \
47 -                       }                                                                                                                               \
48                         return func;                                                                                                    \
49                 }                                                                                                                                       \
50         }                                                                                                                                               \
51 --- php.orig/Zend/tests/bug45877.phpt
52 +++ php/Zend/tests/bug45877.phpt
53 @@ -1,23 +1,40 @@
54  --TEST--
55  Bug #45877 (Array key '2147483647' left as string)
56 ---INI--
57 -precision=20
58  --FILE--
59  <?php
60 -$keys = array(PHP_INT_MAX,
61 -       (string) PHP_INT_MAX,
62 -       (string) (-PHP_INT_MAX - 1),
63 -       -PHP_INT_MAX - 1,
64 -       (string) (PHP_INT_MAX + 1));
65 +$max = sprintf("%d", PHP_INT_MAX);
66 +switch($max) {
67 +case "2147483647": /* 32-bit systems */
68 +       $min = "-2147483648";
69 +       $overflow = "2147483648";
70 +       $underflow = "-2147483649";
71 +       break;
72 +case "9223372036854775807": /* 64-bit systems */
73 +       $min = "-9223372036854775808";
74 +       $overflow = "9223372036854775808";
75 +       $underflow = "-9223372036854775809";
76 +       break;
77 +default:
78 +       die("failed: unknown value for PHP_MAX_INT");
79 +       break;
80 +}
81  
82 -var_dump(array_fill_keys($keys, 1));
83 -?>
84 ---EXPECTF--
85 -array(3) {
86 -  [%d7]=>
87 -  int(1)
88 -  [-%d8]=>
89 -  int(1)
90 -  ["%d8"]=>
91 -  int(1)
92 +function test_value($val, $msg) {
93 +       $a = array($val => 1);
94 +       $keys = array_keys($a);
95 +       if ($val == $keys[0]) $result = "ok";
96 +       else $result = "failed ($val != $keys[0])";
97 +       echo "$msg: $result\n";
98  }
99 +
100 +test_value($max, "max");
101 +test_value($overflow, "overflow");
102 +test_value($min, "min");
103 +test_value($underflow, "underflow");
104 +
105 +?>
106 +--EXPECT--
107 +max: ok
108 +overflow: ok
109 +min: ok
110 +underflow: ok