| 1 | Patch-Source: https://github.com/php/php-src/commit/2d86f8cf489ea5410edd19d301c1aefe330599ab
|
| 2 | From ba2ede2740f05066a390886fb432571043c49876 Mon Sep 17 00:00:00 2001
|
| 3 | From: Ilija Tovilo <[email protected]>
|
| 4 | Date: Thu, 30 Jul 2026 14:29:58 +0200
|
| 5 | Subject: [PATCH 4/4] Fix leak on double DatePeriod::__construct() call
|
| 6 |
|
| 7 | Closes GH-22643
|
| 8 |
|
| 9 | (cherry picked from commit 2d86f8cf489ea5410edd19d301c1aefe330599ab)
|
| 10 |
|
| 11 | PHP 8.1 adaptation: DATE_CHECK_INITIALIZED() stringifies its second
|
| 12 | argument on this branch, so pass the DateInterval class name literally
|
| 13 | instead of Z_OBJCE_P(interval), which would otherwise be printed
|
| 14 | verbatim in the error message.
|
| 15 | ---
|
| 16 | ext/date/php_date.c | 20 ++++++++++++++++++-
|
| 17 | .../DatePeriod_double_constructor_call.phpt | 14 +++++++++++++
|
| 18 | 2 files changed, 33 insertions(+), 1 deletion(-)
|
| 19 | create mode 100644 ext/date/tests/DatePeriod_double_constructor_call.phpt
|
| 20 |
|
| 21 | diff --git a/ext/date/php_date.c b/ext/date/php_date.c
|
| 22 | index fe58eba5c89..6b3842e64be 100644
|
| 23 | |
| 24 | |
| 25 | @@ -4283,6 +4283,23 @@ static bool date_period_initialize(timelib_time **st, timelib_time **et, timelib
|
| 26 | return retval;
|
| 27 | } /* }}} */
|
| 28 |
|
| 29 | +static void date_period_reset(php_period_obj *period_obj)
|
| 30 | +{
|
| 31 | + if (period_obj->start) {
|
| 32 | + timelib_time_dtor(period_obj->start);
|
| 33 | + }
|
| 34 | + if (period_obj->current) {
|
| 35 | + timelib_time_dtor(period_obj->current);
|
| 36 | + }
|
| 37 | + if (period_obj->end) {
|
| 38 | + timelib_time_dtor(period_obj->end);
|
| 39 | + }
|
| 40 | + if (period_obj->interval) {
|
| 41 | + timelib_rel_time_dtor(period_obj->interval);
|
| 42 | + }
|
| 43 | + memset(period_obj, 0, XtOffsetOf(php_period_obj, std));
|
| 44 | +}
|
| 45 | +
|
| 46 | /* {{{ Creates new DatePeriod object. */
|
| 47 | PHP_METHOD(DatePeriod, __construct)
|
| 48 | {
|
| 49 | @@ -4304,7 +4321,7 @@ PHP_METHOD(DatePeriod, __construct)
|
| 50 | }
|
| 51 |
|
| 52 | dpobj = Z_PHPPERIOD_P(ZEND_THIS);
|
| 53 | - dpobj->current = NULL;
|
| 54 | + date_period_reset(dpobj);
|
| 55 |
|
| 56 | if (isostr) {
|
| 57 | if (!date_period_initialize(&(dpobj->start), &(dpobj->end), &(dpobj->interval), &recurrences, isostr, isostr_len)) {
|
| 58 | @@ -4343,6 +4360,7 @@ PHP_METHOD(DatePeriod, __construct)
|
| 59 | if (end) {
|
| 60 | DATE_CHECK_INITIALIZED(Z_PHPDATE_P(end)->time, DateTimeInterface);
|
| 61 | }
|
| 62 | + DATE_CHECK_INITIALIZED(Z_PHPINTERVAL_P(interval)->initialized, DateInterval);
|
| 63 |
|
| 64 | /* init */
|
| 65 | php_interval_obj *intobj = Z_PHPINTERVAL_P(interval);
|
| 66 | diff --git a/ext/date/tests/DatePeriod_double_constructor_call.phpt b/ext/date/tests/DatePeriod_double_constructor_call.phpt
|
| 67 | new file mode 100644
|
| 68 | index 00000000000..551d2727282
|
| 69 | |
| 70 | |
| 71 | @@ -0,0 +1,14 @@
|
| 72 | +--TEST--
|
| 73 | +Double DatePeriod::__construct() call
|
| 74 | +--FILE--
|
| 75 | +<?php
|
| 76 | +
|
| 77 | +$start = new \DateTime();
|
| 78 | +$interval = new \DateInterval('P1D');
|
| 79 | +$period = new \DatePeriod($start, $interval, 1);
|
| 80 | +$period->__construct($start, $interval, 1);
|
| 81 | +
|
| 82 | +?>
|
| 83 | +===DONE===
|
| 84 | +--EXPECT--
|
| 85 | +===DONE===
|