@@ -104,7 +104,7 @@ PHPAPI php_url *php_url_parse_ex(char const *str, int length)
104
104
ue = s + length ;
105
105
106
106
/* parse scheme */
107
- if ((e = memchr (s , ':' , length )) && ( e - s ) ) {
107
+ if ((e = memchr (s , ':' , length )) && e != s ) {
108
108
/* validate scheme */
109
109
p = s ;
110
110
while (p < e ) {
@@ -119,7 +119,7 @@ PHPAPI php_url *php_url_parse_ex(char const *str, int length)
119
119
p ++ ;
120
120
}
121
121
122
- if (* ( e + 1 ) == '\0' ) { /* only scheme is available */
122
+ if (e + 1 == ue ) { /* only scheme is available */
123
123
ret -> scheme = estrndup (s , (e - s ));
124
124
php_replace_controlchars_ex (ret -> scheme , (e - s ));
125
125
return ret ;
@@ -134,11 +134,11 @@ PHPAPI php_url *php_url_parse_ex(char const *str, int length)
134
134
* correctly parse things like a.com:80
135
135
*/
136
136
p = e + 1 ;
137
- while (isdigit (* p )) {
137
+ while (p < ue && isdigit (* p )) {
138
138
p ++ ;
139
139
}
140
140
141
- if ((* p == '\0' || * p == '/' ) && (p - e ) < 7 ) {
141
+ if ((p == ue || * p == '/' ) && (p - e ) < 7 ) {
142
142
goto parse_port ;
143
143
}
144
144
@@ -151,14 +151,14 @@ PHPAPI php_url *php_url_parse_ex(char const *str, int length)
151
151
ret -> scheme = estrndup (s , (e - s ));
152
152
php_replace_controlchars_ex (ret -> scheme , (e - s ));
153
153
154
- if (* (e + 2 ) == '/' ) {
154
+ if (e + 2 < ue && * (e + 2 ) == '/' ) {
155
155
s = e + 3 ;
156
156
if (!strncasecmp ("file" , ret -> scheme , sizeof ("file" ))) {
157
- if (* (e + 3 ) == '/' ) {
157
+ if (e + 3 < ue && * (e + 3 ) == '/' ) {
158
158
/* support windows drive letters as in:
159
159
file:///c:/somedir/file.txt
160
160
*/
161
- if (* (e + 5 ) == ':' ) {
161
+ if (e + 5 < ue && * (e + 5 ) == ':' ) {
162
162
s = e + 4 ;
163
163
}
164
164
goto just_path ;
@@ -174,41 +174,51 @@ PHPAPI php_url *php_url_parse_ex(char const *str, int length)
174
174
p = e + 1 ;
175
175
pp = p ;
176
176
177
- while (pp - p < 6 && isdigit (* pp )) {
177
+ while (pp < ue && pp - p < 6 && isdigit (* pp )) {
178
178
pp ++ ;
179
179
}
180
180
181
- if (pp - p > 0 && pp - p < 6 && (* pp == '/' || * pp == '\0 ' )) {
181
+ if (pp - p > 0 && pp - p < 6 && (pp == ue || * pp == '/ ' )) {
182
182
long port ;
183
183
memcpy (port_buf , p , (pp - p ));
184
184
port_buf [pp - p ] = '\0' ;
185
185
port = strtol (port_buf , NULL , 10 );
186
186
if (port > 0 && port <= 65535 ) {
187
187
ret -> port = (unsigned short ) port ;
188
- if (* s == '/' && * (s + 1 ) == '/' ) { /* relative-scheme URL */
188
+ if (s + 1 < ue && * s == '/' && * (s + 1 ) == '/' ) { /* relative-scheme URL */
189
189
s += 2 ;
190
190
}
191
191
} else {
192
192
STR_FREE (ret -> scheme );
193
193
efree (ret );
194
194
return NULL ;
195
195
}
196
- } else if (p == pp && * pp == '\0' ) {
196
+ } else if (p == pp && pp == ue ) {
197
197
STR_FREE (ret -> scheme );
198
198
efree (ret );
199
199
return NULL ;
200
- } else if (* s == '/' && * (s + 1 ) == '/' ) { /* relative-scheme URL */
200
+ } else if (s + 1 < ue && * s == '/' && * (s + 1 ) == '/' ) { /* relative-scheme URL */
201
201
s += 2 ;
202
202
} else {
203
203
goto just_path ;
204
204
}
205
- } else if (* s == '/' && * (s + 1 ) == '/' ) { /* relative-scheme URL */
205
+ } else if (s + 1 < ue && * s == '/' && * (s + 1 ) == '/' ) { /* relative-scheme URL */
206
206
s += 2 ;
207
207
} else {
208
208
goto just_path ;
209
209
}
210
210
211
- e = s + strcspn (s , "/?#" );
211
+ /* Binary-safe strcspn(s, "/?#") */
212
+ e = ue ;
213
+ if ((p = memchr (s , '/' , e - s ))) {
214
+ e = p ;
215
+ }
216
+ if ((p = memchr (s , '?' , e - s ))) {
217
+ e = p ;
218
+ }
219
+ if ((p = memchr (s , '#' , e - s ))) {
220
+ e = p ;
221
+ }
212
222
213
223
/* check for login and password */
214
224
if ((p = zend_memrchr (s , '@' , (e - s )))) {
@@ -228,18 +238,16 @@ PHPAPI php_url *php_url_parse_ex(char const *str, int length)
228
238
}
229
239
230
240
/* check for port */
231
- if (* s == '[' && * (e - 1 ) == ']' ) {
241
+ if (s < ue && * s == '[' && * (e - 1 ) == ']' ) {
232
242
/* Short circuit portscan,
233
243
we're dealing with an
234
244
IPv6 embedded address */
235
- p = s ;
245
+ p = NULL ;
236
246
} else {
237
- /* memrchr is a GNU specific extension
238
- Emulate for wide compatibility */
239
- for (p = e ; p >= s && * p != ':' ; p -- );
247
+ p = zend_memrchr (s , ':' , (e - s ));
240
248
}
241
249
242
- if (p >= s && * p == ':' ) {
250
+ if (p ) {
243
251
if (!ret -> port ) {
244
252
p ++ ;
245
253
if (e - p > 5 ) { /* port cannot be longer then 5 characters */
0 commit comments