Skip to content

Commit 6d57848

Browse files
committed
Improve strpos and strstr function family implementation
1 parent ade97c2 commit 6d57848

31 files changed

+287
-240
lines changed

UPGRADING

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ PHP 8.0 UPGRADE NOTES
202202
string. Previously non-string needles were interpreted as an ASCII code
203203
point. An explicit call to chr() can be used to restore the previous
204204
behavior.
205+
. The needle argument for strpos(), strrpos(), stripos(), strripos(), strstr() and stristr() can now be empty.
205206
. The 'salt' option of password_hash() is no longer supported. If the 'salt'
206207
option is used a warning is generated, the provided salt is ignored, and a
207208
generated salt is used instead.

Zend/zend_operators.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,10 @@ zend_memnstr(const char *haystack, const char *needle, size_t needle_len, const
152152
ptrdiff_t off_p;
153153
size_t off_s;
154154

155+
if (needle_len == 0) {
156+
return p;
157+
}
158+
155159
if (needle_len == 1) {
156160
return (const char *)memchr(p, *needle, (end-p));
157161
}
@@ -210,6 +214,10 @@ zend_memnrstr(const char *haystack, const char *needle, size_t needle_len, const
210214
ptrdiff_t off_p;
211215
size_t off_s;
212216

217+
if (needle_len == 0) {
218+
return p;
219+
}
220+
213221
if (needle_len == 1) {
214222
return (const char *)zend_memrchr(haystack, *needle, (p - haystack));
215223
}

ext/standard/string.c

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1812,11 +1812,6 @@ PHP_FUNCTION(stristr)
18121812
Z_PARAM_BOOL(part)
18131813
ZEND_PARSE_PARAMETERS_END();
18141814

1815-
if (!ZSTR_LEN(needle)) {
1816-
php_error_docref(NULL, E_WARNING, "Empty needle");
1817-
RETURN_FALSE;
1818-
}
1819-
18201815
haystack_dup = estrndup(ZSTR_VAL(haystack), ZSTR_LEN(haystack));
18211816
orig_needle = estrndup(ZSTR_VAL(needle), ZSTR_LEN(needle));
18221817
found = php_stristr(haystack_dup, orig_needle, ZSTR_LEN(haystack), ZSTR_LEN(needle));
@@ -1853,11 +1848,6 @@ PHP_FUNCTION(strstr)
18531848
Z_PARAM_BOOL(part)
18541849
ZEND_PARSE_PARAMETERS_END();
18551850

1856-
if (!ZSTR_LEN(needle)) {
1857-
php_error_docref(NULL, E_WARNING, "Empty needle");
1858-
RETURN_FALSE;
1859-
}
1860-
18611851
found = php_memnstr(ZSTR_VAL(haystack), ZSTR_VAL(needle), ZSTR_LEN(needle), ZSTR_VAL(haystack) + ZSTR_LEN(haystack));
18621852

18631853
if (found) {
@@ -1899,11 +1889,6 @@ PHP_FUNCTION(strpos)
18991889
RETURN_FALSE;
19001890
}
19011891

1902-
if (!ZSTR_LEN(needle)) {
1903-
php_error_docref(NULL, E_WARNING, "Empty needle");
1904-
RETURN_FALSE;
1905-
}
1906-
19071892
found = (char*)php_memnstr(ZSTR_VAL(haystack) + offset,
19081893
ZSTR_VAL(needle), ZSTR_LEN(needle),
19091894
ZSTR_VAL(haystack) + ZSTR_LEN(haystack));
@@ -1940,7 +1925,7 @@ PHP_FUNCTION(stripos)
19401925
RETURN_FALSE;
19411926
}
19421927

1943-
if (ZSTR_LEN(needle) == 0 || ZSTR_LEN(needle) > ZSTR_LEN(haystack)) {
1928+
if (ZSTR_LEN(needle) > ZSTR_LEN(haystack)) {
19441929
RETURN_FALSE;
19451930
}
19461931

@@ -1964,23 +1949,18 @@ PHP_FUNCTION(stripos)
19641949
Finds position of last occurrence of a string within another string */
19651950
PHP_FUNCTION(strrpos)
19661951
{
1952+
zend_string *needle;
19671953
zend_string *haystack;
1968-
char *needle;
1969-
size_t needle_len;
19701954
zend_long offset = 0;
19711955
const char *p, *e, *found;
19721956

19731957
ZEND_PARSE_PARAMETERS_START(2, 3)
19741958
Z_PARAM_STR(haystack)
1975-
Z_PARAM_STRING(needle, needle_len)
1959+
Z_PARAM_STR(needle)
19761960
Z_PARAM_OPTIONAL
19771961
Z_PARAM_LONG(offset)
19781962
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
19791963

1980-
if (ZSTR_LEN(haystack) == 0 || needle_len == 0) {
1981-
RETURN_FALSE;
1982-
}
1983-
19841964
if (offset >= 0) {
19851965
if ((size_t)offset > ZSTR_LEN(haystack)) {
19861966
php_error_docref(NULL, E_WARNING, "Offset not contained in string");
@@ -1993,15 +1973,16 @@ PHP_FUNCTION(strrpos)
19931973
php_error_docref(NULL, E_WARNING, "Offset not contained in string");
19941974
RETURN_FALSE;
19951975
}
1976+
19961977
p = ZSTR_VAL(haystack);
1997-
if ((size_t)-offset < needle_len) {
1978+
if ((size_t)-offset < ZSTR_LEN(needle)) {
19981979
e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack);
19991980
} else {
2000-
e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack) + offset + needle_len;
1981+
e = ZSTR_VAL(haystack) + ZSTR_LEN(haystack) + offset + ZSTR_LEN(needle);
20011982
}
20021983
}
20031984

2004-
if ((found = zend_memnrstr(p, needle, needle_len, e))) {
1985+
if ((found = zend_memnrstr(p, ZSTR_VAL(needle), ZSTR_LEN(needle), e))) {
20051986
RETURN_LONG(found - ZSTR_VAL(haystack));
20061987
}
20071988

@@ -2026,10 +2007,6 @@ PHP_FUNCTION(strripos)
20262007
Z_PARAM_LONG(offset)
20272008
ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);
20282009

2029-
if (ZSTR_LEN(haystack) == 0 || ZSTR_LEN(needle) == 0) {
2030-
RETURN_FALSE;
2031-
}
2032-
20332010
if (ZSTR_LEN(needle) == 1) {
20342011
/* Single character search can shortcut memcmps
20352012
Can also avoid tolower emallocs */
@@ -2075,6 +2052,7 @@ PHP_FUNCTION(strripos)
20752052
php_error_docref(NULL, E_WARNING, "Offset not contained in string");
20762053
RETURN_FALSE;
20772054
}
2055+
20782056
p = ZSTR_VAL(haystack_dup);
20792057
if ((size_t)-offset < ZSTR_LEN(needle)) {
20802058
e = ZSTR_VAL(haystack_dup) + ZSTR_LEN(haystack);

ext/standard/tests/strings/bug63943.phpt

Lines changed: 0 additions & 8 deletions
This file was deleted.

ext/standard/tests/strings/stripos.phpt

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ stripos() function test
2525
var_dump(stripos("0", false));
2626
var_dump(stripos("1", true));
2727
var_dump(stripos("\\\\a", "\\a"));
28-
29-
echo "Done\n";
3028
?>
29+
30+
DONE
3131
--EXPECT--
3232
int(0)
3333
int(5)
@@ -37,19 +37,20 @@ int(10)
3737
int(2)
3838
int(0)
3939
int(0)
40-
bool(false)
41-
bool(false)
42-
bool(false)
43-
bool(false)
40+
int(0)
4441
int(0)
4542
bool(false)
4643
bool(false)
44+
int(0)
4745
bool(false)
48-
bool(false)
46+
int(0)
4947
bool(false)
5048
bool(false)
5149
int(0)
5250
bool(false)
5351
int(0)
52+
int(0)
53+
int(0)
5454
int(1)
55-
Done
55+
56+
DONE

ext/standard/tests/strings/stripos_variation1.phpt

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -117,20 +117,20 @@ int(9)
117117
int(8)
118118
bool(false)
119119
-- Iteration 12 --
120-
bool(false)
121-
bool(false)
120+
int(0)
121+
int(11)
122122
-- Iteration 13 --
123-
bool(false)
124-
bool(false)
123+
int(0)
124+
int(12)
125125
-- Iteration 14 --
126-
bool(false)
127-
bool(false)
126+
int(0)
127+
int(13)
128128
-- Iteration 15 --
129-
bool(false)
130-
bool(false)
129+
int(0)
130+
int(14)
131131
-- Iteration 16 --
132-
bool(false)
133-
bool(false)
132+
int(0)
133+
int(15)
134134
-- Iteration 17 --
135135
int(10)
136136
int(47)

ext/standard/tests/strings/stripos_variation10.phpt

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ fclose($file_handle); //closing the file handle
9595

9696
echo "*** Done ***";
9797
?>
98-
--EXPECTF--
98+
--EXPECT--
9999
*** Testing stripos() function with unexpected values for needle ***
100100

101101
-- Iteration 1 --
@@ -144,35 +144,35 @@ stripos() expects parameter 2 to be string, array given
144144
int(9)
145145

146146
-- Iteration 16 --
147-
bool(false)
147+
int(0)
148148

149149
-- Iteration 17 --
150150
int(9)
151151

152152
-- Iteration 18 --
153-
bool(false)
153+
int(0)
154154

155155
-- Iteration 19 --
156156
int(64)
157157

158158
-- Iteration 20 --
159-
bool(false)
159+
int(0)
160160

161161
-- Iteration 21 --
162-
bool(false)
162+
int(0)
163163

164164
-- Iteration 22 --
165-
bool(false)
165+
int(0)
166166

167167
-- Iteration 23 --
168-
bool(false)
168+
int(0)
169169

170170
-- Iteration 24 --
171171
stripos() expects parameter 2 to be string, resource given
172172

173173
-- Iteration 25 --
174-
bool(false)
174+
int(0)
175175

176176
-- Iteration 26 --
177-
bool(false)
177+
int(0)
178178
*** Done ***

ext/standard/tests/strings/stripos_variation11.phpt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -144,51 +144,51 @@ stripos() expects parameter 1 to be string, array given
144144
int(0)
145145
bool(false)
146146
-- Iteration 16 --
147-
bool(false)
147+
int(0)
148148

149149
Warning: stripos(): Offset not contained in string in %s on line %d
150150
bool(false)
151151
-- Iteration 17 --
152152
int(0)
153153
bool(false)
154154
-- Iteration 18 --
155-
bool(false)
155+
int(0)
156156

157157
Warning: stripos(): Offset not contained in string in %s on line %d
158158
bool(false)
159159
-- Iteration 19 --
160160
int(0)
161161
bool(false)
162162
-- Iteration 20 --
163-
bool(false)
163+
int(0)
164164

165165
Warning: stripos(): Offset not contained in string in %s on line %d
166166
bool(false)
167167
-- Iteration 21 --
168-
bool(false)
168+
int(0)
169169

170170
Warning: stripos(): Offset not contained in string in %s on line %d
171171
bool(false)
172172
-- Iteration 22 --
173-
bool(false)
173+
int(0)
174174

175175
Warning: stripos(): Offset not contained in string in %s on line %d
176176
bool(false)
177177
-- Iteration 23 --
178-
bool(false)
178+
int(0)
179179

180180
Warning: stripos(): Offset not contained in string in %s on line %d
181181
bool(false)
182182
-- Iteration 24 --
183183
stripos() expects parameter 1 to be string, resource given
184184
stripos() expects parameter 1 to be string, resource given
185185
-- Iteration 25 --
186-
bool(false)
186+
int(0)
187187

188188
Warning: stripos(): Offset not contained in string in %s on line %d
189189
bool(false)
190190
-- Iteration 26 --
191-
bool(false)
191+
int(0)
192192

193193
Warning: stripos(): Offset not contained in string in %s on line %d
194194
bool(false)

ext/standard/tests/strings/stripos_variation2.phpt

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -119,20 +119,20 @@ bool(false)
119119
int(10)
120120
int(10)
121121
-- Iteration 12 --
122-
bool(false)
123-
bool(false)
122+
int(0)
123+
int(11)
124124
-- Iteration 13 --
125-
bool(false)
126-
bool(false)
125+
int(0)
126+
int(12)
127127
-- Iteration 14 --
128-
bool(false)
129-
bool(false)
128+
int(0)
129+
int(13)
130130
-- Iteration 15 --
131-
bool(false)
132-
bool(false)
131+
int(0)
132+
int(14)
133133
-- Iteration 16 --
134-
bool(false)
135-
bool(false)
134+
int(0)
135+
int(15)
136136
-- Iteration 17 --
137137
int(14)
138138
int(51)

ext/standard/tests/strings/stripos_variation3.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,6 @@ echo "*** Done ***";
3232
int(14)
3333
int(23)
3434
int(23)
35-
bool(false)
35+
int(0)
3636
int(7)
3737
*** Done ***

ext/standard/tests/strings/stripos_variation7.phpt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ echo "*** Done ***";
2525
--EXPECTF--
2626
*** Testing stripos() function: with heredoc strings ***
2727
-- With empty heredoc string --
28-
bool(false)
28+
int(0)
2929

3030
Warning: stripos(): Offset not contained in string in %s on line %d
3131
bool(false)
32-
bool(false)
33-
bool(false)
32+
int(0)
33+
int(0)
3434
*** Done ***

0 commit comments

Comments
 (0)