@@ -104,7 +104,7 @@ PHPAPI php_url *php_url_parse_ex(char const *str, size_t 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,10 +119,10 @@ PHPAPI php_url *php_url_parse_ex(char const *str, size_t 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
- goto end ;
125
+ return ret ;
126
126
}
127
127
128
128
/*
@@ -134,90 +134,91 @@ PHPAPI php_url *php_url_parse_ex(char const *str, size_t 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
145
145
ret -> scheme = estrndup (s , (e - s ));
146
146
php_replace_controlchars_ex (ret -> scheme , (e - s ));
147
147
148
- length -= ++ e - s ;
149
- s = e ;
148
+ s = e + 1 ;
150
149
goto just_path ;
151
150
} else {
152
151
ret -> scheme = estrndup (s , (e - s ));
153
152
php_replace_controlchars_ex (ret -> scheme , (e - s ));
154
153
155
- if (* (e + 2 ) == '/' ) {
154
+ if (e + 2 < ue && * (e + 2 ) == '/' ) {
156
155
s = e + 3 ;
157
156
if (!strncasecmp ("file" , ret -> scheme , sizeof ("file" ))) {
158
- if (* (e + 3 ) == '/' ) {
157
+ if (e + 3 < ue && * (e + 3 ) == '/' ) {
159
158
/* support windows drive letters as in:
160
159
file:///c:/somedir/file.txt
161
160
*/
162
- if (* (e + 5 ) == ':' ) {
161
+ if (e + 5 < ue && * (e + 5 ) == ':' ) {
163
162
s = e + 4 ;
164
163
}
165
- goto nohost ;
164
+ goto just_path ;
166
165
}
167
166
}
168
167
} else {
169
- if (!strncasecmp ("file" , ret -> scheme , sizeof ("file" ))) {
170
- s = e + 1 ;
171
- goto nohost ;
172
- } else {
173
- length -= ++ e - s ;
174
- s = e ;
175
- goto just_path ;
176
- }
168
+ s = e + 1 ;
169
+ goto just_path ;
177
170
}
178
171
}
179
172
} else if (e ) { /* no scheme; starts with colon: look for port */
180
173
parse_port :
181
174
p = e + 1 ;
182
175
pp = p ;
183
176
184
- while (pp - p < 6 && isdigit (* pp )) {
177
+ while (pp < ue && pp - p < 6 && isdigit (* pp )) {
185
178
pp ++ ;
186
179
}
187
180
188
- if (pp - p > 0 && pp - p < 6 && (* pp == '/' || * pp == '\0 ' )) {
181
+ if (pp - p > 0 && pp - p < 6 && (pp == ue || * pp == '/ ' )) {
189
182
zend_long port ;
190
183
memcpy (port_buf , p , (pp - p ));
191
184
port_buf [pp - p ] = '\0' ;
192
185
port = ZEND_STRTOL (port_buf , NULL , 10 );
193
186
if (port > 0 && port <= 65535 ) {
194
187
ret -> port = (unsigned short ) port ;
195
- if (* s == '/' && * (s + 1 ) == '/' ) { /* relative-scheme URL */
188
+ if (s + 1 < ue && * s == '/' && * (s + 1 ) == '/' ) { /* relative-scheme URL */
196
189
s += 2 ;
197
190
}
198
191
} else {
199
192
if (ret -> scheme ) efree (ret -> scheme );
200
193
efree (ret );
201
194
return NULL ;
202
195
}
203
- } else if (p == pp && * pp == '\0' ) {
196
+ } else if (p == pp && pp == ue ) {
204
197
if (ret -> scheme ) efree (ret -> scheme );
205
198
efree (ret );
206
199
return NULL ;
207
- } else if (* s == '/' && * (s + 1 ) == '/' ) { /* relative-scheme URL */
200
+ } else if (s + 1 < ue && * s == '/' && * (s + 1 ) == '/' ) { /* relative-scheme URL */
208
201
s += 2 ;
209
202
} else {
210
203
goto just_path ;
211
204
}
212
- } else if (* s == '/' && * (s + 1 ) == '/' ) { /* relative-scheme URL */
205
+ } else if (s + 1 < ue && * s == '/' && * (s + 1 ) == '/' ) { /* relative-scheme URL */
213
206
s += 2 ;
214
207
} else {
215
- just_path :
216
- ue = s + length ;
217
- goto nohost ;
208
+ goto just_path ;
218
209
}
219
210
220
- 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
+ }
221
222
222
223
/* check for login and password */
223
224
if ((p = zend_memrchr (s , '@' , (e - s )))) {
@@ -237,18 +238,16 @@ PHPAPI php_url *php_url_parse_ex(char const *str, size_t length)
237
238
}
238
239
239
240
/* check for port */
240
- if (* s == '[' && * (e - 1 ) == ']' ) {
241
+ if (s < ue && * s == '[' && * (e - 1 ) == ']' ) {
241
242
/* Short circuit portscan,
242
243
we're dealing with an
243
244
IPv6 embedded address */
244
- p = s ;
245
+ p = NULL ;
245
246
} else {
246
- /* memrchr is a GNU specific extension
247
- Emulate for wide compatibility */
248
- for (p = e ; p >= s && * p != ':' ; p -- );
247
+ p = zend_memrchr (s , ':' , (e - s ));
249
248
}
250
249
251
- if (p >= s && * p == ':' ) {
250
+ if (p ) {
252
251
if (!ret -> port ) {
253
252
p ++ ;
254
253
if (e - p > 5 ) { /* port cannot be longer then 5 characters */
@@ -296,54 +295,34 @@ PHPAPI php_url *php_url_parse_ex(char const *str, size_t length)
296
295
297
296
s = e ;
298
297
299
- nohost :
300
-
301
- if ((p = memchr (s , '?' , (ue - s )))) {
302
- pp = memchr (s , '#' , (ue - s ));
303
-
304
- if (pp && pp < p ) {
305
- if (pp - s ) {
306
- ret -> path = estrndup (s , (pp - s ));
307
- php_replace_controlchars_ex (ret -> path , (pp - s ));
308
- }
309
- p = pp ;
310
- goto label_parse ;
311
- }
298
+ just_path :
312
299
313
- if (p - s ) {
314
- ret -> path = estrndup (s , (p - s ));
315
- php_replace_controlchars_ex (ret -> path , (p - s ));
316
- }
317
-
318
- if (pp ) {
319
- if (pp - ++ p ) {
320
- ret -> query = estrndup (p , (pp - p ));
321
- php_replace_controlchars_ex (ret -> query , (pp - p ));
322
- }
323
- p = pp ;
324
- goto label_parse ;
325
- } else if (++ p - ue ) {
326
- ret -> query = estrndup (p , (ue - p ));
327
- php_replace_controlchars_ex (ret -> query , (ue - p ));
328
- }
329
- } else if ((p = memchr (s , '#' , (ue - s )))) {
330
- if (p - s ) {
331
- ret -> path = estrndup (s , (p - s ));
332
- php_replace_controlchars_ex (ret -> path , (p - s ));
300
+ e = ue ;
301
+ p = memchr (s , '#' , (e - s ));
302
+ if (p ) {
303
+ p ++ ;
304
+ if (p < e ) {
305
+ ret -> fragment = estrndup (p , (e - p ));
306
+ php_replace_controlchars_ex (ret -> fragment , (e - p ));
333
307
}
308
+ e = p - 1 ;
309
+ }
334
310
335
- label_parse :
311
+ p = memchr (s , '?' , (e - s ));
312
+ if (p ) {
336
313
p ++ ;
337
-
338
- if (ue - p ) {
339
- ret -> fragment = estrndup (p , (ue - p ));
340
- php_replace_controlchars_ex (ret -> fragment , (ue - p ));
314
+ if (p < e ) {
315
+ ret -> query = estrndup (p , (e - p ));
316
+ php_replace_controlchars_ex (ret -> query , (e - p ));
341
317
}
342
- } else {
343
- ret -> path = estrndup (s , (ue - s ));
344
- php_replace_controlchars_ex (ret -> path , (ue - s ));
318
+ e = p - 1 ;
345
319
}
346
- end :
320
+
321
+ if (s < e || s == ue ) {
322
+ ret -> path = estrndup (s , (e - s ));
323
+ php_replace_controlchars_ex (ret -> path , (e - s ));
324
+ }
325
+
347
326
return ret ;
348
327
}
349
328
/* }}} */
0 commit comments