]> granicus.if.org Git - php/commitdiff
Alter php_json_decode_ex() to respect JSON_BIGINT_AS_STRING for bare numbers.
authorAdam Harvey <aharvey@php.net>
Tue, 11 Dec 2012 11:51:30 +0000 (19:51 +0800)
committerAdam Harvey <aharvey@php.net>
Tue, 11 Dec 2012 11:51:30 +0000 (19:51 +0800)
Fixes bug #63737 (json_decode does not properly decode with options parameter).

NEWS
ext/json/json.c
ext/json/tests/bug63737.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 29b62a3955c478086210cc834e5820195085fb82..0504472ae11d30b25bb79fd31cfeddba80de4a50 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,10 @@ PHP                                                                        NEWS
 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 ?? ??? 2012, PHP 5.4.11
 
+- JSON:
+  . Fixed bug #63737 (json_decode does not properly decode with options
+    parameter). (Adam)
+
 ?? ??? 2012, PHP 5.4.10
 
 - Core:
index fb01529711adc8fdec481df7fda469f201501dda..e26c369589cc3c42881ee32ccbf57dfe06465ee6 100644 (file)
@@ -682,7 +682,7 @@ PHP_JSON_API void php_json_decode_ex(zval *return_value, char *str, int str_len,
        else
        {
                double d;
-               int type;
+               int type, overflow_info;
                long p;
 
                RETVAL_NULL();
@@ -698,11 +698,36 @@ PHP_JSON_API void php_json_decode_ex(zval *return_value, char *str, int str_len,
                        RETVAL_BOOL(0);
                }
 
-               if ((type = is_numeric_string(str, str_len, &p, &d, 0)) != 0) {
+               if ((type = is_numeric_string_ex(str, str_len, &p, &d, 0, &overflow_info)) != 0) {
                        if (type == IS_LONG) {
                                RETVAL_LONG(p);
                        } else if (type == IS_DOUBLE) {
-                               RETVAL_DOUBLE(d);
+                               if (options & PHP_JSON_BIGINT_AS_STRING && overflow_info) {
+                                       /* Within an object or array, a numeric literal is assumed
+                                        * to be an integer if and only if it's entirely made up of
+                                        * digits (exponent notation will result in the number
+                                        * being treated as a double). We'll match that behaviour
+                                        * here. */
+                                       int i;
+                                       zend_bool is_float = 0;
+
+                                       for (i = (str[0] == '-' ? 1 : 0); i < str_len; i++) {
+                                               /* Not using isdigit() because it's locale specific,
+                                                * but we expect JSON input to always be UTF-8. */
+                                               if (str[i] < '0' || str[i] > '9') {
+                                                       is_float = 1;
+                                                       break;
+                                               }
+                                       }
+
+                                       if (is_float) {
+                                               RETVAL_DOUBLE(d);
+                                       } else {
+                                               RETVAL_STRINGL(str, str_len, 1);
+                                       }
+                               } else {
+                                       RETVAL_DOUBLE(d);
+                               }
                        }
                }
 
diff --git a/ext/json/tests/bug63737.phpt b/ext/json/tests/bug63737.phpt
new file mode 100644 (file)
index 0000000..1fb06d4
--- /dev/null
@@ -0,0 +1,32 @@
+--TEST--
+Bug #63737 (json_decode does not properly decode with options parameter)
+--SKIPIF--
+<?php if (!extension_loaded("json")) print "skip"; ?>
+--FILE--
+<?php
+function decode($json) {
+    $x = json_decode($json);
+    var_dump($x);
+    $x = json_decode($json, false, 512, JSON_BIGINT_AS_STRING);
+    var_dump($x);
+}
+
+decode('123456789012345678901234567890');
+decode('-123456789012345678901234567890');
+
+// This shouldn't affect floats, but let's check that.
+decode('123456789012345678901234567890.1');
+decode('-123456789012345678901234567890.1');
+
+echo "Done\n";
+?>
+--EXPECT--
+float(1.2345678901235E+29)
+string(30) "123456789012345678901234567890"
+float(-1.2345678901235E+29)
+string(31) "-123456789012345678901234567890"
+float(1.2345678901235E+29)
+float(1.2345678901235E+29)
+float(-1.2345678901235E+29)
+float(-1.2345678901235E+29)
+Done