diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index 353eaecca24..84d8eb961bd 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -1890,12 +1890,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); @@ -1912,7 +1917,7 @@ PHP_METHOD(RegexIterator, accept) if (intern->u.regex.flags & REGIT_INVERTED) { RETVAL_BOOL(Z_TYPE_P(return_value) != IS_TRUE); } - zend_string_release_ex(subject, 0); + zend_string_release_ex(subject, false); } /* }}} */ /* {{{ Returns current regular expression */ diff --git a/ext/spl/tests/gh14290.phpt b/ext/spl/tests/gh14290.phpt new file mode 100644 index 00000000000..37aba63c80a --- /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