diff --git a/NEWS b/NEWS index e56e562a4c92..f7de9265c750 100644 --- a/NEWS +++ b/NEWS @@ -25,6 +25,8 @@ PHP NEWS wrong argument in error messages. (Weilin Du) - 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 6817f52ffb02..be98a1ea3e04 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 58ebeabcb406..79853f7f6ef5 100644 --- a/ext/intl/common/common_enum.cpp +++ b/ext/intl/common/common_enum.cpp @@ -35,6 +35,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); } @@ -147,7 +149,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-- +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)