mirror of
https://github.com/php/php-src.git
synced 2025-08-18 15:08:55 +02:00
Update the JSON parser with that on json.org, biggest change here is code readability. Less magic numbers in the state table.
Add missing reflection information to json_encode() Fixes bug #45791 with 0e0 not being supported as a value Error values are stored when encountered during parsing
This commit is contained in:
parent
c7a56d604b
commit
cae85c867a
3 changed files with 636 additions and 599 deletions
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,24 @@
|
||||||
/* JSON_checker.h */
|
/* JSON_parser.h */
|
||||||
|
|
||||||
|
#ifndef JSON_PARSER_H
|
||||||
|
#define JSON_PARSER_H
|
||||||
|
|
||||||
#include "php.h"
|
#include "php.h"
|
||||||
#include "ext/standard/php_smart_str.h"
|
#include "ext/standard/php_smart_str.h"
|
||||||
|
|
||||||
extern int JSON_parser(zval *z, unsigned short p[], int length, int assoc TSRMLS_DC);
|
#define JSON_PARSER_MAX_DEPTH 512
|
||||||
|
|
||||||
|
typedef struct JSON_parser_struct {
|
||||||
|
int state;
|
||||||
|
int depth;
|
||||||
|
int top;
|
||||||
|
int error;
|
||||||
|
int* stack;
|
||||||
|
zval *the_zstack[JSON_PARSER_MAX_DEPTH];
|
||||||
|
|
||||||
|
} * JSON_parser;
|
||||||
|
|
||||||
|
extern JSON_parser new_JSON_parser(int depth);
|
||||||
|
extern int parse_JSON(JSON_parser jp, zval *z, unsigned short utf16_json[], int length, int assoc TSRMLS_DC);
|
||||||
|
extern int free_JSON_parser(JSON_parser jp);
|
||||||
|
#endif
|
||||||
|
|
|
@ -475,7 +475,7 @@ static PHP_FUNCTION(json_encode)
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ proto mixed json_decode(string json [, bool assoc]) U
|
/* {{{ proto mixed json_decode(string json [, bool assoc [, long depth]]) U
|
||||||
Decodes the JSON representation into a PHP value */
|
Decodes the JSON representation into a PHP value */
|
||||||
static PHP_FUNCTION(json_decode)
|
static PHP_FUNCTION(json_decode)
|
||||||
{
|
{
|
||||||
|
@ -483,10 +483,12 @@ static PHP_FUNCTION(json_decode)
|
||||||
int str_len, utf16_len;
|
int str_len, utf16_len;
|
||||||
zend_uchar str_type;
|
zend_uchar str_type;
|
||||||
zend_bool assoc = 0; /* return JS objects as PHP objects by default */
|
zend_bool assoc = 0; /* return JS objects as PHP objects by default */
|
||||||
|
long depth = JSON_PARSER_MAX_DEPTH;
|
||||||
zval *z;
|
zval *z;
|
||||||
unsigned short *utf16;
|
unsigned short *utf16;
|
||||||
|
JSON_parser jp;
|
||||||
|
|
||||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t|b", &str, &str_len, &str_type, &assoc) == FAILURE) {
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t|bl", &str, &str_len, &str_type, &assoc, &depth) == FAILURE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -509,14 +511,15 @@ static PHP_FUNCTION(json_decode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ALLOC_INIT_ZVAL(z);
|
/* can be removed once we remove the max depth limit */
|
||||||
if (JSON_parser(z, utf16, utf16_len, assoc TSRMLS_CC)) {
|
if (depth <= 0 || depth > JSON_PARSER_MAX_DEPTH) {
|
||||||
*return_value = *z;
|
depth = JSON_PARSER_MAX_DEPTH;
|
||||||
FREE_ZVAL(z);
|
}
|
||||||
|
|
||||||
if (str_type == IS_STRING) {
|
ALLOC_INIT_ZVAL(z);
|
||||||
efree(utf16);
|
jp = new_JSON_parser(depth);
|
||||||
}
|
if (parse_JSON(jp, z, utf16, utf16_len, assoc TSRMLS_CC)) {
|
||||||
|
*return_value = *z;
|
||||||
}
|
}
|
||||||
else if (str_type == IS_STRING)
|
else if (str_type == IS_STRING)
|
||||||
{
|
{
|
||||||
|
@ -525,26 +528,25 @@ static PHP_FUNCTION(json_decode)
|
||||||
long p;
|
long p;
|
||||||
|
|
||||||
zval_dtor(z);
|
zval_dtor(z);
|
||||||
FREE_ZVAL(z);
|
RETVAL_NULL();
|
||||||
efree(utf16);
|
|
||||||
|
|
||||||
if (str_len == 4) {
|
if (str_len == 4) {
|
||||||
if (!strcasecmp(str.s, "null")) {
|
if (!strcasecmp(str.s, "null")) {
|
||||||
RETURN_NULL();
|
RETVAL_NULL();
|
||||||
} else if (!strcasecmp(str.s, "true")) {
|
} else if (!strcasecmp(str.s, "true")) {
|
||||||
RETURN_BOOL(1);
|
RETVAL_BOOL(1);
|
||||||
}
|
}
|
||||||
} else if (str_len == 5 && !strcasecmp(str.s, "false")) {
|
} else if (str_len == 5 && !strcasecmp(str.s, "false")) {
|
||||||
RETURN_BOOL(0);
|
RETVAL_BOOL(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((type = is_numeric_string(str.s, str_len, &p, &d, 0)) != 0) {
|
if ((type = is_numeric_string(str.s, str_len, &p, &d, 0)) != 0) {
|
||||||
if (type == IS_LONG) {
|
if (type == IS_LONG) {
|
||||||
RETURN_LONG(p);
|
RETVAL_LONG(p);
|
||||||
} else if (type == IS_DOUBLE) {
|
} else if (type == IS_DOUBLE) {
|
||||||
RETURN_DOUBLE(d);
|
RETVAL_DOUBLE(d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RETURN_NULL();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -553,26 +555,32 @@ static PHP_FUNCTION(json_decode)
|
||||||
long p;
|
long p;
|
||||||
|
|
||||||
zval_dtor(z);
|
zval_dtor(z);
|
||||||
FREE_ZVAL(z);
|
RETVAL_NULL();
|
||||||
|
|
||||||
if (str_len == 4) {
|
if (str_len == 4) {
|
||||||
if (ZEND_U_CASE_EQUAL(IS_UNICODE, str, str_len, "null", sizeof("null")-1)) {
|
if (ZEND_U_CASE_EQUAL(IS_UNICODE, str, str_len, "null", sizeof("null")-1)) {
|
||||||
RETURN_NULL();
|
RETVAL_NULL();
|
||||||
} else if (ZEND_U_CASE_EQUAL(IS_UNICODE, str, str_len, "true", sizeof("true")-1)) {
|
} else if (ZEND_U_CASE_EQUAL(IS_UNICODE, str, str_len, "true", sizeof("true")-1)) {
|
||||||
RETURN_BOOL(1);
|
RETVAL_BOOL(1);
|
||||||
}
|
}
|
||||||
} else if (str_len == 5 && ZEND_U_CASE_EQUAL(IS_UNICODE, str, str_len, "false", sizeof("false")-1)) {
|
} else if (str_len == 5 && ZEND_U_CASE_EQUAL(IS_UNICODE, str, str_len, "false", sizeof("false")-1)) {
|
||||||
RETURN_BOOL(0);
|
RETVAL_BOOL(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((type = is_numeric_unicode(str.u, str_len, &p, &d, 0)) != 0) {
|
if ((type = is_numeric_unicode(str.u, str_len, &p, &d, 0)) != 0) {
|
||||||
if (type == IS_LONG) {
|
if (type == IS_LONG) {
|
||||||
RETURN_LONG(p);
|
RETVAL_LONG(p);
|
||||||
} else if (type == IS_DOUBLE) {
|
} else if (type == IS_DOUBLE) {
|
||||||
RETURN_DOUBLE(d);
|
RETVAL_DOUBLE(d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RETURN_NULL();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FREE_ZVAL(z);
|
||||||
|
if (str_type == IS_STRING) {
|
||||||
|
efree(utf16);
|
||||||
|
}
|
||||||
|
free_JSON_parser(jp);
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue