@@ -682,7 +682,7 @@ PHP_JSON_API void php_json_decode_ex(zval *return_value, char *str, int str_len,
682
682
else
683
683
{
684
684
double d ;
685
- int type ;
685
+ int type , overflow_info ;
686
686
long p ;
687
687
688
688
RETVAL_NULL ();
@@ -698,11 +698,36 @@ PHP_JSON_API void php_json_decode_ex(zval *return_value, char *str, int str_len,
698
698
RETVAL_BOOL (0 );
699
699
}
700
700
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 ) {
702
702
if (type == IS_LONG ) {
703
703
RETVAL_LONG (p );
704
704
} 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
+ }
706
731
}
707
732
}
708
733
0 commit comments