Skip to content

Commit b3a56bd

Browse files
committed
Fix phpGH-14290: Member access within null pointer in extension spl
php_pcre_replace_impl() can fail and return NULL. We should take that error condition into account. Because other failures return false, we return false here as well. At first, I also thought there was a potential memory leak in the error check of replacement_str, but found that the error condition can never trigger, so replace that with an assertion. Closes phpGH-14292.
1 parent c69c84a commit b3a56bd

File tree

3 files changed

+28
-4
lines changed

3 files changed

+28
-4
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? ????, PHP 8.2.21
44

5+
- SPL:
6+
. Fixed bug GH-14290 (Member access within null pointer in extension spl).
7+
(nielsdos)
58

69
06 Jun 2024, PHP 8.2.20
710

ext/spl/spl_iterators.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1904,12 +1904,17 @@ PHP_METHOD(RegexIterator, accept)
19041904
zval *replacement = zend_read_property(intern->std.ce, Z_OBJ_P(ZEND_THIS), "replacement", sizeof("replacement")-1, 1, &rv);
19051905
zend_string *replacement_str = zval_try_get_string(replacement);
19061906

1907-
if (UNEXPECTED(!replacement_str)) {
1908-
RETURN_THROWS();
1909-
}
1907+
/* Property type is ?string, so this should always succeed. */
1908+
ZEND_ASSERT(replacement_str != NULL);
19101909

19111910
result = php_pcre_replace_impl(intern->u.regex.pce, subject, ZSTR_VAL(subject), ZSTR_LEN(subject), replacement_str, -1, &count);
19121911

1912+
if (UNEXPECTED(!result)) {
1913+
zend_string_release(replacement_str);
1914+
zend_string_release_ex(subject, false);
1915+
RETURN_FALSE;
1916+
}
1917+
19131918
if (intern->u.regex.flags & REGIT_USE_KEY) {
19141919
zval_ptr_dtor(&intern->current.key);
19151920
ZVAL_STR(&intern->current.key, result);
@@ -1926,7 +1931,7 @@ PHP_METHOD(RegexIterator, accept)
19261931
if (intern->u.regex.flags & REGIT_INVERTED) {
19271932
RETVAL_BOOL(Z_TYPE_P(return_value) != IS_TRUE);
19281933
}
1929-
zend_string_release_ex(subject, 0);
1934+
zend_string_release_ex(subject, false);
19301935
} /* }}} */
19311936

19321937
/* {{{ Returns current regular expression */

ext/spl/tests/gh14290.phpt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
GH-14290 (Member access within null pointer in extension spl)
3+
--INI--
4+
pcre.backtrack_limit=2
5+
pcre.jit=0
6+
--FILE--
7+
<?php
8+
$h = new ArrayIterator(['test' => 'test1']);
9+
$i = new RegexIterator($h, '/^test(.*)/', RegexIterator::REPLACE);
10+
foreach ($i as $name => $value) {
11+
var_dump($name, $value);
12+
}
13+
echo "Done\n";
14+
?>
15+
--EXPECT--
16+
Done

0 commit comments

Comments
 (0)