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