Merge branch 'pull-request/1303'

* pull-request/1303:
  Distinguish between unmatched subpatterns and empty matches in preg_*()
  news entry for PR #1303
This commit is contained in:
Joe Watkins 2017-01-06 05:46:10 +00:00
commit ee6aaee83a
No known key found for this signature in database
GPG key ID: F9BA0ADA31CBD89E
9 changed files with 554 additions and 43 deletions

3
NEWS
View file

@ -71,6 +71,9 @@ PHP NEWS
. Fixed bug #73800 (sporadic segfault with MYSQLI_OPT_INT_AND_FLOAT_NATIVE). . Fixed bug #73800 (sporadic segfault with MYSQLI_OPT_INT_AND_FLOAT_NATIVE).
(vanviegen) (vanviegen)
- PCRE:
. Fixed bug #61780 (Inconsistent PCRE captures in match results). (cmb)
- PDO: - PDO:
. Add "Sent SQL" to debug dump for emulated prepares. (Adam Baratz) . Add "Sent SQL" to debug dump for emulated prepares. (Adam Baratz)

View file

@ -646,7 +646,11 @@ static inline void add_offset_pair(zval *result, char *str, int len, int offset,
array_init_size(&match_pair, 2); array_init_size(&match_pair, 2);
/* Add (match, offset) to the return value */ /* Add (match, offset) to the return value */
ZVAL_STRINGL(&tmp, str, len); if (offset < 0) { /* unset substring */
ZVAL_NULL(&tmp);
} else {
ZVAL_STRINGL(&tmp, str, len);
}
zend_hash_next_index_insert_new(Z_ARRVAL(match_pair), &tmp); zend_hash_next_index_insert_new(Z_ARRVAL(match_pair), &tmp);
ZVAL_LONG(&tmp, offset); ZVAL_LONG(&tmp, offset);
zend_hash_next_index_insert_new(Z_ARRVAL(match_pair), &tmp); zend_hash_next_index_insert_new(Z_ARRVAL(match_pair), &tmp);
@ -847,8 +851,12 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
} }
} else { } else {
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
add_next_index_stringl(&match_sets[i], (char *)stringlist[i], if (offsets[i<<1] < 0) { /* unset substring */
offsets[(i<<1)+1] - offsets[i<<1]); add_next_index_null(&match_sets[i]);
} else {
add_next_index_stringl(&match_sets[i], (char *)stringlist[i],
offsets[(i<<1)+1] - offsets[i<<1]);
}
} }
} }
/* Add MARK, if available */ /* Add MARK, if available */
@ -861,11 +869,11 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
/* /*
* If the number of captured subpatterns on this run is * If the number of captured subpatterns on this run is
* less than the total possible number, pad the result * less than the total possible number, pad the result
* arrays with empty strings. * arrays with NULLs.
*/ */
if (count < num_subpats) { if (count < num_subpats) {
for (; i < num_subpats; i++) { for (; i < num_subpats; i++) {
add_next_index_string(&match_sets[i], ""); add_next_index_null(&match_sets[i]);
} }
} }
} else { } else {
@ -882,11 +890,19 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
} else { } else {
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
if (subpat_names[i]) { if (subpat_names[i]) {
add_assoc_stringl(&result_set, subpat_names[i], (char *)stringlist[i], if (offsets[i<<1] < 0) { /* unset substring */
add_assoc_null(&result_set, subpat_names[i]);
} else {
add_assoc_stringl(&result_set, subpat_names[i], (char *)stringlist[i],
offsets[(i<<1)+1] - offsets[i<<1]);
}
}
if (offsets[i<<1] < 0) { /* unset substring */
add_next_index_null(&result_set);
} else {
add_next_index_stringl(&result_set, (char *)stringlist[i],
offsets[(i<<1)+1] - offsets[i<<1]); offsets[(i<<1)+1] - offsets[i<<1]);
} }
add_next_index_stringl(&result_set, (char *)stringlist[i],
offsets[(i<<1)+1] - offsets[i<<1]);
} }
} }
} else { } else {
@ -897,8 +913,12 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
} }
} else { } else {
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
add_next_index_stringl(&result_set, (char *)stringlist[i], if (offsets[i<<1] < 0) { /* unset substring */
offsets[(i<<1)+1] - offsets[i<<1]); add_next_index_null(&result_set);
} else {
add_next_index_stringl(&result_set, (char *)stringlist[i],
offsets[(i<<1)+1] - offsets[i<<1]);
}
} }
} }
} }
@ -921,11 +941,19 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
} else { } else {
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
if (subpat_names[i]) { if (subpat_names[i]) {
add_assoc_stringl(subpats, subpat_names[i], (char *)stringlist[i], if (offsets[i<<1] < 0) { /* unset substring */
offsets[(i<<1)+1] - offsets[i<<1]); add_assoc_null(subpats, subpat_names[i]);
} else {
add_assoc_stringl(subpats, subpat_names[i], (char *)stringlist[i],
offsets[(i<<1)+1] - offsets[i<<1]);
}
}
if (offsets[i<<1] < 0) { /* unset substring */
add_next_index_null(subpats);
} else {
add_next_index_stringl(subpats, (char *)stringlist[i],
offsets[(i<<1)+1] - offsets[i<<1]);
} }
add_next_index_stringl(subpats, (char *)stringlist[i],
offsets[(i<<1)+1] - offsets[i<<1]);
} }
} }
} else { } else {
@ -937,8 +965,12 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
} }
} else { } else {
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
add_next_index_stringl(subpats, (char *)stringlist[i], if (offsets[i<<1] < 0) { /* unset substring */
offsets[(i<<1)+1] - offsets[i<<1]); add_next_index_null(subpats);
} else {
add_next_index_stringl(subpats, (char *)stringlist[i],
offsets[(i<<1)+1] - offsets[i<<1]);
}
} }
} }
} }

View file

@ -52,7 +52,7 @@ array(10) {
[2]=> [2]=>
string(2) "06" string(2) "06"
[3]=> [3]=>
string(0) "" NULL
["month"]=> ["month"]=>
string(2) "12" string(2) "12"
[4]=> [4]=>
@ -75,7 +75,7 @@ array(10) {
[2]=> [2]=>
string(2) "12" string(2) "12"
[3]=> [3]=>
string(0) "" NULL
["month"]=> ["month"]=>
string(3) "Aug" string(3) "Aug"
[4]=> [4]=>

View file

@ -58,7 +58,7 @@ array(10) {
[0]=> [0]=>
string(2) "20" string(2) "20"
[1]=> [1]=>
string(0) "" NULL
} }
["month"]=> ["month"]=>
array(2) { array(2) {
@ -127,7 +127,7 @@ array(2) {
[2]=> [2]=>
string(2) "12" string(2) "12"
[3]=> [3]=>
string(0) "" NULL
["month"]=> ["month"]=>
string(3) "Aug" string(3) "Aug"
[4]=> [4]=>

View file

@ -24,7 +24,7 @@ array(2) {
[1]=> [1]=>
string(12) "unsigned int" string(12) "unsigned int"
[2]=> [2]=>
string(0) "" NULL
[3]=> [3]=>
string(0) "" string(0) ""
[4]=> [4]=>
@ -41,13 +41,13 @@ array(2) {
[1]=> [1]=>
string(5) "short" string(5) "short"
[2]=> [2]=>
string(0) "" NULL
[3]=> [3]=>
string(0) "" string(0) ""
[4]=> [4]=>
string(1) "a" string(1) "a"
[5]=> [5]=>
string(0) "" NULL
[6]=> [6]=>
string(3) ", b" string(3) ", b"
} }

View file

@ -0,0 +1,18 @@
--TEST--
Bug #61780 (Inconsistent PCRE captures in match results): basics
--FILE--
<?php
preg_match('/(a)?([a-z]*)(\d*)/', '123', $matches);
var_dump($matches);
?>
--EXPECT--
array(4) {
[0]=>
string(3) "123"
[1]=>
NULL
[2]=>
string(0) ""
[3]=>
string(3) "123"
}

View file

@ -0,0 +1,194 @@
--TEST--
Bug #61780 (Inconsistent PCRE captures in match results): numeric subpatterns
--FILE--
<?php
preg_match('/(4)?(2)?\d/', '23456', $matches);
var_export($matches);
echo "\n\n";
preg_match('/(4)?(2)?\d/', '23456', $matches, PREG_OFFSET_CAPTURE);
var_export($matches);
echo "\n\n";
preg_match_all('/(4)?(2)?\d/', '123456', $matches);
var_export($matches);
echo "\n\n";
preg_match_all('/(4)?(2)?\d/', '123456', $matches, PREG_OFFSET_CAPTURE);
var_export($matches);
echo "\n\n";
preg_match_all('/(4)?(2)?\d/', '123456', $matches, PREG_SET_ORDER);
var_export($matches);
echo "\n\n";
preg_match_all('/(4)?(2)?\d/', '123456', $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
var_export($matches);
?>
--EXPECT--
array (
0 => '23',
1 => NULL,
2 => '2',
)
array (
0 =>
array (
0 => '23',
1 => 0,
),
1 =>
array (
0 => NULL,
1 => -1,
),
2 =>
array (
0 => '2',
1 => 0,
),
)
array (
0 =>
array (
0 => '1',
1 => '23',
2 => '45',
3 => '6',
),
1 =>
array (
0 => NULL,
1 => NULL,
2 => '4',
3 => NULL,
),
2 =>
array (
0 => NULL,
1 => '2',
2 => NULL,
3 => NULL,
),
)
array (
0 =>
array (
0 =>
array (
0 => '1',
1 => 0,
),
1 =>
array (
0 => '23',
1 => 1,
),
2 =>
array (
0 => '45',
1 => 3,
),
3 =>
array (
0 => '6',
1 => 5,
),
),
1 =>
array (
0 => NULL,
1 =>
array (
0 => NULL,
1 => -1,
),
2 =>
array (
0 => '4',
1 => 3,
),
3 => NULL,
),
2 =>
array (
0 => NULL,
1 =>
array (
0 => '2',
1 => 1,
),
2 => NULL,
3 => NULL,
),
)
array (
0 =>
array (
0 => '1',
),
1 =>
array (
0 => '23',
1 => NULL,
2 => '2',
),
2 =>
array (
0 => '45',
1 => '4',
),
3 =>
array (
0 => '6',
),
)
array (
0 =>
array (
0 =>
array (
0 => '1',
1 => 0,
),
),
1 =>
array (
0 =>
array (
0 => '23',
1 => 1,
),
1 =>
array (
0 => NULL,
1 => -1,
),
2 =>
array (
0 => '2',
1 => 1,
),
),
2 =>
array (
0 =>
array (
0 => '45',
1 => 3,
),
1 =>
array (
0 => '4',
1 => 3,
),
),
3 =>
array (
0 =>
array (
0 => '6',
1 => 5,
),
),
)

View file

@ -0,0 +1,264 @@
--TEST--
Bug #61780 (Inconsistent PCRE captures in match results): named subpatterns
--FILE--
<?php
preg_match('/(?<a>4)?(?<b>2)?\d/', '23456', $matches);
var_export($matches);
echo "\n\n";
preg_match('/(?<a>4)?(?<b>2)?\d/', '23456', $matches, PREG_OFFSET_CAPTURE);
var_export($matches);
echo "\n\n";
preg_match_all('/(?<a>4)?(?<b>2)?\d/', '123456', $matches);
var_export($matches);
echo "\n\n";
preg_match_all('/(?<a>4)?(?<b>2)?\d/', '123456', $matches, PREG_OFFSET_CAPTURE);
var_export($matches);
echo "\n\n";
preg_match_all('/(?<a>4)?(?<b>2)?\d/', '123456', $matches, PREG_SET_ORDER);
var_export($matches);
echo "\n\n";
preg_match_all('/(?<a>4)?(?<b>2)?\d/', '123456', $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
var_export($matches);
?>
--EXPECT--
array (
0 => '23',
'a' => NULL,
1 => NULL,
'b' => '2',
2 => '2',
)
array (
0 =>
array (
0 => '23',
1 => 0,
),
'a' =>
array (
0 => NULL,
1 => -1,
),
1 =>
array (
0 => NULL,
1 => -1,
),
'b' =>
array (
0 => '2',
1 => 0,
),
2 =>
array (
0 => '2',
1 => 0,
),
)
array (
0 =>
array (
0 => '1',
1 => '23',
2 => '45',
3 => '6',
),
'a' =>
array (
0 => NULL,
1 => NULL,
2 => '4',
3 => NULL,
),
1 =>
array (
0 => NULL,
1 => NULL,
2 => '4',
3 => NULL,
),
'b' =>
array (
0 => NULL,
1 => '2',
2 => NULL,
3 => NULL,
),
2 =>
array (
0 => NULL,
1 => '2',
2 => NULL,
3 => NULL,
),
)
array (
0 =>
array (
0 =>
array (
0 => '1',
1 => 0,
),
1 =>
array (
0 => '23',
1 => 1,
),
2 =>
array (
0 => '45',
1 => 3,
),
3 =>
array (
0 => '6',
1 => 5,
),
),
'a' =>
array (
0 => NULL,
1 =>
array (
0 => NULL,
1 => -1,
),
2 =>
array (
0 => '4',
1 => 3,
),
3 => NULL,
),
1 =>
array (
0 => NULL,
1 =>
array (
0 => NULL,
1 => -1,
),
2 =>
array (
0 => '4',
1 => 3,
),
3 => NULL,
),
'b' =>
array (
0 => NULL,
1 =>
array (
0 => '2',
1 => 1,
),
2 => NULL,
3 => NULL,
),
2 =>
array (
0 => NULL,
1 =>
array (
0 => '2',
1 => 1,
),
2 => NULL,
3 => NULL,
),
)
array (
0 =>
array (
0 => '1',
),
1 =>
array (
0 => '23',
'a' => NULL,
1 => NULL,
'b' => '2',
2 => '2',
),
2 =>
array (
0 => '45',
'a' => '4',
1 => '4',
),
3 =>
array (
0 => '6',
),
)
array (
0 =>
array (
0 =>
array (
0 => '1',
1 => 0,
),
),
1 =>
array (
0 =>
array (
0 => '23',
1 => 1,
),
'a' =>
array (
0 => NULL,
1 => -1,
),
1 =>
array (
0 => NULL,
1 => -1,
),
'b' =>
array (
0 => '2',
1 => 1,
),
2 =>
array (
0 => '2',
1 => 1,
),
),
2 =>
array (
0 =>
array (
0 => '45',
1 => 3,
),
'a' =>
array (
0 => '4',
1 => 3,
),
1 =>
array (
0 => '4',
1 => 3,
),
),
3 =>
array (
0 =>
array (
0 => '6',
1 => 5,
),
),
)

View file

@ -39,9 +39,9 @@ array(5) {
[0]=> [0]=>
string(3) "_c_" string(3) "_c_"
[1]=> [1]=>
string(0) "" NULL
[2]=> [2]=>
string(0) "" NULL
[3]=> [3]=>
string(1) "c" string(1) "c"
["MARK"]=> ["MARK"]=>
@ -65,42 +65,42 @@ array(6) {
[0]=> [0]=>
string(1) "a" string(1) "a"
[1]=> [1]=>
string(0) "" NULL
[2]=> [2]=>
string(0) "" NULL
[3]=> [3]=>
string(0) "" NULL
} }
[2]=> [2]=>
array(4) { array(4) {
[0]=> [0]=>
string(0) "" NULL
[1]=> [1]=>
string(1) "b" string(1) "b"
[2]=> [2]=>
string(0) "" NULL
[3]=> [3]=>
string(0) "" NULL
} }
[3]=> [3]=>
array(4) { array(4) {
[0]=> [0]=>
string(0) "" NULL
[1]=> [1]=>
string(0) "" NULL
[2]=> [2]=>
string(1) "c" string(1) "c"
[3]=> [3]=>
string(0) "" NULL
} }
[4]=> [4]=>
array(4) { array(4) {
[0]=> [0]=>
string(0) "" NULL
[1]=> [1]=>
string(0) "" NULL
[2]=> [2]=>
string(0) "" NULL
[3]=> [3]=>
string(1) "d" string(1) "d"
} }
@ -128,7 +128,7 @@ array(4) {
[0]=> [0]=>
string(3) "_b_" string(3) "_b_"
[1]=> [1]=>
string(0) "" NULL
[2]=> [2]=>
string(1) "b" string(1) "b"
} }
@ -137,9 +137,9 @@ array(4) {
[0]=> [0]=>
string(3) "_c_" string(3) "_c_"
[1]=> [1]=>
string(0) "" NULL
[2]=> [2]=>
string(0) "" NULL
[3]=> [3]=>
string(1) "c" string(1) "c"
["MARK"]=> ["MARK"]=>
@ -150,11 +150,11 @@ array(4) {
[0]=> [0]=>
string(3) "_d_" string(3) "_d_"
[1]=> [1]=>
string(0) "" NULL
[2]=> [2]=>
string(0) "" NULL
[3]=> [3]=>
string(0) "" NULL
[4]=> [4]=>
string(1) "d" string(1) "d"
} }