Commit 8b1079a890a for php.net

commit 8b1079a890a55b4865585001a6e5dae4e396ac0b
Author: Derick Rethans <github@derickrethans.nl>
Date:   Fri Jul 10 13:38:56 2026 +0100

    Fix GH-11310: __debugInfo does nothing on userland classes extending Date classes (#22655)

    * Fix GH-11310: __debugInfo does nothing on userland classes extending Date classes

    * Add tests to make sure not calling the parent constructor has any effect

diff --git a/NEWS b/NEWS
index 7aada8213bb..2d0abd7eb42 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 08a91a6318e..e16a61035c5 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-1.phpt b/ext/date/tests/bug-gh11310-1.phpt
new file mode 100644
index 00000000000..c12b0201294
--- /dev/null
+++ b/ext/date/tests/bug-gh11310-1.phpt
@@ -0,0 +1,37 @@
+--TEST--
+Bug GH-11310: __debugInfo does nothing on userland classes extending Date classes
+--FILE--
+<?php
+class UDateTime extends DateTime { public function __debugInfo(): array { return ['value' => '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"
+}
diff --git a/ext/date/tests/bug-gh11310-2.phpt b/ext/date/tests/bug-gh11310-2.phpt
new file mode 100644
index 00000000000..8dce510a19d
--- /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--
+<?php
+class UDateTime extends DateTime { public function __construct() {} public function __debugInfo(): array { return ['value' => '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"
+}