Skip to content

Commit 44b11b7

Browse files
authored
ext/Intl: Fix IntlIterator::current() on invalid iterators (php#22495)
IntlIterator::current() could expose an undefined zval when called before theiterator is positioned, or after the iterator becomes invalid. In these cases we directly returns the undefined zval and cause to a UNKNOWN:0 output in userland. Generally, a NULL output would be more proper.
1 parent 958bcb0 commit 44b11b7

4 files changed

Lines changed: 28 additions & 4 deletions

File tree

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ PHP NEWS
107107
as float rather than int on 64-bit platforms. (Weilin Du)
108108
. Fixed UConverter::transcode() silently truncating from_subst and to_subst
109109
option lengths greater than 127 bytes. (Weilin Du)
110+
. Fixed IntlIterator::current() to return NULL instead of an undefined value
111+
when the iterator is not positioned on a valid element. (Weilin Du)
110112

111113
- IO:
112114
. Added new polling API. (Jakub Zelenka)

docs/source/core/data-structures/zend_string.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ in bytes, and the ``val`` field contains the actual string data.
2929

3030
You may wonder why the ``val`` field is declared as ``char val[1]``. This is called the `struct
3131
hack`_ in C. It is used to create structs with a flexible size, namely by allowing the last element
32-
to be expanded arbitrarily. In this case, the size of ``zend_string`` depends on the string's length,
33-
which is determined at runtime (see ``_ZSTR_STRUCT_SIZE``). When allocating the string, we append
34-
enough bytes to the allocation to hold the strings content.
32+
to be expanded arbitrarily. In this case, the size of ``zend_string`` depends on the string's
33+
length, which is determined at runtime (see ``_ZSTR_STRUCT_SIZE``). When allocating the string, we
34+
append enough bytes to the allocation to hold the strings content.
3535

3636
.. _struct hack: https://www.geeksforgeeks.org/struct-hack/
3737

ext/intl/common/common_enum.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ PHP_METHOD(IntlIterator, current)
226226

227227
INTLITERATOR_METHOD_FETCH_OBJECT;
228228
data = ii->iterator->funcs->get_current_data(ii->iterator);
229-
if (data) {
229+
if (data && !Z_ISUNDEF_P(data)) {
230230
RETURN_COPY_DEREF(data);
231231
}
232232
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
IntlIterator::current() returns null when the iterator is not valid
3+
--EXTENSIONS--
4+
intl
5+
--FILE--
6+
<?php
7+
$iterator = IntlBreakIterator::createWordInstance('en_US')->getPartsIterator();
8+
var_dump($iterator->current());
9+
10+
$breakIterator = IntlBreakIterator::createWordInstance('en_US');
11+
$breakIterator->setText('foo');
12+
$iterator = $breakIterator->getPartsIterator();
13+
$iterator->rewind();
14+
$iterator->next();
15+
$iterator->next();
16+
var_dump($iterator->valid());
17+
var_dump($iterator->current());
18+
?>
19+
--EXPECT--
20+
NULL
21+
bool(false)
22+
NULL

0 commit comments

Comments
 (0)