[Pkg-php-commits] [php/debian-sid] Another integer overflow/underflow logic fix.
Sean Finney
seanius at debian.org
Fri Feb 26 23:25:32 UTC 2010
Once again, don't rely on undefined behavior and instead detect
the overflow/underflow conditions intelligently.
Closes: #570144
---
debian/patches/series | 1 +
debian/patches/zend_int_overflow.patch | 110 ++++++++++++++++++++++++++++++++
2 files changed, 111 insertions(+), 0 deletions(-)
create mode 100644 debian/patches/zend_int_overflow.patch
diff --git a/debian/patches/series b/debian/patches/series
index e7c1a45..4bdb1e2 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -45,3 +45,4 @@ broken_5.3_test-posix_uname.patch
shtool_mkdir_-p_-race-condition.patch
qdbm-is-usr_include_qdbm.patch
filter_validate_int.patch
+zend_int_overflow.patch
diff --git a/debian/patches/zend_int_overflow.patch b/debian/patches/zend_int_overflow.patch
new file mode 100644
index 0000000..3df7fa0
--- /dev/null
+++ b/debian/patches/zend_int_overflow.patch
@@ -0,0 +1,110 @@
+Author: Sean Finney <seanius at debian.org>
+Description: Another integer overflow/underflow logic fix.
+ Once again, don't rely on undefined behavior and instead detect
+ the overflow/underflow conditions intelligently.
+Bug: http://bugs.php.net/bug.php?id=51008
+Bug-Debian: http://bugs.debian.org/570144
+--- php.orig/Zend/zend_hash.h
++++ php/Zend/zend_hash.h
+@@ -306,9 +306,11 @@ END_EXTERN_C()
+
+ #define ZEND_HANDLE_NUMERIC(key, length, func) do { \
+ register const char *tmp = key; \
++ int negative = 0; \
+ \
+ if (*tmp == '-') { \
+ tmp++; \
++ negative = 1; \
+ } \
+ if (*tmp >= '0' && *tmp <= '9') { /* possibly a numeric index */ \
+ const char *end = key + length - 1; \
+@@ -322,19 +324,19 @@ END_EXTERN_C()
+ *tmp > '2')) { /* overflow */ \
+ break; \
+ } \
+- idx = (*tmp - '0'); \
++ idx = ((negative)?-1:1) * (*tmp - '0'); \
+ while (++tmp != end && *tmp >= '0' && *tmp <= '9') { \
+- idx = (idx * 10) + (*tmp - '0'); \
++ int digit = (*tmp - '0'); \
++ if ( (!negative) && idx <= (LONG_MAX-digit)/10 ) { \
++ idx = (idx * 10) + digit; \
++ } else if ( (negative) && idx >= (LONG_MIN+digit)/10 ) { \
++ idx = (idx * 10) - digit; \
++ } else { \
++ --tmp; /* overflow or underflow, make sure tmp != end */ \
++ break; \
++ } \
+ } \
+ if (tmp == end) { \
+- if (*key == '-') { \
+- idx = -idx; \
+- if (idx > 0) { /* overflow */ \
+- break; \
+- } \
+- } else if (idx < 0) { /* overflow */ \
+- break; \
+- } \
+ return func; \
+ } \
+ } \
+--- php.orig/Zend/tests/bug45877.phpt
++++ php/Zend/tests/bug45877.phpt
+@@ -1,23 +1,40 @@
+ --TEST--
+ Bug #45877 (Array key '2147483647' left as string)
+---INI--
+-precision=20
+ --FILE--
+ <?php
+-$keys = array(PHP_INT_MAX,
+- (string) PHP_INT_MAX,
+- (string) (-PHP_INT_MAX - 1),
+- -PHP_INT_MAX - 1,
+- (string) (PHP_INT_MAX + 1));
++$max = sprintf("%d", PHP_INT_MAX);
++switch($max) {
++case "2147483647": /* 32-bit systems */
++ $min = "-2147483648";
++ $overflow = "2147483648";
++ $underflow = "-2147483649";
++ break;
++case "9223372036854775807": /* 64-bit systems */
++ $min = "-9223372036854775808";
++ $overflow = "9223372036854775808";
++ $underflow = "-9223372036854775809";
++ break;
++default:
++ die("failed: unknown value for PHP_MAX_INT");
++ break;
++}
+
+-var_dump(array_fill_keys($keys, 1));
+-?>
+---EXPECTF--
+-array(3) {
+- [%d7]=>
+- int(1)
+- [-%d8]=>
+- int(1)
+- ["%d8"]=>
+- int(1)
++function test_value($val, $msg) {
++ $a = array($val => 1);
++ $keys = array_keys($a);
++ if ($val == $keys[0]) $result = "ok";
++ else $result = "failed ($val != $keys[0])";
++ echo "$msg: $result\n";
+ }
++
++test_value($max, "max");
++test_value($overflow, "overflow");
++test_value($min, "min");
++test_value($underflow, "underflow");
++
++?>
++--EXPECT--
++max: ok
++overflow: ok
++min: ok
++underflow: ok
--
1.6.3.3
More information about the Pkg-php-commits
mailing list