[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