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"