Skip to content

Commit 2d1694d

Browse files
committed
Alter php_json_decode_ex() to respect JSON_BIGINT_AS_STRING for bare numbers.
Fixes bug #63737 (json_decode does not properly decode with options parameter).
1 parent 95fd52f commit 2d1694d

File tree

3 files changed

+64
-3
lines changed

3 files changed

+64
-3
lines changed

NEWS

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? 2012, PHP 5.4.11
44

5+
- JSON:
6+
. Fixed bug #63737 (json_decode does not properly decode with options
7+
parameter). (Adam)
8+
59
?? ??? 2012, PHP 5.4.10
610

711
- Core:

ext/json/json.c

+28-3
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,7 @@ PHP_JSON_API void php_json_decode_ex(zval *return_value, char *str, int str_len,
682682
else
683683
{
684684
double d;
685-
int type;
685+
int type, overflow_info;
686686
long p;
687687

688688
RETVAL_NULL();
@@ -698,11 +698,36 @@ PHP_JSON_API void php_json_decode_ex(zval *return_value, char *str, int str_len,
698698
RETVAL_BOOL(0);
699699
}
700700

701-
if ((type = is_numeric_string(str, str_len, &p, &d, 0)) != 0) {
701+
if ((type = is_numeric_string_ex(str, str_len, &p, &d, 0, &overflow_info)) != 0) {
702702
if (type == IS_LONG) {
703703
RETVAL_LONG(p);
704704
} else if (type == IS_DOUBLE) {
705-
RETVAL_DOUBLE(d);
705+
if (options & PHP_JSON_BIGINT_AS_STRING && overflow_info) {
706+
/* Within an object or array, a numeric literal is assumed
707+
* to be an integer if and only if it's entirely made up of
708+
* digits (exponent notation will result in the number
709+
* being treated as a double). We'll match that behaviour
710+
* here. */
711+
int i;
712+
zend_bool is_float = 0;
713+
714+
for (i = (str[0] == '-' ? 1 : 0); i < str_len; i++) {
715+
/* Not using isdigit() because it's locale specific,
716+
* but we expect JSON input to always be UTF-8. */
717+
if (str[i] < '0' || str[i] > '9') {
718+
is_float = 1;
719+
break;
720+
}
721+
}
722+
723+
if (is_float) {
724+
RETVAL_DOUBLE(d);
725+
} else {
726+
RETVAL_STRINGL(str, str_len, 1);
727+
}
728+
} else {
729+
RETVAL_DOUBLE(d);
730+
}
706731
}
707732
}
708733

ext/json/tests/bug63737.phpt

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
Bug #63737 (json_decode does not properly decode with options parameter)
3+
--SKIPIF--
4+
<?php if (!extension_loaded("json")) print "skip"; ?>
5+
--FILE--
6+
<?php
7+
function decode($json) {
8+
$x = json_decode($json);
9+
var_dump($x);
10+
$x = json_decode($json, false, 512, JSON_BIGINT_AS_STRING);
11+
var_dump($x);
12+
}
13+
14+
decode('123456789012345678901234567890');
15+
decode('-123456789012345678901234567890');
16+
17+
// This shouldn't affect floats, but let's check that.
18+
decode('123456789012345678901234567890.1');
19+
decode('-123456789012345678901234567890.1');
20+
21+
echo "Done\n";
22+
?>
23+
--EXPECT--
24+
float(1.2345678901235E+29)
25+
string(30) "123456789012345678901234567890"
26+
float(-1.2345678901235E+29)
27+
string(31) "-123456789012345678901234567890"
28+
float(1.2345678901235E+29)
29+
float(1.2345678901235E+29)
30+
float(-1.2345678901235E+29)
31+
float(-1.2345678901235E+29)
32+
Done

0 commit comments

Comments
 (0)