Skip to content

Commit aaa680c

Browse files
committed
Merge branch 'PHP-8.6'
* PHP-8.6: Fix json_encode() reporting false "Recursion detected" after OOM for hooked-property objects (#24992)
2 parents 08b3587 + a8a3635 commit aaa680c

2 files changed

Lines changed: 30 additions & 1 deletion

File tree

‎ext/json/json_encoder.c‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,8 +286,9 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options,
286286
if (php_json_escape_string(buf, ZSTR_VAL(key), ZSTR_LEN(key),
287287
options & ~PHP_JSON_NUMERIC_CHECK, encoder) == FAILURE) {
288288
if (ZEND_HAS_OOM()) {
289-
PHP_JSON_HASH_UNPROTECT_RECURSION(myht);
289+
PHP_JSON_HASH_UNPROTECT_RECURSION(recursion_rc);
290290
zend_release_properties(prop_ht);
291+
zval_ptr_dtor(&tmp);
291292
return FAILURE;
292293
}
293294
if ((options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) && buf->s) {
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--TEST--
2+
json_encode() OOM while escaping a property name releases the recursion guard of an object with hooked properties
3+
--FILE--
4+
<?php
5+
6+
#[AllowDynamicProperties]
7+
class C {
8+
public string $a { get => str_repeat('v', 100); }
9+
}
10+
11+
$o = new C;
12+
$o->{str_repeat('k', 3 * 1024 * 1024)} = 1;
13+
14+
register_shutdown_function(function () use ($o) {
15+
ini_set('memory_limit', '-1');
16+
$json = json_encode($o);
17+
var_dump($json !== false, json_last_error_msg());
18+
});
19+
20+
// Leave less than the 3 MiB property name needs, so that pre-allocating it
21+
// fails while escaping the key, after the object was marked as being encoded.
22+
ini_set('memory_limit', memory_get_usage(true) + 1024 * 1024);
23+
json_encode($o);
24+
?>
25+
--EXPECTF--
26+
Fatal error: Allowed memory size of %d bytes exhausted %S(tried to allocate %d bytes) in %s on line %d
27+
%Abool(true)
28+
string(8) "No error"

0 commit comments

Comments
 (0)