Skip to content

Commit e7adcaf

Browse files
committed
Don't build prop table during json_encode(JsonSerializable)
Save memory and time by not building/updating the property table. When performing infinite recursion detection on objects, always check it on the object rather than its property table. This reduces the additional memory usage for both internal and userland implementations of JsonSerializable caused by json_encode. It does this by avoiding creating the properties table for the first time. (Classes such as SplFixedArray both implement JsonSerializable and override get_properties) This change also makes the method of infinite recursion detection consistent with the special case for standard classes from f9f8c1c
1 parent b87a2e6 commit e7adcaf

File tree

2 files changed

+8
-11
lines changed

2 files changed

+8
-11
lines changed

ext/json/json_encoder.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -534,20 +534,20 @@ static zend_result php_json_escape_string(
534534

535535
static zend_result php_json_encode_serializable_object(smart_str *buf, zval *val, int options, php_json_encoder *encoder) /* {{{ */
536536
{
537+
zend_object *obj = Z_OBJ_P(val);
537538
zend_class_entry *ce = Z_OBJCE_P(val);
538-
HashTable* myht = Z_OBJPROP_P(val);
539539
zval retval, fname;
540540
zend_result return_code;
541541

542-
if (myht && GC_IS_RECURSIVE(myht)) {
542+
if (GC_IS_RECURSIVE(obj)) {
543543
encoder->error_code = PHP_JSON_ERROR_RECURSION;
544544
if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
545545
smart_str_appendl(buf, "null", 4);
546546
}
547547
return FAILURE;
548548
}
549549

550-
PHP_JSON_HASH_PROTECT_RECURSION(myht);
550+
GC_PROTECT_RECURSION(obj);
551551

552552
ZVAL_STRING(&fname, "jsonSerialize");
553553

@@ -560,7 +560,7 @@ static zend_result php_json_encode_serializable_object(smart_str *buf, zval *val
560560
if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
561561
smart_str_appendl(buf, "null", 4);
562562
}
563-
PHP_JSON_HASH_UNPROTECT_RECURSION(myht);
563+
GC_UNPROTECT_RECURSION(obj);
564564
return FAILURE;
565565
}
566566

@@ -572,19 +572,19 @@ static zend_result php_json_encode_serializable_object(smart_str *buf, zval *val
572572
if (options & PHP_JSON_PARTIAL_OUTPUT_ON_ERROR) {
573573
smart_str_appendl(buf, "null", 4);
574574
}
575-
PHP_JSON_HASH_UNPROTECT_RECURSION(myht);
575+
GC_UNPROTECT_RECURSION(obj);
576576
return FAILURE;
577577
}
578578

579579
if ((Z_TYPE(retval) == IS_OBJECT) &&
580580
(Z_OBJ(retval) == Z_OBJ_P(val))) {
581581
/* Handle the case where jsonSerialize does: return $this; by going straight to encode array */
582-
PHP_JSON_HASH_UNPROTECT_RECURSION(myht);
582+
GC_UNPROTECT_RECURSION(obj);
583583
return_code = php_json_encode_array(buf, &retval, options, encoder);
584584
} else {
585585
/* All other types, encode as normal */
586586
return_code = php_json_encode_zval(buf, &retval, options, encoder);
587-
PHP_JSON_HASH_UNPROTECT_RECURSION(myht);
587+
GC_UNPROTECT_RECURSION(obj);
588588
}
589589

590590
zval_ptr_dtor(&retval);

ext/json/tests/bug77843.phpt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,5 @@ var_dump(json_encode([&$arr]));
1818

1919
?>
2020
--EXPECT--
21-
object(X)#1 (1) {
22-
["prop"]=>
23-
string(5) "value"
24-
}
21+
*RECURSION*
2522
string(20) "[[{"prop":"value"}]]"

0 commit comments

Comments
 (0)