[php-src] master: Merge branch '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:11-04:00
Commit: https://github.com/php/php-src/commit/53c3116c380ee629c35931ba02881ebb9b3d006f
Raw diff: https://github.com/php/php-src/commit/53c3116c380ee629c35931ba02881ebb9b3d006f.diff
Merge branch 'PHP-8.5'
* PHP-8.5:
[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 50c3346e17a3..41ee6be929d6 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,8 @@ PHP NEWS
100-continue flow control). (Sjoerd Langkemper)
- Intl:
+ . Fixed a memory leak when iterating IntlBreakIterator::getPartsIterator()
+ results. (iliaal)
. Fixed a leak in Locale::getKeywords() when a keyword value cannot be
read. (iliaal)
diff --git a/ext/intl/breakiterator/breakiterator_iterators.cpp b/ext/intl/breakiterator/breakiterator_iterators.cpp
index d792a6367139..def0fa9d9fc5 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 4260e3cce57f..16c892074915 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)