mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Add initial failure checking for json_encode
This commit is contained in:
parent
0e709fe42d
commit
12a8c3f6e7
3 changed files with 57 additions and 43 deletions
|
@ -186,9 +186,7 @@ static PHP_MINFO_FUNCTION(json)
|
|||
|
||||
PHP_JSON_API int php_json_encode(smart_str *buf, zval *val, int options) /* {{{ */
|
||||
{
|
||||
php_json_encode_zval(buf, val, options);
|
||||
|
||||
return JSON_G(error_code) > 0 ? FAILURE : SUCCESS;
|
||||
return php_json_encode_zval(buf, val, options);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
static const char digits[] = "0123456789abcdef";
|
||||
|
||||
static void php_json_escape_string(smart_str *buf, char *s, size_t len, int options);
|
||||
static int php_json_escape_string(smart_str *buf, char *s, size_t len, int options);
|
||||
|
||||
static int php_json_determine_array_type(zval *val) /* {{{ */
|
||||
{
|
||||
|
@ -108,7 +108,7 @@ static inline void php_json_encode_double(smart_str *buf, double d, int options)
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
static void php_json_encode_array(smart_str *buf, zval *val, int options) /* {{{ */
|
||||
static int php_json_encode_array(smart_str *buf, zval *val, int options) /* {{{ */
|
||||
{
|
||||
int i, r, need_comma = 0;
|
||||
HashTable *myht;
|
||||
|
@ -124,7 +124,7 @@ static void php_json_encode_array(smart_str *buf, zval *val, int options) /* {{{
|
|||
if (myht && ZEND_HASH_GET_APPLY_COUNT(myht) > 1) {
|
||||
JSON_G(error_code) = PHP_JSON_ERROR_RECURSION;
|
||||
smart_str_appendl(buf, "null", 4);
|
||||
return;
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (r == PHP_JSON_OUTPUT_ARRAY) {
|
||||
|
@ -159,7 +159,6 @@ static void php_json_encode_array(smart_str *buf, zval *val, int options) /* {{{
|
|||
|
||||
php_json_pretty_print_char(buf, options, '\n');
|
||||
php_json_pretty_print_indent(buf, options);
|
||||
php_json_encode(buf, data, options);
|
||||
} else if (r == PHP_JSON_OUTPUT_OBJECT) {
|
||||
if (key) {
|
||||
if (ZSTR_VAL(key)[0] == '\0' && ZSTR_LEN(key) > 0 && Z_TYPE_P(val) == IS_OBJECT) {
|
||||
|
@ -180,11 +179,6 @@ static void php_json_encode_array(smart_str *buf, zval *val, int options) /* {{{
|
|||
php_json_pretty_print_indent(buf, options);
|
||||
|
||||
php_json_escape_string(buf, ZSTR_VAL(key), ZSTR_LEN(key), options & ~PHP_JSON_NUMERIC_CHECK);
|
||||
smart_str_appendc(buf, ':');
|
||||
|
||||
php_json_pretty_print_char(buf, options, ' ');
|
||||
|
||||
php_json_encode(buf, data, options);
|
||||
} else {
|
||||
if (need_comma) {
|
||||
smart_str_appendc(buf, ',');
|
||||
|
@ -198,12 +192,14 @@ static void php_json_encode_array(smart_str *buf, zval *val, int options) /* {{{
|
|||
smart_str_appendc(buf, '"');
|
||||
smart_str_append_long(buf, (zend_long) index);
|
||||
smart_str_appendc(buf, '"');
|
||||
smart_str_appendc(buf, ':');
|
||||
|
||||
php_json_pretty_print_char(buf, options, ' ');
|
||||
|
||||
php_json_encode(buf, data, options);
|
||||
}
|
||||
|
||||
smart_str_appendc(buf, ':');
|
||||
php_json_pretty_print_char(buf, options, ' ');
|
||||
}
|
||||
|
||||
if (php_json_encode(buf, data, options) == FAILURE && (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) {
|
||||
|
@ -214,6 +210,9 @@ static void php_json_encode_array(smart_str *buf, zval *val, int options) /* {{{
|
|||
|
||||
if (JSON_G(encoder_depth) > JSON_G(encode_max_depth)) {
|
||||
JSON_G(error_code) = PHP_JSON_ERROR_DEPTH;
|
||||
if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
--JSON_G(encoder_depth);
|
||||
|
||||
|
@ -228,6 +227,8 @@ static void php_json_encode_array(smart_str *buf, zval *val, int options) /* {{{
|
|||
} else {
|
||||
smart_str_appendc(buf, '}');
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -268,7 +269,7 @@ static int php_json_utf8_to_utf16(unsigned short *utf16, char utf8[], size_t len
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
static void php_json_escape_string(smart_str *buf, char *s, size_t len, int options) /* {{{ */
|
||||
static int php_json_escape_string(smart_str *buf, char *s, size_t len, int options) /* {{{ */
|
||||
{
|
||||
int status;
|
||||
unsigned int us;
|
||||
|
@ -276,7 +277,7 @@ static void php_json_escape_string(smart_str *buf, char *s, size_t len, int opti
|
|||
|
||||
if (len == 0) {
|
||||
smart_str_appendl(buf, "\"\"", 2);
|
||||
return;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
if (options & PHP_JSON_NUMERIC_CHECK) {
|
||||
|
@ -287,10 +288,10 @@ static void php_json_escape_string(smart_str *buf, char *s, size_t len, int opti
|
|||
if ((type = is_numeric_string(s, len, &p, &d, 0)) != 0) {
|
||||
if (type == IS_LONG) {
|
||||
smart_str_append_long(buf, p);
|
||||
return;
|
||||
return SUCCESS;
|
||||
} else if (type == IS_DOUBLE && php_json_is_valid_double(d)) {
|
||||
php_json_encode_double(buf, d, options);
|
||||
return;
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,8 +301,10 @@ static void php_json_escape_string(smart_str *buf, char *s, size_t len, int opti
|
|||
/* validate UTF-8 string first */
|
||||
if (php_json_utf8_to_utf16(NULL, s, len) < 0) {
|
||||
JSON_G(error_code) = PHP_JSON_ERROR_UTF8;
|
||||
smart_str_appendl(buf, "null", 4);
|
||||
return;
|
||||
if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
|
||||
smart_str_appendl(buf, "null", 4);
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -322,8 +325,10 @@ static void php_json_escape_string(smart_str *buf, char *s, size_t len, int opti
|
|||
ZSTR_LEN(buf->s) = checkpoint;
|
||||
}
|
||||
JSON_G(error_code) = PHP_JSON_ERROR_UTF8;
|
||||
smart_str_appendl(buf, "null", 4);
|
||||
return;
|
||||
if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
|
||||
smart_str_appendl(buf, "null", 4);
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
/* Escape U+2028/U+2029 line terminators, UNLESS both
|
||||
JSON_UNESCAPED_UNICODE and
|
||||
|
@ -442,10 +447,12 @@ static void php_json_escape_string(smart_str *buf, char *s, size_t len, int opti
|
|||
} while (pos < len);
|
||||
|
||||
smart_str_appendc(buf, '"');
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static void php_json_encode_serializable_object(smart_str *buf, zval *val, int options) /* {{{ */
|
||||
static int php_json_encode_serializable_object(smart_str *buf, zval *val, int options) /* {{{ */
|
||||
{
|
||||
zend_class_entry *ce = Z_OBJCE_P(val);
|
||||
zval retval, fname;
|
||||
|
@ -460,8 +467,10 @@ static void php_json_encode_serializable_object(smart_str *buf, zval *val, int o
|
|||
|
||||
if (myht && ZEND_HASH_GET_APPLY_COUNT(myht) > 1) {
|
||||
JSON_G(error_code) = PHP_JSON_ERROR_RECURSION;
|
||||
smart_str_appendl(buf, "null", 4);
|
||||
return;
|
||||
if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
|
||||
smart_str_appendl(buf, "null", 4);
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
|
||||
|
@ -470,9 +479,12 @@ static void php_json_encode_serializable_object(smart_str *buf, zval *val, int o
|
|||
origin_error_code = JSON_G(error_code);
|
||||
if (FAILURE == call_user_function_ex(EG(function_table), val, &fname, &retval, 0, NULL, 1, NULL) || Z_TYPE(retval) == IS_UNDEF) {
|
||||
zend_throw_exception_ex(NULL, 0, "Failed calling %s::jsonSerialize()", ZSTR_VAL(ce->name));
|
||||
smart_str_appendl(buf, "null", sizeof("null") - 1);
|
||||
zval_ptr_dtor(&fname);
|
||||
return;
|
||||
|
||||
if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
|
||||
smart_str_appendl(buf, "null", 4);
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
JSON_G(error_code) = origin_error_code;
|
||||
|
@ -480,8 +492,11 @@ static void php_json_encode_serializable_object(smart_str *buf, zval *val, int o
|
|||
/* Error already raised */
|
||||
zval_ptr_dtor(&retval);
|
||||
zval_ptr_dtor(&fname);
|
||||
smart_str_appendl(buf, "null", sizeof("null") - 1);
|
||||
return;
|
||||
|
||||
if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
|
||||
smart_str_appendl(buf, "null", 4);
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if ((Z_TYPE(retval) == IS_OBJECT) &&
|
||||
|
@ -495,10 +510,12 @@ static void php_json_encode_serializable_object(smart_str *buf, zval *val, int o
|
|||
|
||||
zval_ptr_dtor(&retval);
|
||||
zval_ptr_dtor(&fname);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
void php_json_encode_zval(smart_str *buf, zval *val, int options) /* {{{ */
|
||||
int php_json_encode_zval(smart_str *buf, zval *val, int options) /* {{{ */
|
||||
{
|
||||
again:
|
||||
switch (Z_TYPE_P(val))
|
||||
|
@ -528,18 +545,15 @@ again:
|
|||
break;
|
||||
|
||||
case IS_STRING:
|
||||
php_json_escape_string(buf, Z_STRVAL_P(val), Z_STRLEN_P(val), options);
|
||||
break;
|
||||
return php_json_escape_string(buf, Z_STRVAL_P(val), Z_STRLEN_P(val), options);
|
||||
|
||||
case IS_OBJECT:
|
||||
if (instanceof_function(Z_OBJCE_P(val), php_json_serializable_ce)) {
|
||||
php_json_encode_serializable_object(buf, val, options);
|
||||
break;
|
||||
return php_json_encode_serializable_object(buf, val, options);
|
||||
}
|
||||
/* fallthrough -- Non-serializable object */
|
||||
case IS_ARRAY:
|
||||
php_json_encode_array(buf, val, options);
|
||||
break;
|
||||
return php_json_encode_array(buf, val, options);
|
||||
|
||||
case IS_REFERENCE:
|
||||
val = Z_REFVAL_P(val);
|
||||
|
@ -547,11 +561,13 @@ again:
|
|||
|
||||
default:
|
||||
JSON_G(error_code) = PHP_JSON_ERROR_UNSUPPORTED_TYPE;
|
||||
smart_str_appendl(buf, "null", 4);
|
||||
break;
|
||||
if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
|
||||
smart_str_appendl(buf, "null", 4);
|
||||
}
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
return;
|
||||
return SUCCESS;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
|
|
@ -22,6 +22,6 @@
|
|||
#include "php.h"
|
||||
#include "zend_smart_str.h"
|
||||
|
||||
void php_json_encode_zval(smart_str *buf, zval *val, int options);
|
||||
int php_json_encode_zval(smart_str *buf, zval *val, int options);
|
||||
|
||||
#endif /* PHP_JSON_ENCODER_H */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue