]> granicus.if.org Git - php/commitdiff
Add optional depth parameter to json_encode #62369
authorFlorian Anderiasch <fa@php.net>
Tue, 24 Jul 2012 11:15:16 +0000 (13:15 +0200)
committerFlorian Anderiasch <fa@php.net>
Tue, 24 Jul 2012 11:15:16 +0000 (13:15 +0200)
ext/json/json.c
ext/json/php_json.h
ext/json/tests/bug62369.phpt [new file with mode: 0644]

index 96690477c94de4919a3df76a431403b4d6e492ac..dab423084c41691c607e904bd2475a61cdc2c77b 100644 (file)
@@ -47,6 +47,7 @@ ZEND_DECLARE_MODULE_GLOBALS(json)
 ZEND_BEGIN_ARG_INFO_EX(arginfo_json_encode, 0, 0, 1)
        ZEND_ARG_INFO(0, value)
        ZEND_ARG_INFO(0, options)
+       ZEND_ARG_INFO(0, depth)
 ZEND_END_ARG_INFO()
 
 ZEND_BEGIN_ARG_INFO_EX(arginfo_json_decode, 0, 0, 1)
@@ -126,6 +127,7 @@ static PHP_GINIT_FUNCTION(json)
 {
        json_globals->encoder_depth = 0;
        json_globals->error_code = 0;
+       json_globals->encode_max_depth = 0;
 }
 /* }}} */
 
@@ -341,6 +343,9 @@ static void json_encode_array(smart_str *buf, zval **val, int options TSRMLS_DC)
                }
        }
 
+       if (JSON_G(encoder_depth) > JSON_G(encode_max_depth)) {
+               JSON_G(error_code) = PHP_JSON_ERROR_DEPTH;
+       }
        --JSON_G(encoder_depth);
        json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
        json_pretty_print_indent(buf, options TSRMLS_CC);
@@ -702,13 +707,16 @@ static PHP_FUNCTION(json_encode)
        zval *parameter;
        smart_str buf = {0};
        long options = 0;
+    long depth = JSON_PARSER_DEFAULT_DEPTH;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &parameter, &options) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|ll", &parameter, &options, &depth) == FAILURE) {
                return;
        }
 
        JSON_G(error_code) = PHP_JSON_ERROR_NONE;
 
+       JSON_G(encode_max_depth) = depth;
+
        php_json_encode(&buf, parameter, options TSRMLS_CC);
 
        if (JSON_G(error_code) != PHP_JSON_ERROR_NONE && !(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
index afeff3f6cc85523cae225e266eba76848062087e..2b3cf5868ad4fb3583b64e45a4c994ec964e4c32 100644 (file)
@@ -40,6 +40,7 @@ extern zend_module_entry json_module_entry;
 ZEND_BEGIN_MODULE_GLOBALS(json)
        int encoder_depth;
        int error_code;
+       int encode_max_depth;
 ZEND_END_MODULE_GLOBALS(json)
 
 #ifdef ZTS
diff --git a/ext/json/tests/bug62369.phpt b/ext/json/tests/bug62369.phpt
new file mode 100644 (file)
index 0000000..a5efd80
--- /dev/null
@@ -0,0 +1,34 @@
+--TEST--
+FR #62369 (Segfault on json_encode(deeply_nested_array)
+--SKIPIF--
+<?php if (!extension_loaded("json")) print "skip"; ?>
+--FILE--
+<?php
+
+$array = array();
+for ($i=0; $i<550; $i++) {
+    $array = array($array);
+}
+
+json_encode($array, 0, 551);
+switch (json_last_error()) {
+    case JSON_ERROR_NONE:
+        echo 'OK'.PHP_EOL;
+    break;
+    case JSON_ERROR_DEPTH:
+        echo 'ERROR'.PHP_EOL;
+    break;
+}
+
+json_encode($array, 0, 540);
+switch (json_last_error()) {
+    case JSON_ERROR_NONE:
+        echo 'OK'.PHP_EOL;
+    break;
+    case JSON_ERROR_DEPTH:
+        echo 'ERROR'.PHP_EOL;
+    break;
+}
+--EXPECTF--
+OK
+ERROR