Skip to content

Commit ee6aaee

Browse files
committed
Merge branch 'pull-request/1303'
* pull-request/1303: Distinguish between unmatched subpatterns and empty matches in preg_*() news entry for PR #1303
2 parents 1db0569 + 5ca664a commit ee6aaee

File tree

9 files changed

+554
-43
lines changed

9 files changed

+554
-43
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ PHP NEWS
7171
. Fixed bug #73800 (sporadic segfault with MYSQLI_OPT_INT_AND_FLOAT_NATIVE).
7272
(vanviegen)
7373

74+
- PCRE:
75+
. Fixed bug #61780 (Inconsistent PCRE captures in match results). (cmb)
76+
7477
- PDO:
7578
. Add "Sent SQL" to debug dump for emulated prepares. (Adam Baratz)
7679

ext/pcre/php_pcre.c

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,11 @@ static inline void add_offset_pair(zval *result, char *str, int len, int offset,
646646
array_init_size(&match_pair, 2);
647647

648648
/* Add (match, offset) to the return value */
649-
ZVAL_STRINGL(&tmp, str, len);
649+
if (offset < 0) { /* unset substring */
650+
ZVAL_NULL(&tmp);
651+
} else {
652+
ZVAL_STRINGL(&tmp, str, len);
653+
}
650654
zend_hash_next_index_insert_new(Z_ARRVAL(match_pair), &tmp);
651655
ZVAL_LONG(&tmp, offset);
652656
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
847851
}
848852
} else {
849853
for (i = 0; i < count; i++) {
850-
add_next_index_stringl(&match_sets[i], (char *)stringlist[i],
851-
offsets[(i<<1)+1] - offsets[i<<1]);
854+
if (offsets[i<<1] < 0) { /* unset substring */
855+
add_next_index_null(&match_sets[i]);
856+
} else {
857+
add_next_index_stringl(&match_sets[i], (char *)stringlist[i],
858+
offsets[(i<<1)+1] - offsets[i<<1]);
859+
}
852860
}
853861
}
854862
/* Add MARK, if available */
@@ -861,11 +869,11 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
861869
/*
862870
* If the number of captured subpatterns on this run is
863871
* less than the total possible number, pad the result
864-
* arrays with empty strings.
872+
* arrays with NULLs.
865873
*/
866874
if (count < num_subpats) {
867875
for (; i < num_subpats; i++) {
868-
add_next_index_string(&match_sets[i], "");
876+
add_next_index_null(&match_sets[i]);
869877
}
870878
}
871879
} else {
@@ -882,11 +890,19 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
882890
} else {
883891
for (i = 0; i < count; i++) {
884892
if (subpat_names[i]) {
885-
add_assoc_stringl(&result_set, subpat_names[i], (char *)stringlist[i],
893+
if (offsets[i<<1] < 0) { /* unset substring */
894+
add_assoc_null(&result_set, subpat_names[i]);
895+
} else {
896+
add_assoc_stringl(&result_set, subpat_names[i], (char *)stringlist[i],
897+
offsets[(i<<1)+1] - offsets[i<<1]);
898+
}
899+
}
900+
if (offsets[i<<1] < 0) { /* unset substring */
901+
add_next_index_null(&result_set);
902+
} else {
903+
add_next_index_stringl(&result_set, (char *)stringlist[i],
886904
offsets[(i<<1)+1] - offsets[i<<1]);
887905
}
888-
add_next_index_stringl(&result_set, (char *)stringlist[i],
889-
offsets[(i<<1)+1] - offsets[i<<1]);
890906
}
891907
}
892908
} else {
@@ -897,8 +913,12 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
897913
}
898914
} else {
899915
for (i = 0; i < count; i++) {
900-
add_next_index_stringl(&result_set, (char *)stringlist[i],
901-
offsets[(i<<1)+1] - offsets[i<<1]);
916+
if (offsets[i<<1] < 0) { /* unset substring */
917+
add_next_index_null(&result_set);
918+
} else {
919+
add_next_index_stringl(&result_set, (char *)stringlist[i],
920+
offsets[(i<<1)+1] - offsets[i<<1]);
921+
}
902922
}
903923
}
904924
}
@@ -921,11 +941,19 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
921941
} else {
922942
for (i = 0; i < count; i++) {
923943
if (subpat_names[i]) {
924-
add_assoc_stringl(subpats, subpat_names[i], (char *)stringlist[i],
925-
offsets[(i<<1)+1] - offsets[i<<1]);
944+
if (offsets[i<<1] < 0) { /* unset substring */
945+
add_assoc_null(subpats, subpat_names[i]);
946+
} else {
947+
add_assoc_stringl(subpats, subpat_names[i], (char *)stringlist[i],
948+
offsets[(i<<1)+1] - offsets[i<<1]);
949+
}
950+
}
951+
if (offsets[i<<1] < 0) { /* unset substring */
952+
add_next_index_null(subpats);
953+
} else {
954+
add_next_index_stringl(subpats, (char *)stringlist[i],
955+
offsets[(i<<1)+1] - offsets[i<<1]);
926956
}
927-
add_next_index_stringl(subpats, (char *)stringlist[i],
928-
offsets[(i<<1)+1] - offsets[i<<1]);
929957
}
930958
}
931959
} else {
@@ -937,8 +965,12 @@ PHPAPI void php_pcre_match_impl(pcre_cache_entry *pce, char *subject, int subjec
937965
}
938966
} else {
939967
for (i = 0; i < count; i++) {
940-
add_next_index_stringl(subpats, (char *)stringlist[i],
941-
offsets[(i<<1)+1] - offsets[i<<1]);
968+
if (offsets[i<<1] < 0) { /* unset substring */
969+
add_next_index_null(subpats);
970+
} else {
971+
add_next_index_stringl(subpats, (char *)stringlist[i],
972+
offsets[(i<<1)+1] - offsets[i<<1]);
973+
}
942974
}
943975
}
944976
}

ext/pcre/tests/001.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ array(10) {
5252
[2]=>
5353
string(2) "06"
5454
[3]=>
55-
string(0) ""
55+
NULL
5656
["month"]=>
5757
string(2) "12"
5858
[4]=>
@@ -75,7 +75,7 @@ array(10) {
7575
[2]=>
7676
string(2) "12"
7777
[3]=>
78-
string(0) ""
78+
NULL
7979
["month"]=>
8080
string(3) "Aug"
8181
[4]=>

ext/pcre/tests/003.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ array(10) {
5858
[0]=>
5959
string(2) "20"
6060
[1]=>
61-
string(0) ""
61+
NULL
6262
}
6363
["month"]=>
6464
array(2) {
@@ -127,7 +127,7 @@ array(2) {
127127
[2]=>
128128
string(2) "12"
129129
[3]=>
130-
string(0) ""
130+
NULL
131131
["month"]=>
132132
string(3) "Aug"
133133
[4]=>

ext/pcre/tests/004.phpt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ array(2) {
2424
[1]=>
2525
string(12) "unsigned int"
2626
[2]=>
27-
string(0) ""
27+
NULL
2828
[3]=>
2929
string(0) ""
3030
[4]=>
@@ -41,13 +41,13 @@ array(2) {
4141
[1]=>
4242
string(5) "short"
4343
[2]=>
44-
string(0) ""
44+
NULL
4545
[3]=>
4646
string(0) ""
4747
[4]=>
4848
string(1) "a"
4949
[5]=>
50-
string(0) ""
50+
NULL
5151
[6]=>
5252
string(3) ", b"
5353
}

ext/pcre/tests/bug61780.phpt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
Bug #61780 (Inconsistent PCRE captures in match results): basics
3+
--FILE--
4+
<?php
5+
preg_match('/(a)?([a-z]*)(\d*)/', '123', $matches);
6+
var_dump($matches);
7+
?>
8+
--EXPECT--
9+
array(4) {
10+
[0]=>
11+
string(3) "123"
12+
[1]=>
13+
NULL
14+
[2]=>
15+
string(0) ""
16+
[3]=>
17+
string(3) "123"
18+
}

0 commit comments

Comments
 (0)