diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index 2f2b800039e39..d546cfd090c8c 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -1904,12 +1904,17 @@ PHP_METHOD(RegexIterator, accept) zval *replacement = zend_read_property(intern->std.ce, Z_OBJ_P(ZEND_THIS), "replacement", sizeof("replacement")-1, 1, &rv); zend_string *replacement_str = zval_try_get_string(replacement); - if (UNEXPECTED(!replacement_str)) { - RETURN_THROWS(); - } + /* Property type is ?string, so this should always succeed. */ + ZEND_ASSERT(replacement_str != NULL); result = php_pcre_replace_impl(intern->u.regex.pce, subject, ZSTR_VAL(subject), ZSTR_LEN(subject), replacement_str, -1, &count); + if (UNEXPECTED(!result)) { + zend_string_release(replacement_str); + zend_string_release_ex(subject, false); + RETURN_FALSE; + } + if (intern->u.regex.flags & REGIT_USE_KEY) { zval_ptr_dtor(&intern->current.key); ZVAL_STR(&intern->current.key, result); diff --git a/ext/spl/tests/gh14290.phpt b/ext/spl/tests/gh14290.phpt new file mode 100644 index 0000000000000..37aba63c80a3c --- /dev/null +++ b/ext/spl/tests/gh14290.phpt @@ -0,0 +1,16 @@ +--TEST-- +GH-14290 (Member access within null pointer in extension spl) +--INI-- +pcre.backtrack_limit=2 +pcre.jit=0 +--FILE-- + 'test1']); +$i = new RegexIterator($h, '/^test(.*)/', RegexIterator::REPLACE); +foreach ($i as $name => $value) { + var_dump($name, $value); +} +echo "Done\n"; +?> +--EXPECT-- +Done