Commit b60b72229e6 for php.net

commit b60b72229e68824e3df3b2ea845e2482006e5ba0
Author: Tim Düsterhus <tim@bastelstu.be>
Date:   Fri Aug 7 13:22:46 2026 +0200

    date: Fix `Z_PARAM_DATE_TIME_DURATION()` error handling (#23097)

    The `Z_PARAM_*()` macros rely on `break;` to jump to
    `ZEND_PARSE_PARAMETERS_END()`, thus we must not wrap their code into a
    `do { } while(0)` loop, but instead must use a regular block.

diff --git a/ext/date/php_time.h b/ext/date/php_time.h
index fad711b519e..a0425fa9ac5 100644
--- a/ext/date/php_time.h
+++ b/ext/date/php_time.h
@@ -28,17 +28,17 @@ typedef struct php_date_time_duration {

 # define Z_DATE_TIME_DURATION_P(zv)  php_date_time_duration_from_obj(Z_OBJ_P((zv)))

-# define Z_PARAM_DATE_TIME_DURATION(d) do { \
+# define Z_PARAM_DATE_TIME_DURATION(d) { \
 		zend_object *__d; \
 		Z_PARAM_OBJ_OF_CLASS(__d, php_date_ce_time_duration); \
 		d = php_date_time_duration_from_obj(__d); \
-	} while (0);
+	}

-# define Z_PARAM_DATE_TIME_DURATION_OR_NULL(d) do { \
+# define Z_PARAM_DATE_TIME_DURATION_OR_NULL(d) { \
 		zend_object *__d; \
 		Z_PARAM_OBJ_OF_CLASS_OR_NULL(__d, php_date_ce_time_duration); \
 		d = __d ? php_date_time_duration_from_obj(__d) : NULL; \
-	} while (0);
+	}

 PHPAPI extern zend_class_entry *php_date_ce_time_duration;
 PHPAPI extern zend_class_entry *php_date_ce_time_timeexception;
diff --git a/ext/date/tests/time/duration/z_param_date_time_duration.phpt b/ext/date/tests/time/duration/z_param_date_time_duration.phpt
new file mode 100644
index 00000000000..23c2fe080aa
--- /dev/null
+++ b/ext/date/tests/time/duration/z_param_date_time_duration.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Time\Duration: Z_PARAM_DATE_TIME_DURATION() correctly aborts parameter parsing
+--FILE--
+<?php
+
+require __DIR__ . '/helper.inc';
+
+try {
+    Time\Duration::compare(1, 2);
+} catch (Throwable $e) {
+    echo $e::class, ': ', $e->getMessage(), PHP_EOL;
+}
+
+?>
+--EXPECT--
+TypeError: Time\Duration::compare(): Argument #1 ($a) must be of type Time\Duration, int given