Bug #70232 [NEW]: Incorrect bump-along behavior with \K and empty string match
| From: | nhahtdh at gmail dot com | Date: | Tue, 11 Aug 2015 04:57:21 +0000 |
| Subject: | Bug #70232 [NEW]: Incorrect bump-along behavior with \K and empty string match | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-195101@lists.php.net to get a copy of this message | ||
From: nhahtdh at gmail dot com
Operating system:
PHP version: 5.6.12
Package: PCRE related
Bug Type: Bug
Bug description:Incorrect bump-along behavior with \K and empty string match
Description:
------------
Please see the test case, the expected result and the actual result in
the bug report below.
From analyzing the code, I have identified that the error comes from the
following line of code (plus similar code in other functions):
https://github.com/php/php-src/blob/0787cd60ed3d0c8c8c8ff7e49b9bb3587bf33b64/ext/pcre/php_pcre.c#L891
g_notempty = (offsets[1] == offsets[0])? PCRE_NOTEMPTY | PCRE_ANCHORED
: 0;
/* Advance to the position right after the last full match */
start_offset = offsets[1];
This part of the code checks whether the match is empty. If the match it
empty, it tries to perform another match from the last position of the
match with PCRE_NOTEMPTY flag to force the match to be non-empty.
However, it's incorrect to set the PCRE_NOTEMPTY flag by checking the
length of the match based on the start and end indices of the match. For
the regex in the test case ~(?: |\G)\d\B\K~ (which always results in
empty string matches due to \K), the index where we execute the match
from (start_offset) and the start index of the match (offsets[0]) are
always different. Therefore, the regex actually advances ahead in the
string, and setting PCRE_NOTEMPTY in such case rejects valid empty
string matches.
I believe (offsets[1] == offsets[0]) should be changed to (offsets[1] ==
start_offset). If start_offset <= offsets[0] <= offsets[1] is an
invariant, then the change should be correct.
Original report and analysis:
http://chat.stackoverflow.com/transcript/message/24995536#24995536
Test script:
---------------
<?
$str = "123 a123 1234567 b123 123";
$str = preg_replace('~(?: |\G)\d\B\K~', "*", $str);
echo $str;
?>
Expected result:
----------------
1*2*3 a123 1*2*3*4*5*6*7 b123 1*2*3
The expected result (10 matches/replacements) can be observed on
- pcretest with PCRE version 8.35 2014-04-04
- regex101 https://regex101.com/r/oP9mZ7/3
Actual result:
--------------
1*23 a123 1*23*45*67 b123 1*23
--
Edit bug report at https://bugs.php.net/bug.php?id=70232&edit=1
--
Try a snapshot (PHP 5.4): https://bugs.php.net/fix.php?id=70232&r=trysnapshot54
Try a snapshot (PHP 5.5): https://bugs.php.net/fix.php?id=70232&r=trysnapshot55
Try a snapshot (trunk): https://bugs.php.net/fix.php?id=70232&r=trysnapshottrunk
Fixed in SVN: https://bugs.php.net/fix.php?id=70232&r=fixed
Fixed in release: https://bugs.php.net/fix.php?id=70232&r=alreadyfixed
Need backtrace: https://bugs.php.net/fix.php?id=70232&r=needtrace
Need Reproduce Script: https://bugs.php.net/fix.php?id=70232&r=needscript
Try newer version: https://bugs.php.net/fix.php?id=70232&r=oldversion
Not developer issue: https://bugs.php.net/fix.php?id=70232&r=support
Expected behavior: https://bugs.php.net/fix.php?id=70232&r=notwrong
Not enough info: https://bugs.php.net/fix.php?id=70232&r=notenoughinfo
Submitted twice: https://bugs.php.net/fix.php?id=70232&r=submittedtwice
register_globals: https://bugs.php.net/fix.php?id=70232&r=globals
PHP 4 support discontinued: https://bugs.php.net/fix.php?id=70232&r=php4
Daylight Savings: https://bugs.php.net/fix.php?id=70232&r=dst
IIS Stability: https://bugs.php.net/fix.php?id=70232&r=isapi
Install GNU Sed: https://bugs.php.net/fix.php?id=70232&r=gnused
Floating point limitations: https://bugs.php.net/fix.php?id=70232&r=float
No Zend Extensions: https://bugs.php.net/fix.php?id=70232&r=nozend
MySQL Configuration Error: https://bugs.php.net/fix.php?id=70232&r=mysqlcfg