From b5943e948f8bff295ec0a23e3c4832ba19b0218e Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Sun, 16 Aug 2026 12:36:22 -0400 Subject: [PATCH] Fix IntlGregorianCalendar double-free of an adopted TimeZone GregorianCalendar(TimeZone*, ...) adopts the zone in the constructor. On U_FAILURE the calendar destructor already deletes that zone. Remove the extra delete tz. The 8.5/master unique_ptr path has the same extra delete after the smart pointer already destroyed the calendar. --- NEWS | 4 ++++ .../calendar/gregoriancalendar_methods.cpp | 1 - .../gregoriancalendar_adopt_timezone.phpt | 21 +++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 ext/intl/tests/gregoriancalendar_adopt_timezone.phpt diff --git a/NEWS b/NEWS index ecb4d105e917..24b817b7a6f9 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,10 @@ PHP NEWS . Fixed bug GH-15375 (Nested "yield from" skips items after a valid() or next() call on the inner generator). (iliaal) +- Intl: + . Fixed a double-free when IntlGregorianCalendar construction fails after + the ICU constructor adopts the TimeZone. (iliaal) + - Opcache: . Fixed opcache.protect_memory race under ZTS. (realFlowControl) diff --git a/ext/intl/calendar/gregoriancalendar_methods.cpp b/ext/intl/calendar/gregoriancalendar_methods.cpp index 0b36e621ef7f..0725cb4582fd 100644 --- a/ext/intl/calendar/gregoriancalendar_methods.cpp +++ b/ext/intl/calendar/gregoriancalendar_methods.cpp @@ -168,7 +168,6 @@ static void _php_intlgregcal_constructor_body( if (gcal) { delete gcal; } - delete tz; if (!is_constructor) { zval_ptr_dtor(return_value); RETVAL_NULL(); diff --git a/ext/intl/tests/gregoriancalendar_adopt_timezone.phpt b/ext/intl/tests/gregoriancalendar_adopt_timezone.phpt new file mode 100644 index 000000000000..7afe4290f2ed --- /dev/null +++ b/ext/intl/tests/gregoriancalendar_adopt_timezone.phpt @@ -0,0 +1,21 @@ +--TEST-- +IntlGregorianCalendar timezone-and-locale constructor adopts the TimeZone +--EXTENSIONS-- +intl +--INI-- +date.timezone=UTC +--FILE-- +getTimeZone()->getID(), "\n"; +echo $cal->getType(), "\n"; + +$cal2 = IntlGregorianCalendar::createInstance('UTC', 'en_US'); +echo $cal2->getTimeZone()->getID(), "\n"; + +?> +--EXPECT-- +Europe/Amsterdam +gregorian +UTC