Skip to content

Commit e1e07b9

Browse files
committed
Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4: ext/json: Stop encoding after a key fails to encode
2 parents 1938dba + de6ffeb commit e1e07b9

3 files changed

Lines changed: 61 additions & 4 deletions

File tree

‎NEWS‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@ PHP NEWS
9898
(adapik)
9999
. Fixed json_encode() silently narrowing $depth values outside the int range,
100100
which wrapped to an unrelated depth. (cuishuang)
101+
. Fixed json_encode() continuing to encode after an array or object key
102+
failed to encode. (Ilia Alshanetsky)
101103

102104
- LDAP:
103105
. Fix crash in ldap_exop_sync() when $response_data is omitted. (lacatoire)

‎ext/json/json_encoder.c‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,11 +172,11 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options,
172172

173173
if (php_json_escape_string(buf, ZSTR_VAL(prop_info->name), ZSTR_LEN(prop_info->name),
174174
options & ~PHP_JSON_NUMERIC_CHECK, encoder) == FAILURE) {
175-
if (ZEND_HAS_OOM()) {
175+
if (ZEND_HAS_OOM() || !(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
176176
PHP_JSON_HASH_UNPROTECT_RECURSION(obj);
177177
return FAILURE;
178178
}
179-
if ((options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) && buf->s) {
179+
if (buf->s) {
180180
ZEND_ASSERT(ZSTR_LEN(buf->s) >= 4);
181181
ZSTR_LEN(buf->s) -= 4;
182182
smart_str_appendl(buf, "\"\"", 2);
@@ -293,13 +293,13 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options,
293293

294294
if (php_json_escape_string(buf, ZSTR_VAL(key), ZSTR_LEN(key),
295295
options & ~PHP_JSON_NUMERIC_CHECK, encoder) == FAILURE) {
296-
if (ZEND_HAS_OOM()) {
296+
if (ZEND_HAS_OOM() || !(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
297297
PHP_JSON_HASH_UNPROTECT_RECURSION(recursion_rc);
298298
zend_release_properties(prop_ht);
299299
zval_ptr_dtor(&tmp);
300300
return FAILURE;
301301
}
302-
if ((options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) && buf->s) {
302+
if (buf->s) {
303303
ZEND_ASSERT(ZSTR_LEN(buf->s) >= 4);
304304
ZSTR_LEN(buf->s) -= 4;
305305
smart_str_appendl(buf, "\"\"", 2);
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
--TEST--
2+
json_encode() stops encoding after an object or array key fails to encode
3+
--FILE--
4+
<?php
5+
6+
class Value implements JsonSerializable
7+
{
8+
public function jsonSerialize(): mixed
9+
{
10+
echo "jsonSerialize() called\n";
11+
return 1;
12+
}
13+
}
14+
15+
eval('class Declared { public $' . "\xff" . ' = 1; public $next; }');
16+
17+
$dynamic = new stdClass;
18+
$dynamic->{"\xff"} = 1;
19+
$dynamic->next = new Value;
20+
21+
$declared = new Declared;
22+
$declared->next = new Value;
23+
24+
$cases = [
25+
'array' => ["\xff" => 1, 'next' => new Value],
26+
'array, later NAN' => ["\xff" => 1, 'next' => NAN],
27+
'dynamic property' => $dynamic,
28+
'declared property' => $declared,
29+
];
30+
31+
foreach ($cases as $name => $value) {
32+
echo "$name:\n";
33+
var_dump(json_encode($value), json_last_error_msg());
34+
}
35+
36+
echo "partial output:\n";
37+
var_dump(json_encode(["\xff" => 1, 'next' => 2], JSON_PARTIAL_OUTPUT_ON_ERROR), json_last_error_msg());
38+
39+
?>
40+
--EXPECT--
41+
array:
42+
bool(false)
43+
string(56) "Malformed UTF-8 characters, possibly incorrectly encoded"
44+
array, later NAN:
45+
bool(false)
46+
string(56) "Malformed UTF-8 characters, possibly incorrectly encoded"
47+
dynamic property:
48+
bool(false)
49+
string(56) "Malformed UTF-8 characters, possibly incorrectly encoded"
50+
declared property:
51+
bool(false)
52+
string(56) "Malformed UTF-8 characters, possibly incorrectly encoded"
53+
partial output:
54+
string(15) "{"":1,"next":2}"
55+
string(56) "Malformed UTF-8 characters, possibly incorrectly encoded"

0 commit comments

Comments
 (0)