@@ -275,7 +275,8 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
275275 get to the end without encountering a delimiter. */
276276 while (isspace ((int )* (unsigned char * )p )) p ++ ;
277277 if (* p == 0 ) {
278- php_error_docref (NULL TSRMLS_CC , E_WARNING , "Empty regular expression ");
278+ php_error_docref (NULL TSRMLS_CC , E_WARNING ,
279+ p < regex + regex_len ? "Null byte in regex" : "Empty regular expression" );
279280 return NULL ;
280281 }
281282
@@ -292,29 +293,25 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
292293 delimiter = pp [5 ];
293294 end_delimiter = delimiter ;
294295
296+ pp = p ;
297+
295298 if (start_delimiter == end_delimiter ) {
296299 /* We need to iterate through the pattern, searching for the ending delimiter,
297300 but skipping the backslashed delimiters. If the ending delimiter is not
298301 found, display a warning. */
299- pp = p ;
300302 while (* pp != 0 ) {
301303 if (* pp == '\\' && pp [1 ] != 0 ) pp ++ ;
302304 else if (* pp == delimiter )
303305 break ;
304306 pp ++ ;
305307 }
306- if (* pp == 0 ) {
307- php_error_docref (NULL TSRMLS_CC ,E_WARNING , "No ending delimiter '%c' found" , delimiter );
308- return NULL ;
309- }
310308 } else {
311309 /* We iterate through the pattern, searching for the matching ending
312310 * delimiter. For each matching starting delimiter, we increment nesting
313311 * level, and decrement it for each matching ending delimiter. If we
314312 * reach the end of the pattern without matching, display a warning.
315313 */
316314 int brackets = 1 ; /* brackets nesting level */
317- pp = p ;
318315 while (* pp != 0 ) {
319316 if (* pp == '\\' && pp [1 ] != 0 ) pp ++ ;
320317 else if (* pp == end_delimiter && -- brackets <= 0 )
@@ -323,10 +320,17 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
323320 brackets ++ ;
324321 pp ++ ;
325322 }
326- if (* pp == 0 ) {
327- php_error_docref (NULL TSRMLS_CC ,E_WARNING , "No ending matching delimiter '%c' found" , end_delimiter );
328- return NULL ;
323+ }
324+
325+ if (* pp == 0 ) {
326+ if (pp < regex + regex_len ) {
327+ php_error_docref (NULL TSRMLS_CC ,E_WARNING , "Null byte in regex" );
328+ } else if (start_delimiter == end_delimiter ) {
329+ php_error_docref (NULL TSRMLS_CC ,E_WARNING , "No ending delimiter '%c' found" , delimiter );
330+ } else {
331+ php_error_docref (NULL TSRMLS_CC ,E_WARNING , "No ending matching delimiter '%c' found" , delimiter );
329332 }
333+ return NULL ;
330334 }
331335
332336 /* Make a copy of the actual pattern. */
@@ -337,7 +341,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
337341
338342 /* Parse through the options, setting appropriate flags. Display
339343 a warning if we encounter an unknown modifier. */
340- while (* pp != 0 ) {
344+ while (pp < regex + regex_len ) {
341345 switch (* pp ++ ) {
342346 /* Perl compatible options */
343347 case 'i' : coptions |= PCRE_CASELESS ; break ;
@@ -368,7 +372,11 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache(char *regex, int regex_le
368372 break ;
369373
370374 default :
371- php_error_docref (NULL TSRMLS_CC ,E_WARNING , "Unknown modifier '%c'" , pp [-1 ]);
375+ if (pp [-1 ]) {
376+ php_error_docref (NULL TSRMLS_CC ,E_WARNING , "Unknown modifier '%c'" , pp [-1 ]);
377+ } else {
378+ php_error_docref (NULL TSRMLS_CC ,E_WARNING , "Null byte in regex" );
379+ }
372380 efree (pattern );
373381 return NULL ;
374382 }
0 commit comments