[php-src] PHP-8.5: Merge branch 'PHP-8.4' into PHP-8.5

Ilia Alshanetsky <[email protected]>
Newsgroups gmane.comp.php.cvs.general
Message-ID <[email protected]>
Author: Ilia Alshanetsky (iliaal)
Date: 2026-08-26T16:19:10-04:00

Commit: https://github.com/php/php-src/commit/24c5a32c6af321afa2f60774603e9db3b8611d26
Raw diff: https://github.com/php/php-src/commit/24c5a32c6af321afa2f60774603e9db3b8611d26.diff

Merge branch 'PHP-8.4' into PHP-8.5

* PHP-8.4:
  [intl] fix leak when iterating IntlBreakIterator parts iterators

Changed paths:
  A  ext/intl/tests/breakiter_parts_iterator_current_leak.phpt
  M  NEWS
  M  ext/intl/breakiterator/breakiterator_iterators.cpp
  M  ext/intl/common/common_enum.cpp


Diff:

diff --git a/NEWS b/NEWS
index 3b865718f09d..149fea347077 100644
--- a/NEWS
+++ b/NEWS
@@ -26,6 +26,8 @@ PHP                                                                        NEWS
   . Fixed bug GH-19320 (FPM UID and GID overflow). (Pratik Bhujel)
 
 - Intl:
+  . Fixed a memory leak when iterating IntlBreakIterator::getPartsIterator()
+    results. (iliaal)
   . Fixed a double-free when IntlGregorianCalendar construction fails after
     the ICU constructor adopts the TimeZone. (iliaal)
   . Fixed bug GH-23094 (NumberFormatter parsing offsets use UTF-16 positions
diff --git a/ext/intl/breakiterator/breakiterator_iterators.cpp b/ext/intl/breakiterator/breakiterator_iterators.cpp
index 34176bf90e52..d6fc5669f3db 100644
--- a/ext/intl/breakiterator/breakiterator_iterators.cpp
+++ b/ext/intl/breakiterator/breakiterator_iterators.cpp
@@ -242,7 +242,7 @@ void IntlIterator_from_BreakIterator_parts(zval *break_iter_zv,
 	ii->iterator->index = 0;
 
 	((zoi_with_current*)ii->iterator)->destroy_it = _breakiterator_parts_destroy_it;
-	ZVAL_OBJ_COPY(&((zoi_with_current*)ii->iterator)->wrapping_obj, Z_OBJ_P(object));
+	ZVAL_UNDEF(&((zoi_with_current*)ii->iterator)->wrapping_obj);
 	ZVAL_UNDEF(&((zoi_with_current*)ii->iterator)->current);
 
 	((zoi_break_iter_parts*)ii->iterator)->bio = Z_INTL_BREAKITERATOR_P(break_iter_zv);
diff --git a/ext/intl/common/common_enum.cpp b/ext/intl/common/common_enum.cpp
index 8cf9796717f4..25545a1bf994 100644
--- a/ext/intl/common/common_enum.cpp
+++ b/ext/intl/common/common_enum.cpp
@@ -39,6 +39,8 @@ zend_object_handlers IntlIterator_handlers;
 void zoi_with_current_dtor(zend_object_iterator *iter)
 {
 	zoi_with_current *zoiwc = (zoi_with_current*)iter;
+	iter->funcs->invalidate_current(iter);
+	zoiwc->destroy_it(iter);
 	zval_ptr_dtor(&zoiwc->wrapping_obj);
 	ZVAL_UNDEF(&zoiwc->wrapping_obj);
 }
@@ -149,7 +151,6 @@ static void IntlIterator_objects_dtor(zend_object *object)
 {
 	IntlIterator_object	*ii = php_intl_iterator_fetch_object(object);
 	if (ii->iterator) {
-		((zoi_with_current*)ii->iterator)->destroy_it(ii->iterator);
 		OBJ_RELEASE(&ii->iterator->std);
 		ii->iterator = NULL;
 	}
diff --git a/ext/intl/tests/breakiter_parts_iterator_current_leak.phpt b/ext/intl/tests/breakiter_parts_iterator_current_leak.phpt
new file mode 100644
index 000000000000..a006d7f2f792
--- /dev/null
+++ b/ext/intl/tests/breakiter_parts_iterator_current_leak.phpt
@@ -0,0 +1,31 @@
+--TEST--
+IntlPartsIterator must not leak, and a temporary one must not dangle
+--EXTENSIONS--
+intl
+--FILE--
+<?php
+function parts(): IntlPartsIterator {
+    $bi = IntlBreakIterator::createWordInstance('en');
+    $bi->setText('hello world');
+    return $bi->getPartsIterator();
+}
+
+foreach (parts() as $part) {
+    echo "[$part]\n";
+}
+
+$bi = IntlBreakIterator::createWordInstance('en');
+$bi->setText('hello world foo bar baz');
+$m0 = memory_get_usage();
+for ($i = 0; $i < 20000; $i++) {
+    foreach ($bi->getPartsIterator() as $v) {
+        break;
+    }
+}
+var_dump(memory_get_usage() - $m0 < 1024 * 1024);
+?>
+--EXPECT--
+[hello]
+[ ]
+[world]
+bool(true)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.