summaryrefslogtreecommitdiff
path: root/ext/json/json.c
diff options
context:
space:
mode:
authorNikita Popov <nikic@php.net>2012-06-23 20:46:27 +0200
committerNikita Popov <nikic@php.net>2012-06-23 20:51:52 +0200
commit84fe2cc890e49f40bac7c3ba74b3cfc6dc4cef2f (patch)
tree4b07a64554232483751acac245a9eb43154d0ecc /ext/json/json.c
parentcc90ac54beb7359e5a3210261ce09159bbc43e92 (diff)
downloadphp-git-84fe2cc890e49f40bac7c3ba74b3cfc6dc4cef2f.tar.gz
Improve json_encode error handling
json_encode() now returns bool(false) for all possible errors, throws the respective warning and also sets the respective json_last_error() error code. Three new error codes have been added: * JSON_ERROR_RECURSION * JSON_ERROR_INF_OR_NAN * JSON_ERROR_UNSUPPORTED_TYPE To get a partial JSON output instead of bool(false) the option JSON_PARTIAL_OUTPUT_ON_ERROR can be specified. In this case the invalid segments will be replaced either by null (for recursion, unsupported type and invalid JSON) or 0 (for Inf and NaN). The warning for invalid UTF-8 stays intact and is thrown also with display_errors = On. If this behavior is undesired this can be remedied later.
Diffstat (limited to 'ext/json/json.c')
-rw-r--r--ext/json/json.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/ext/json/json.c b/ext/json/json.c
index ce2cf43fcc..a90476530e 100644
--- a/ext/json/json.c
+++ b/ext/json/json.c
@@ -81,6 +81,9 @@ static PHP_MINIT_FUNCTION(json)
REGISTER_LONG_CONSTANT("JSON_ERROR_CTRL_CHAR", PHP_JSON_ERROR_CTRL_CHAR, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("JSON_ERROR_SYNTAX", PHP_JSON_ERROR_SYNTAX, CONST_CS | CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("JSON_ERROR_UTF8", PHP_JSON_ERROR_UTF8, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("JSON_ERROR_RECURSION", PHP_JSON_ERROR_RECURSION, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("JSON_ERROR_INF_OR_NAN", PHP_JSON_ERROR_INF_OR_NAN, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("JSON_ERROR_UNSUPPORTED_TYPE", PHP_JSON_ERROR_UNSUPPORTED_TYPE, CONST_CS | CONST_PERSISTENT);
return SUCCESS;
}
@@ -181,6 +184,7 @@ static void json_encode_array(smart_str *buf, zval **val, int options TSRMLS_DC)
}
if (myht && myht->nApplyCount > 1) {
+ JSON_G(error_code) = PHP_JSON_ERROR_RECURSION;
php_error_docref(NULL TSRMLS_CC, E_WARNING, "recursion detected");
smart_str_appendl(buf, "null", 4);
return;
@@ -303,7 +307,8 @@ static void json_escape_string(smart_str *buf, char *s, int len, int options TSR
smart_str_appendl(buf, tmp, l);
efree(tmp);
} else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "double %.9g does not conform to the JSON spec, encoded as 0", d);
+ JSON_G(error_code) = PHP_JSON_ERROR_INF_OR_NAN;
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "double %.9g does not conform to the JSON spec", d);
smart_str_appendc(buf, '0');
}
}
@@ -460,7 +465,8 @@ PHP_JSON_API void php_json_encode(smart_str *buf, zval *val, int options TSRMLS_
smart_str_appendl(buf, d, len);
efree(d);
} else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "double %.9g does not conform to the JSON spec, encoded as 0", dbl);
+ JSON_G(error_code) = PHP_JSON_ERROR_INF_OR_NAN;
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "double %.9g does not conform to the JSON spec", dbl);
smart_str_appendc(buf, '0');
}
}
@@ -476,7 +482,8 @@ PHP_JSON_API void php_json_encode(smart_str *buf, zval *val, int options TSRMLS_
break;
default:
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "type is unsupported, encoded as null");
+ JSON_G(error_code) = PHP_JSON_ERROR_UNSUPPORTED_TYPE;
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "type is unsupported");
smart_str_appendl(buf, "null", 4);
break;
}
@@ -570,7 +577,7 @@ static PHP_FUNCTION(json_encode)
php_json_encode(&buf, parameter, options TSRMLS_CC);
- if (JSON_G(error_code) != PHP_JSON_ERROR_NONE && options ^ PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
+ if (JSON_G(error_code) != PHP_JSON_ERROR_NONE && !(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
ZVAL_FALSE(return_value);
} else {
ZVAL_STRINGL(return_value, buf.c, buf.len, 1);