summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntony Dovgal <tony2001@php.net>2007-04-22 21:33:10 +0000
committerAntony Dovgal <tony2001@php.net>2007-04-22 21:33:10 +0000
commitf6cef916bc36e60c3c92e09e9264a0a28d24a30d (patch)
treea0db47034fe37b3b652ba0171803c6f580822310
parente910699347be2deeaa1fada69b183bdace1d962a (diff)
downloadphp-git-f6cef916bc36e60c3c92e09e9264a0a28d24a30d.tar.gz
MFH: fix #41118 (PHP does not handle overflow of octal integers)
-rw-r--r--Zend/tests/hex_overflow_32bit.phpt27
-rw-r--r--Zend/tests/oct_overflow_32bit.phpt29
-rw-r--r--Zend/zend_language_scanner.l6
-rw-r--r--Zend/zend_strtod.c28
-rw-r--r--Zend/zend_strtod.h1
5 files changed, 90 insertions, 1 deletions
diff --git a/Zend/tests/hex_overflow_32bit.phpt b/Zend/tests/hex_overflow_32bit.phpt
new file mode 100644
index 0000000000..34306ccc53
--- /dev/null
+++ b/Zend/tests/hex_overflow_32bit.phpt
@@ -0,0 +1,27 @@
+--TEST--
+testing integer overflow (32bit)
+--SKIPIF--
+<?php if (PHP_INT_SIZE != 4) die("skip this test is for 32bit platform only"); ?>
+--FILE--
+<?php
+
+$doubles = array(
+ 0x1736123FFFAAA,
+ 0XFFFFFFFFFFFFFFFFFF,
+ 0xAAAAAAAAAAAAAAEEEEEEEEEBBB,
+ 0x66666666666666666777777,
+ );
+
+foreach ($doubles as $d) {
+ $l = $d;
+ var_dump($l);
+}
+
+echo "Done\n";
+?>
+--EXPECTF--
+float(4083360297110%d)
+float(4.7223664828%dE+21)
+float(1.3521606402%dE+31)
+float(1.9807040628%dE+27)
+Done
diff --git a/Zend/tests/oct_overflow_32bit.phpt b/Zend/tests/oct_overflow_32bit.phpt
new file mode 100644
index 0000000000..77befbaa7a
--- /dev/null
+++ b/Zend/tests/oct_overflow_32bit.phpt
@@ -0,0 +1,29 @@
+--TEST--
+testing integer overflow (32bit)
+--SKIPIF--
+<?php if (PHP_INT_SIZE != 4) die("skip this test is for 32bit platform only"); ?>
+--FILE--
+<?php
+
+$doubles = array(
+ 076545676543223,
+ 032325463734,
+ 077777797777777,
+ 07777777777777977777777777,
+ 03333333333333382222222222222,
+ );
+
+foreach ($doubles as $d) {
+ $l = (double)$d;
+ var_dump($l);
+}
+
+echo "Done\n";
+?>
+--EXPECTF--
+float(4308640384%d)
+float(3545655%d)
+float(262143)
+float(549755813%d)
+float(1884877076%d)
+Done
diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l
index bf76d9773c..ca0912323f 100644
--- a/Zend/zend_language_scanner.l
+++ b/Zend/zend_language_scanner.l
@@ -1247,7 +1247,11 @@ NEWLINE ("\r"|"\n"|"\r\n")
errno = 0;
zendlval->value.lval = strtol(yytext, NULL, 0);
if (errno == ERANGE) { /* Overflow */
- zendlval->value.dval = zend_strtod(yytext, NULL);
+ if (yytext[0] == '0') { /* octal overflow */
+ zendlval->value.dval = zend_oct_strtod(yytext, NULL);
+ } else {
+ zendlval->value.dval = zend_strtod(yytext, NULL);
+ }
zendlval->type = IS_DOUBLE;
return T_DNUMBER;
}
diff --git a/Zend/zend_strtod.c b/Zend/zend_strtod.c
index 94d1383aa2..49b591da14 100644
--- a/Zend/zend_strtod.c
+++ b/Zend/zend_strtod.c
@@ -2604,6 +2604,34 @@ ZEND_API double zend_hex_strtod(const char *str, char **endptr)
return value;
}
+ZEND_API double zend_oct_strtod(const char *str, char **endptr)
+{
+ const char *s = str;
+ char c;
+ double value = 0;
+ int any = 0;
+
+ /* skip leading zero */
+ s++;
+
+ while ((c = *s++)) {
+ if (c > '7') {
+ /* break and return the current value if the number is not well-formed
+ * that's what Linux strtol() does
+ */
+ break;
+ }
+ value = value * 8 + c - '0';
+ any = 1;
+ }
+
+ if (endptr != NULL) {
+ *endptr = (char *)(any ? s - 1 : str);
+ }
+
+ return value;
+}
+
/*
* Local variables:
* tab-width: 4
diff --git a/Zend/zend_strtod.h b/Zend/zend_strtod.h
index 2dfe5a1a60..f4e066a58a 100644
--- a/Zend/zend_strtod.h
+++ b/Zend/zend_strtod.h
@@ -29,6 +29,7 @@ ZEND_API void zend_freedtoa(char *s);
ZEND_API char * zend_dtoa(double _d, int mode, int ndigits, int *decpt, int *sign, char **rve);
ZEND_API double zend_strtod(const char *s00, char **se);
ZEND_API double zend_hex_strtod(const char *str, char **endptr);
+ZEND_API double zend_oct_strtod(const char *str, char **endptr);
ZEND_API int zend_startup_strtod(void);
ZEND_API int zend_shutdown_strtod(void);
END_EXTERN_C()