Skip to content

Commit 2e166e1

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

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
@@ -67,6 +67,8 @@ PHP NEWS
6767
(adapik)
6868
. Fixed json_encode() silently narrowing $depth values outside the int range,
6969
which wrapped to an unrelated depth. (cuishuang)
70+
. Fixed json_encode() continuing to encode after an array or object key
71+
failed to encode. (Ilia Alshanetsky)
7072

7173
- LDAP:
7274
. 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
@@ -164,11 +164,11 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options,
164164

165165
if (php_json_escape_string(buf, ZSTR_VAL(prop_info->name), ZSTR_LEN(prop_info->name),
166166
options & ~PHP_JSON_NUMERIC_CHECK, encoder) == FAILURE) {
167-
if (ZEND_HAS_OOM()) {
167+
if (ZEND_HAS_OOM() || !(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
168168
PHP_JSON_HASH_UNPROTECT_RECURSION(obj);
169169
return FAILURE;
170170
}
171-
if ((options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) && buf->s) {
171+
if (buf->s) {
172172
ZEND_ASSERT(ZSTR_LEN(buf->s) >= 4);
173173
ZSTR_LEN(buf->s) -= 4;
174174
smart_str_appendl(buf, "\"\"", 2);
@@ -285,13 +285,13 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options,
285285

286286
if (php_json_escape_string(buf, ZSTR_VAL(key), ZSTR_LEN(key),
287287
options & ~PHP_JSON_NUMERIC_CHECK, encoder) == FAILURE) {
288-
if (ZEND_HAS_OOM()) {
288+
if (ZEND_HAS_OOM() || !(options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR)) {
289289
PHP_JSON_HASH_UNPROTECT_RECURSION(recursion_rc);
290290
zend_release_properties(prop_ht);
291291
zval_ptr_dtor(&tmp);
292292
return FAILURE;
293293
}
294-
if ((options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) && buf->s) {
294+
if (buf->s) {
295295
ZEND_ASSERT(ZSTR_LEN(buf->s) >= 4);
296296
ZSTR_LEN(buf->s) -= 4;
297297
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)