php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #73483 Segmentation fault
Submitted: 2016-11-09 12:06 UTC Modified: 2016-11-14 04:35 UTC
From: alex at buayacorp dot com Assigned: dmitry (profile)
Status: Closed Package: PCRE related
PHP Version: 7.0.12 OS: debian wheezy
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: alex at buayacorp dot com
New email:
PHP Version: OS:

 

 [2016-11-09 12:06 UTC] alex at buayacorp dot com
Description:
------------
We've noticed a few segmentation faults in some of our servers. I am able to consistently reproduce it in a debian wheezy vm with the test script below.

alex@atoq-wheezy:~/php-7.0.12$ uname -a
Linux atoq-wheezy 3.2.0-4-amd64 #1 SMP Debian 3.2.82-1 x86_64 GNU/Linux
alex@atoq-wheezy:~/php-7.0.12$ locale
LANG=en_US.UTF-8
LANGUAGE=en_US:en
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=

# PHP compiled with --disable-all flag.
alex@atoq-wheezy:~/php-7.0.12$ sapi/cli/php -v
PHP 7.0.12 (cli) (built: Nov  9 2016 11:29:49) ( NTS )
Copyright (c) 1997-2016 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2016 Zend Technologies

The script works fine in the same VM under PHP 5.6.27.
# PHP compiled with --disable-all flag.
alex@atoq-wheezy:~/php-5.6.27$ sapi/cli/php ../segfault.php
string(22) "<p>hola</p><p>hola</p>"

Test script:
---------------
https://gist.github.com/xknown/b0bdcfa87edf039e995822d86cfde441

Expected result:
----------------
string(22) "<p>hola</p><p>hola</p>"

Actual result:
--------------
alex@atoq-wheezy:~/php-7.0.12$ sapi/cli/php -dpcre.jit=0 ../segfault.php
NULL

alex@atoq-wheezy:~/php-7.0.12$ sapi/cli/php -dpcre.jit=1 ../segfault.php
NULL
Segmentation fault


Patches

use-regex-cache-key-with-locale (last revision 2016-11-10 15:32 UTC by alex at buayacorp dot com)

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-11-09 15:33 UTC] cmb@php.net
-Status: Open +Status: Verified -Assigned To: +Assigned To: dmitry
 [2016-11-09 15:33 UTC] cmb@php.net
This issue is apparently locale related. For instance, the script works
fine if the locale is "C", see <https://3v4l.org/4IVgb>. Alternatively,
commenting out line 58[1] will also let the script succeed.

Anyhow, the behavioral change had been introduced with commit
4514ba01[2].

Dmitry, can you please have a look at this issue?

[1] <https://gist.github.com/xknown/b0bdcfa87edf039e995822d86cfde441#file-segfault-php-L58>
[2] <http://git.php.net/?p=php-src.git;a=commit;h=4514ba016ff158cd113deef1a215fcdcb6913b48>
 [2016-11-10 15:30 UTC] alex at buayacorp dot com
After looking a little bit more into this issue I think this happens because the update logic of already cached items doesn't really take into account locale changes.

For example, if a regex A was cached with locale X, then `pcre_get_compiled_regex_cache ` will store it as `H(x, compiled(A))`. If this cached value is still in use (i.e. preg_replace_callback in the provided script) AND the locale changes to Y, then `pcre_get_compiled_regex_cache` will update the entry `H(x, compiled(B))` (via zend_hash_update_mem), this will override the refere that's still in use for `H(x, compiled(A))`.
 [2016-11-10 15:34 UTC] alex at buayacorp dot com
I added a naive patch that uses a combination of regex+locale (if available) which seems to fix this issue.
 [2016-11-14 04:34 UTC] laruence@php.net
I got another patch, which could get rid of the pce->locale checks at all.

https://gist.github.com/laruence/44287a993205fe0ac75321db959ea121

thanks
 [2016-11-14 04:35 UTC] laruence@php.net
And a simpler reproduce script:

<?php
$regex = "#dummy#";
setlocale(LC_ALL, "C");
preg_replace_callback($regex, function (array $matches) use($regex) {
    setlocale(LC_ALL, "en_US");
    preg_replace($regex, "A", "A");
    setlocale(LC_ALL, "C");
}, "dummy");
 [2016-11-14 09:05 UTC] alex at buayacorp dot com
Thanks. I am not longer able to reproduce this issue with the patch above.
 [2016-11-20 07:53 UTC] laruence@php.net
Automatic comment on behalf of laruence@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=ebfd93f725eb9b9cfadbbde98047efe76f658da6
Log: Fixed bug #73483 (Segmentation fault on pcre_replace_callback)
 [2016-11-20 07:53 UTC] laruence@php.net
-Status: Verified +Status: Closed
 [2016-11-22 13:14 UTC] krakjoe@php.net
Automatic comment on behalf of laruence@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=ebfd93f725eb9b9cfadbbde98047efe76f658da6
Log: Fixed bug #73483 (Segmentation fault on pcre_replace_callback)
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 13:01:29 2024 UTC