From 3bfd3d18f8e2f2cca0abbef4da96ce5b13ba4948 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Thu, 9 Jul 2026 18:08:13 +0100 Subject: [PATCH 1/2] Fix GH-11310: __debugInfo does nothing on userland classes extending Date classes --- NEWS | 2 ++ ext/date/php_date.c | 24 +++++++++++++++++++-- ext/date/tests/bug-gh11310.phpt | 37 +++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 ext/date/tests/bug-gh11310.phpt diff --git a/NEWS b/NEWS index d64ce32ab995..5d84e1a69039 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,8 @@ PHP NEWS an error). (Derick) . Fixed Unix timestamps in February of the year 0 are misparsed with @-notation. (LukasGelbmann) + . Fixed bug GH-11310 (__debugInfo does nothing on userland classes extending + Date classes). (Derick) - DBA: . Fixed OOB read on malformed length field in dba flatfile handler. (alhudz) diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 08a91a6318e9..e16a61035c5b 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -1995,12 +1995,22 @@ static HashTable *date_object_get_properties_for(zend_object *object, zend_prop_ php_date_obj *dateobj; switch (purpose) { - case ZEND_PROP_PURPOSE_DEBUG: case ZEND_PROP_PURPOSE_SERIALIZE: case ZEND_PROP_PURPOSE_VAR_EXPORT: case ZEND_PROP_PURPOSE_JSON: case ZEND_PROP_PURPOSE_ARRAY_CAST: break; + case ZEND_PROP_PURPOSE_DEBUG: { + if (object->ce->__debugInfo) { + int is_temp = 0; + HashTable *ht = zend_std_get_debug_info(object, &is_temp); + if (ht && !is_temp) { + GC_TRY_ADDREF(ht); + } + return ht; + } + break; + } default: return zend_std_get_properties_for(object, purpose); } @@ -2117,12 +2127,22 @@ static HashTable *date_object_get_properties_for_timezone(zend_object *object, z php_timezone_obj *tzobj; switch (purpose) { - case ZEND_PROP_PURPOSE_DEBUG: case ZEND_PROP_PURPOSE_SERIALIZE: case ZEND_PROP_PURPOSE_VAR_EXPORT: case ZEND_PROP_PURPOSE_JSON: case ZEND_PROP_PURPOSE_ARRAY_CAST: break; + case ZEND_PROP_PURPOSE_DEBUG: { + if (object->ce->__debugInfo) { + int is_temp = 0; + HashTable *ht = zend_std_get_debug_info(object, &is_temp); + if (ht && !is_temp) { + GC_TRY_ADDREF(ht); + } + return ht; + } + break; + } default: return zend_std_get_properties_for(object, purpose); } diff --git a/ext/date/tests/bug-gh11310.phpt b/ext/date/tests/bug-gh11310.phpt new file mode 100644 index 000000000000..c12b0201294d --- /dev/null +++ b/ext/date/tests/bug-gh11310.phpt @@ -0,0 +1,37 @@ +--TEST-- +Bug GH-11310: __debugInfo does nothing on userland classes extending Date classes +--FILE-- + 'zzz']; } } +class UDateTimeImmutable extends DateTimeImmutable { public function __debugInfo(): array { return ['value' => 'zzz']; } } +class UDateTimeZone extends DateTimeZone { public function __debugInfo(): array { return ['value' => 'zzz']; } } +class UDateInterval extends DateInterval { public function __debugInfo(): array { return ['value' => 'zzz']; } } +class UDatePeriod extends DatePeriod { public function __debugInfo(): array { return ['value' => 'zzz']; } } + +$d = new UDateTime(); var_dump($d); +$d = new UDateTimeImmutable(); var_dump($d); +$d = new UDateTimeZone("Europe/Kyiv"); var_dump($d); +$d = new UDateInterval("P3D"); var_dump($d); +$d = UDatePeriod::createFromISO8601String("2026-07-09T17:23:06Z/P3D/R5"); var_dump($d); +?> +--EXPECTF-- +object(UDateTime)#%d (1) { + ["value"]=> + string(3) "zzz" +} +object(UDateTimeImmutable)#%d (1) { + ["value"]=> + string(3) "zzz" +} +object(UDateTimeZone)#%d (1) { + ["value"]=> + string(3) "zzz" +} +object(UDateInterval)#%d (1) { + ["value"]=> + string(3) "zzz" +} +object(UDatePeriod)#%d (1) { + ["value"]=> + string(3) "zzz" +} From ed4ad0ea40cfd2514f8294f8f4f45a1e557408a1 Mon Sep 17 00:00:00 2001 From: Derick Rethans Date: Thu, 9 Jul 2026 18:30:09 +0100 Subject: [PATCH 2/2] Add tests to make sure not calling the parent constructor has any effect --- .../{bug-gh11310.phpt => bug-gh11310-1.phpt} | 0 ext/date/tests/bug-gh11310-2.phpt | 37 +++++++++++++++++++ 2 files changed, 37 insertions(+) rename ext/date/tests/{bug-gh11310.phpt => bug-gh11310-1.phpt} (100%) create mode 100644 ext/date/tests/bug-gh11310-2.phpt diff --git a/ext/date/tests/bug-gh11310.phpt b/ext/date/tests/bug-gh11310-1.phpt similarity index 100% rename from ext/date/tests/bug-gh11310.phpt rename to ext/date/tests/bug-gh11310-1.phpt diff --git a/ext/date/tests/bug-gh11310-2.phpt b/ext/date/tests/bug-gh11310-2.phpt new file mode 100644 index 000000000000..8dce510a19d6 --- /dev/null +++ b/ext/date/tests/bug-gh11310-2.phpt @@ -0,0 +1,37 @@ +--TEST-- +Bug GH-11310: __debugInfo does nothing on userland classes extending Date classes +--FILE-- + 'zzz']; } } +class UDateTimeImmutable extends DateTimeImmutable { public function __construct() {} public function __debugInfo(): array { return ['value' => 'zzz']; } } +class UDateTimeZone extends DateTimeZone { public function __construct() {} public function __debugInfo(): array { return ['value' => 'zzz']; } } +class UDateInterval extends DateInterval { public function __construct() {} public function __debugInfo(): array { return ['value' => 'zzz']; } } +class UDatePeriod extends DatePeriod { public function __construct() {} public function __debugInfo(): array { return ['value' => 'zzz']; } } + +$d = new UDateTime(); var_dump($d); +$d = new UDateTimeImmutable(); var_dump($d); +$d = new UDateTimeZone("Europe/Kyiv"); var_dump($d); +$d = new UDateInterval("P3D"); var_dump($d); +$d = UDatePeriod::createFromISO8601String("2026-07-09T17:23:06Z/P3D/R5"); var_dump($d); +?> +--EXPECTF-- +object(UDateTime)#%d (1) { + ["value"]=> + string(3) "zzz" +} +object(UDateTimeImmutable)#%d (1) { + ["value"]=> + string(3) "zzz" +} +object(UDateTimeZone)#%d (1) { + ["value"]=> + string(3) "zzz" +} +object(UDateInterval)#%d (1) { + ["value"]=> + string(3) "zzz" +} +object(UDatePeriod)#%d (1) { + ["value"]=> + string(3) "zzz" +}