Merge branch 'PHP-5.6'

* PHP-5.6:
  Fix #70232: Incorrect bump-along behavior with \K and empty string match

Resolved conflicts:
	ext/pcre/php_pcre.c
This commit is contained in:
Christoph M. Becker 2015-08-13 14:28:16 +02:00
commit 1ec40e84d4
2 changed files with 82 additions and 9 deletions

View File

@ -44,6 +44,11 @@
#define PCRE_CACHE_SIZE 4096
/* not fully functional workaround for libpcre < 8.0, see bug #70232 */
#ifndef PCRE_NOTEMPTY_ATSTART
# define PCRE_NOTEMPTY_ATSTART PCRE_NOTEMPTY
#endif
enum {
PHP_PCRE_NO_ERROR = 0,
PHP_PCRE_INTERNAL_ERROR,
@ -876,7 +881,7 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
pcre_free((void *) stringlist);
}
} else if (count == PCRE_ERROR_NOMATCH) {
/* If we previously set PCRE_NOTEMPTY after a null match,
/* If we previously set PCRE_NOTEMPTY_ATSTART after a null match,
this is not necessarily the end. We need to advance
the start offset, and continue. Fudge the offset values
to achieve this, unless we're already at the end of the string. */
@ -893,10 +898,10 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
}
/* If we have matched an empty string, mimic what Perl's /g options does.
This turns out to be rather cunning. First we set PCRE_NOTEMPTY and try
This turns out to be rather cunning. First we set PCRE_NOTEMPTY_ATSTART and try
the match again at the same point. If this fails (picked up above) we
advance to the next character. */
g_notempty = (offsets[1] == offsets[0])? PCRE_NOTEMPTY | PCRE_ANCHORED : 0;
g_notempty = (offsets[1] == offsets[0])? PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED : 0;
/* Advance to the position right after the last full match */
start_offset = offsets[1];
@ -1271,7 +1276,7 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
limit--;
}
} else if (count == PCRE_ERROR_NOMATCH || UNEXPECTED(limit == 0)) {
/* If we previously set PCRE_NOTEMPTY after a null match,
/* If we previously set PCRE_NOTEMPTY_ATSTART after a null match,
this is not necessarily the end. We need to advance
the start offset, and continue. Fudge the offset values
to achieve this, unless we're already at the end of the string. */
@ -1313,10 +1318,10 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
}
/* If we have matched an empty string, mimic what Perl's /g options does.
This turns out to be rather cunning. First we set PCRE_NOTEMPTY and try
This turns out to be rather cunning. First we set PCRE_NOTEMPTY_ATSTART and try
the match again at the same point. If this fails (picked up above) we
advance to the next character. */
g_notempty = (offsets[1] == offsets[0])? PCRE_NOTEMPTY | PCRE_ANCHORED : 0;
g_notempty = (offsets[1] == offsets[0])? PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED : 0;
/* Advance to the next piece. */
start_offset = offsets[1];
@ -1815,7 +1820,7 @@ PHPAPI void php_pcre_split_impl(pcre_cache_entry *pce, char *subject, int subjec
}
}
} else if (count == PCRE_ERROR_NOMATCH) {
/* If we previously set PCRE_NOTEMPTY after a null match,
/* If we previously set PCRE_NOTEMPTY_ATSTART after a null match,
this is not necessarily the end. We need to advance
the start offset, and continue. Fudge the offset values
to achieve this, unless we're already at the end of the string. */
@ -1849,10 +1854,10 @@ PHPAPI void php_pcre_split_impl(pcre_cache_entry *pce, char *subject, int subjec
}
/* If we have matched an empty string, mimic what Perl's /g options does.
This turns out to be rather cunning. First we set PCRE_NOTEMPTY and try
This turns out to be rather cunning. First we set PCRE_NOTEMPTY_ATSTART and try
the match again at the same point. If this fails (picked up above) we
advance to the next character. */
g_notempty = (offsets[1] == offsets[0])? PCRE_NOTEMPTY | PCRE_ANCHORED : 0;
g_notempty = (offsets[1] == offsets[0])? PCRE_NOTEMPTY_ATSTART | PCRE_ANCHORED : 0;
/* Advance to the position right after the last full match */
start_offset = offsets[1];

View File

@ -0,0 +1,68 @@
--TEST--
Bug #70232 (Incorrect bump-along behavior with \K and empty string match)
--SKIPIF--
<?php
if (version_compare(explode(' ', PCRE_VERSION)[0], '8.0', 'lt')) {
die("skip this test requires libpcre >= 8.0");
}
?>
--FILE--
<?php
$pattern = '~(?: |\G)\d\B\K~';
$subject = "123 a123 1234567 b123 123";
preg_match_all($pattern, $subject, $matches);
var_dump($matches);
var_dump(preg_replace($pattern, "*", $subject));
var_dump(preg_split($pattern, $subject));
?>
--EXPECT--
array(1) {
[0]=>
array(10) {
[0]=>
string(0) ""
[1]=>
string(0) ""
[2]=>
string(0) ""
[3]=>
string(0) ""
[4]=>
string(0) ""
[5]=>
string(0) ""
[6]=>
string(0) ""
[7]=>
string(0) ""
[8]=>
string(0) ""
[9]=>
string(0) ""
}
}
string(35) "1*2*3 a123 1*2*3*4*5*6*7 b123 1*2*3"
array(11) {
[0]=>
string(1) "1"
[1]=>
string(1) "2"
[2]=>
string(8) "3 a123 1"
[3]=>
string(1) "2"
[4]=>
string(1) "3"
[5]=>
string(1) "4"
[6]=>
string(1) "5"
[7]=>
string(1) "6"
[8]=>
string(8) "7 b123 1"
[9]=>
string(1) "2"
[10]=>
string(1) "3"
}