diff options
author | Xinchen Hui <laruence@gmail.com> | 2016-05-06 18:38:26 +0800 |
---|---|---|
committer | Xinchen Hui <laruence@gmail.com> | 2016-05-06 18:38:26 +0800 |
commit | 459a7cc209da130256d66c1f896199540f4dadbc (patch) | |
tree | f13908f7c8f108e31e064a0b05f04bdbda132f8d | |
parent | 627b5aae3f5f3986f5d57c86d567f0bf7d376cca (diff) | |
download | php-git-459a7cc209da130256d66c1f896199540f4dadbc.tar.gz |
Fixed bug #72170 (JsonSerializable may inc apply count without dec it)
I don't want use zend_try here, but seems I have no choice :<
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | ext/json/json_encoder.c | 83 | ||||
-rw-r--r-- | ext/json/tests/bug72170.phpt | 32 |
3 files changed, 79 insertions, 38 deletions
@@ -24,6 +24,8 @@ PHP NEWS . Fixed bug #72157 (use-after-free caused by dba_open). (Shm, Laruence) - JSON: + . Fixed bug #72170 (JsonSerializable may inc apply count without dec it). + (Laruence) . Fixed bug #72069 (Behavior \JsonSerializable different from json_encode). (Laruence) diff --git a/ext/json/json_encoder.c b/ext/json/json_encoder.c index ae9e086fc0..58ea67a04a 100644 --- a/ext/json/json_encoder.c +++ b/ext/json/json_encoder.c @@ -157,26 +157,8 @@ static void php_json_encode_array(smart_str *buf, zval *val, int options) /* {{{ ZEND_HASH_INC_APPLY_COUNT(tmp_ht); } - if (r == PHP_JSON_OUTPUT_ARRAY) { - if (need_comma) { - smart_str_appendc(buf, ','); - } else { - need_comma = 1; - } - - 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' && Z_TYPE_P(val) == IS_OBJECT) { - /* Skip protected and private members. */ - if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) { - ZEND_HASH_DEC_APPLY_COUNT(tmp_ht); - } - continue; - } - + zend_try { + if (r == PHP_JSON_OUTPUT_ARRAY) { if (need_comma) { smart_str_appendc(buf, ','); } else { @@ -185,33 +167,58 @@ 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' && Z_TYPE_P(val) == IS_OBJECT) { + /* Skip protected and private members. */ + if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) { + ZEND_HASH_DEC_APPLY_COUNT(tmp_ht); + } + continue; + } - php_json_escape_string(buf, ZSTR_VAL(key), ZSTR_LEN(key), options & ~PHP_JSON_NUMERIC_CHECK); - smart_str_appendc(buf, ':'); + if (need_comma) { + smart_str_appendc(buf, ','); + } else { + need_comma = 1; + } - php_json_pretty_print_char(buf, options, ' '); + php_json_pretty_print_char(buf, options, '\n'); + php_json_pretty_print_indent(buf, options); - php_json_encode(buf, data, options); - } else { - if (need_comma) { - smart_str_appendc(buf, ','); + 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 { - need_comma = 1; - } + if (need_comma) { + smart_str_appendc(buf, ','); + } else { + need_comma = 1; + } - php_json_pretty_print_char(buf, options, '\n'); - php_json_pretty_print_indent(buf, options); + php_json_pretty_print_char(buf, options, '\n'); + php_json_pretty_print_indent(buf, options); - smart_str_appendc(buf, '"'); - smart_str_append_long(buf, (zend_long) index); - smart_str_appendc(buf, '"'); - smart_str_appendc(buf, ':'); + 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_pretty_print_char(buf, options, ' '); - php_json_encode(buf, data, options); + php_json_encode(buf, data, options); + } } - } + } zend_catch { + if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) { + ZEND_HASH_DEC_APPLY_COUNT(tmp_ht); + } + zend_bailout(); + } zend_end_try(); if (tmp_ht && ZEND_HASH_APPLY_PROTECTION(tmp_ht)) { ZEND_HASH_DEC_APPLY_COUNT(tmp_ht); diff --git a/ext/json/tests/bug72170.phpt b/ext/json/tests/bug72170.phpt new file mode 100644 index 0000000000..a7c25c2061 --- /dev/null +++ b/ext/json/tests/bug72170.phpt @@ -0,0 +1,32 @@ +--TEST-- +Bug #72170 (JsonSerializable may inc apply count without dec it) +--SKIPIF-- +<?php if (!extension_loaded("json")) print "skip"; ?> +--FILE-- +<?php + +class Dummy implements JsonSerializable{ + public function jsonSerialize() { + global $flag; + if ($flag) { + exit; + } else { + return "okey"; + } + } +} + +$array = array(); +$array[] = new Dummy; + +register_shutdown_function(function() use($array) { + global $flag; + $flag = 0; + var_dump(json_encode(array($array))); +}); + +$flag = 1; +json_encode(array($array)); +?> +--EXPECT-- +string(10) "[["okey"]]" |