From 358f3aa095b8fe601587b08f1b09c6dc5acb9a4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heath=20Dutton=F0=9F=95=B4=EF=B8=8F?= Date: Tue, 16 Dec 2025 18:37:39 -0500 Subject: [PATCH] Fix GH-20503: Assertion failure with ext/date DateInterval property hash --- ext/date/php_date.c | 6 ++++++ ext/date/tests/bug-gh20503.phpt | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 ext/date/tests/bug-gh20503.phpt diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 6773fa939e6b..c455b226c34e 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -2265,6 +2265,12 @@ static HashTable *date_object_get_properties_interval(zend_object *object) /* {{ return props; } + /* The table may still be held elsewhere (e.g. json_encode() walking a cycle), so separate it before writing */ + if (UNEXPECTED(GC_REFCOUNT(props) > 1)) { + GC_TRY_DELREF(props); + props = object->properties = zend_array_dup(props); + } + date_interval_object_to_hash(intervalobj, props); return props; diff --git a/ext/date/tests/bug-gh20503.phpt b/ext/date/tests/bug-gh20503.phpt new file mode 100644 index 000000000000..468afb3d124b --- /dev/null +++ b/ext/date/tests/bug-gh20503.phpt @@ -0,0 +1,33 @@ +--TEST-- +GH-20503 (Assertion failure with ext/date DateInterval property hash construction) +--SKIPIF-- + +--INI-- +zend.max_allowed_stack_size=512K +--FILE-- +prop3 = $obj; +var_dump(json_encode($obj)); +var_dump(json_last_error_msg()); + +$obj2 = new DateInterval('P1D'); +$obj2->prop = [$obj2]; +var_dump(json_encode($obj2)); +var_dump(json_last_error_msg()); +?> +--EXPECTF-- +Deprecated: Creation of dynamic property DateInterval::$prop3 is deprecated in %s on line %d +bool(false) +string(28) "Maximum stack depth exceeded" + +Deprecated: Creation of dynamic property DateInterval::$prop is deprecated in %s on line %d +bool(false) +string(18) "Recursion detected"