Skip to content

Fix a NULL pointer dereference bug lead by php_pcre_replace_impl() #8271

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

zhou1615
Copy link
Contributor

php_pcre_replace_impl() will return NULL on failure. However in the function
zim_RegexIterator_accept(), the return value of php_pcre_replace_impl()
is directly used without any check, which could lead to NULL
pointer dereference.

Fix this by adding a NULL check.

This bug is found by a static analyzer, so it is hard to reproduce it.

@cmb69
Copy link
Member

cmb69 commented Mar 29, 2022

Thanks for the new PR! This is definitely an issue that needs to be fixed in PHP-8.0 and up; I'm not quite sure about what should happen in case php_pcre_replace_impl() returns NULL: throw an exception, raise a warning, or just silently fail like it is now in this PR.

Anyhow, a test case matching the PR as is (without the fix, this reproduces the segfault):

--TEST--
NULL pointer dereference in RegexIterator::accept()
--FILE--
<?php
function words() {
    foreach (["f\xC3oo", "bar", "baz"] as $word) {
        yield $word;
    }
}

$it = new RegexIterator(words(), '/a/u', RegexIterator::REPLACE);
var_dump(iterator_to_array($it));
?>
--EXPECT--
array(2) {
  [1]=>
  string(2) "br"
  [2]=>
  string(2) "bz"
}

@Girgias
Copy link
Member

Girgias commented Apr 1, 2022

Thanks for the new PR! This is definitely an issue that needs to be fixed in PHP-8.0 and up; I'm not quite sure about what should happen in case php_pcre_replace_impl() returns NULL: throw an exception, raise a warning, or just silently fail like it is now in this PR.

Anyhow, a test case matching the PR as is (without the fix, this reproduces the segfault):

--TEST--
NULL pointer dereference in RegexIterator::accept()
--FILE--
<?php
function words() {
    foreach (["f\xC3oo", "bar", "baz"] as $word) {
        yield $word;
    }
}

$it = new RegexIterator(words(), '/a/u', RegexIterator::REPLACE);
var_dump(iterator_to_array($it));
?>
--EXPECT--
array(2) {
  [1]=>
  string(2) "br"
  [2]=>
  string(2) "bz"
}

If this segfaulted before I suppose we can add an exception? As this seems to be some sort of bug

@cmb69
Copy link
Member

cmb69 commented Apr 1, 2022

If this segfaulted before I suppose we can add an exception? As this seems to be some sort of bug

Yes, I think the edge-case of a failing preg_replace() has not been properly handled so far.

php_pcre_replace_impl() will return NULL on failure. However in the function
zim_RegexIterator_accept(), the return value of php_pcre_replace_impl()
is directly used without any check, which could lead to NULL
pointer dereference.

Fix this by adding a NULL check.
@zhou1615 zhou1615 force-pushed the php_pcre_replace_impl branch from 8f46842 to 60bf71d Compare April 19, 2022 02:39
Girgias added a commit to Girgias/php-src that referenced this pull request Feb 6, 2023
… SPL RegexIterator()

The regex is precompiled during the constructions of the object at line 1424 in spl_iterators.c
Moreover, the warnings emitted by pcre_get_compiled_regex_cache() get promoted to InvalidArgumentExceptions.

php_pcre_replace_impl() will only return NULL in case of an internal PCRE error, something which should not happen.

Closes phpGH-8271
Girgias pushed a commit to Girgias/php-src that referenced this pull request Feb 9, 2023
php_pcre_replace_impl() will return NULL on failure.
However, in the implementation of RegexIterator::accept() the return value of
php_pcre_replace_impl() is directly used without any check,
which leads to a NULL pointer dereference.

Fix this by adding a NULL check, and returning false in that case.

Closes phpGH-8271

Signed-off-by: George Peter Banyard <[email protected]>
Girgias pushed a commit to Girgias/php-src that referenced this pull request Feb 9, 2023
php_pcre_replace_impl() will return NULL on failure.
However, in the implementation of RegexIterator::accept() the return value of
php_pcre_replace_impl() is directly used without any check,
which leads to a NULL pointer dereference.

Fix this by adding a NULL check, and returning false in that case.

Closes phpGH-8271

Signed-off-by: George Peter Banyard <[email protected]>
Girgias pushed a commit to Girgias/php-src that referenced this pull request Feb 13, 2023
php_pcre_replace_impl() will return NULL on failure.
However, in the implementation of RegexIterator::accept() the return value of
php_pcre_replace_impl() is directly used without any check,
which leads to a NULL pointer dereference.

Fix this by adding a NULL check, and returning false in that case.

Closes phpGH-8271

Signed-off-by: George Peter Banyard <[email protected]>
Girgias pushed a commit to Girgias/php-src that referenced this pull request Mar 10, 2023
php_pcre_replace_impl() will return NULL on failure.
However, in the implementation of RegexIterator::accept() the return value of
php_pcre_replace_impl() is directly used without any check,
which leads to a NULL pointer dereference.

Fix this by adding a NULL check, and returning false in that case.

Closes phpGH-8271

Signed-off-by: George Peter Banyard <[email protected]>
Girgias pushed a commit to Girgias/php-src that referenced this pull request Mar 10, 2023
php_pcre_replace_impl() will return NULL on failure.
However, in the implementation of RegexIterator::accept() the return value of
php_pcre_replace_impl() is directly used without any check,
which leads to a NULL pointer dereference.

Fix this by adding a NULL check, and returning false in that case.

Closes phpGH-8271

Signed-off-by: George Peter Banyard <[email protected]>
@nielsdos
Copy link
Member

nielsdos commented Jun 3, 2025

This fix is incomplete as it leaks memory, but fortunately this was already fixed by b3a56bd (including a test)

@nielsdos nielsdos closed this Jun 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants