Skip to content

Commit 45d596e

Browse files
committed
Add optional depth parameter to json_encode #62369
1 parent dd9d64b commit 45d596e

3 files changed

Lines changed: 44 additions & 1 deletion

File tree

ext/json/json.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ ZEND_DECLARE_MODULE_GLOBALS(json)
4747
ZEND_BEGIN_ARG_INFO_EX(arginfo_json_encode, 0, 0, 1)
4848
ZEND_ARG_INFO(0, value)
4949
ZEND_ARG_INFO(0, options)
50+
ZEND_ARG_INFO(0, depth)
5051
ZEND_END_ARG_INFO()
5152

5253
ZEND_BEGIN_ARG_INFO_EX(arginfo_json_decode, 0, 0, 1)
@@ -126,6 +127,7 @@ static PHP_GINIT_FUNCTION(json)
126127
{
127128
json_globals->encoder_depth = 0;
128129
json_globals->error_code = 0;
130+
json_globals->encode_max_depth = 0;
129131
}
130132
/* }}} */
131133

@@ -341,6 +343,9 @@ static void json_encode_array(smart_str *buf, zval **val, int options TSRMLS_DC)
341343
}
342344
}
343345

346+
if (JSON_G(encoder_depth) > JSON_G(encode_max_depth)) {
347+
JSON_G(error_code) = PHP_JSON_ERROR_DEPTH;
348+
}
344349
--JSON_G(encoder_depth);
345350
json_pretty_print_char(buf, options, '\n' TSRMLS_CC);
346351
json_pretty_print_indent(buf, options TSRMLS_CC);
@@ -702,13 +707,16 @@ static PHP_FUNCTION(json_encode)
702707
zval *parameter;
703708
smart_str buf = {0};
704709
long options = 0;
710+
long depth = JSON_PARSER_DEFAULT_DEPTH;
705711

706-
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|l", &parameter, &options) == FAILURE) {
712+
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|ll", &parameter, &options, &depth) == FAILURE) {
707713
return;
708714
}
709715

710716
JSON_G(error_code) = PHP_JSON_ERROR_NONE;
711717

718+
JSON_G(encode_max_depth) = depth;
719+
712720
php_json_encode(&buf, parameter, options TSRMLS_CC);
713721

714722
if (JSON_G(error_code) != PHP_JSON_ERROR_NONE && !(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {

ext/json/php_json.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ extern zend_module_entry json_module_entry;
4040
ZEND_BEGIN_MODULE_GLOBALS(json)
4141
int encoder_depth;
4242
int error_code;
43+
int encode_max_depth;
4344
ZEND_END_MODULE_GLOBALS(json)
4445

4546
#ifdef ZTS

ext/json/tests/bug62369.phpt

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
--TEST--
2+
FR #62369 (Segfault on json_encode(deeply_nested_array)
3+
--SKIPIF--
4+
<?php if (!extension_loaded("json")) print "skip"; ?>
5+
--FILE--
6+
<?php
7+
8+
$array = array();
9+
for ($i=0; $i<550; $i++) {
10+
$array = array($array);
11+
}
12+
13+
json_encode($array, 0, 551);
14+
switch (json_last_error()) {
15+
case JSON_ERROR_NONE:
16+
echo 'OK'.PHP_EOL;
17+
break;
18+
case JSON_ERROR_DEPTH:
19+
echo 'ERROR'.PHP_EOL;
20+
break;
21+
}
22+
23+
json_encode($array, 0, 540);
24+
switch (json_last_error()) {
25+
case JSON_ERROR_NONE:
26+
echo 'OK'.PHP_EOL;
27+
break;
28+
case JSON_ERROR_DEPTH:
29+
echo 'ERROR'.PHP_EOL;
30+
break;
31+
}
32+
--EXPECTF--
33+
OK
34+
ERROR

0 commit comments

Comments
 (0)