Patch-Source: https://github.com/php/php-src/commit/2d86f8cf489ea5410edd19d301c1aefe330599ab From ba2ede2740f05066a390886fb432571043c49876 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 30 Jul 2026 14:29:58 +0200 Subject: [PATCH 4/4] Fix leak on double DatePeriod::__construct() call Closes GH-22643 (cherry picked from commit 2d86f8cf489ea5410edd19d301c1aefe330599ab) PHP 8.1 adaptation: DATE_CHECK_INITIALIZED() stringifies its second argument on this branch, so pass the DateInterval class name literally instead of Z_OBJCE_P(interval), which would otherwise be printed verbatim in the error message. --- ext/date/php_date.c | 20 ++++++++++++++++++- .../DatePeriod_double_constructor_call.phpt | 14 +++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 ext/date/tests/DatePeriod_double_constructor_call.phpt diff --git a/ext/date/php_date.c b/ext/date/php_date.c index fe58eba5c89..6b3842e64be 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -4283,6 +4283,23 @@ static bool date_period_initialize(timelib_time **st, timelib_time **et, timelib return retval; } /* }}} */ +static void date_period_reset(php_period_obj *period_obj) +{ + if (period_obj->start) { + timelib_time_dtor(period_obj->start); + } + if (period_obj->current) { + timelib_time_dtor(period_obj->current); + } + if (period_obj->end) { + timelib_time_dtor(period_obj->end); + } + if (period_obj->interval) { + timelib_rel_time_dtor(period_obj->interval); + } + memset(period_obj, 0, XtOffsetOf(php_period_obj, std)); +} + /* {{{ Creates new DatePeriod object. */ PHP_METHOD(DatePeriod, __construct) { @@ -4304,7 +4321,7 @@ PHP_METHOD(DatePeriod, __construct) } dpobj = Z_PHPPERIOD_P(ZEND_THIS); - dpobj->current = NULL; + date_period_reset(dpobj); if (isostr) { if (!date_period_initialize(&(dpobj->start), &(dpobj->end), &(dpobj->interval), &recurrences, isostr, isostr_len)) { @@ -4343,6 +4360,7 @@ PHP_METHOD(DatePeriod, __construct) if (end) { DATE_CHECK_INITIALIZED(Z_PHPDATE_P(end)->time, DateTimeInterface); } + DATE_CHECK_INITIALIZED(Z_PHPINTERVAL_P(interval)->initialized, DateInterval); /* init */ php_interval_obj *intobj = Z_PHPINTERVAL_P(interval); diff --git a/ext/date/tests/DatePeriod_double_constructor_call.phpt b/ext/date/tests/DatePeriod_double_constructor_call.phpt new file mode 100644 index 00000000000..551d2727282 --- /dev/null +++ b/ext/date/tests/DatePeriod_double_constructor_call.phpt @@ -0,0 +1,14 @@ +--TEST-- +Double DatePeriod::__construct() call +--FILE-- +__construct($start, $interval, 1); + +?> +===DONE=== +--EXPECT-- +===DONE===