On October 4, 2002 11:27 am, Jani Taskinen wrote: > On Fri, 4 Oct 2002, Andrei Zmievski wrote: > >> Please let me know if there are any objections, better suggestions, bug > >> reports (pertaining to this patch) that would need to be resolved before > >> this bug goes into the CVS. > > > >I am not against merging this in before branching for 4.3.0, but we > >would really need to make sure that these functions are rock solid. > >Hopefully our QA team or what's left of it can come up with some tests. > > Propably would be best to wait to get the tests before this > is committed? (sorry if this was obvious..just wanted to be sure..) >
I've added 3 tests today that validate input of strstr, substr_count and strpos functions. These three functions are the ones affected by the patch, there is already a check for addslashes(). I've also made small revisions to the code that addresses at a searching problem inside php_memnstr in the original patch. The final patch is attached.
Index: string.c =================================================================== RCS file: /repository/php4/ext/standard/string.c,v retrieving revision 1.315 diff -u -3 -p -r1.315 string.c --- string.c 6 Oct 2002 18:39:03 -0000 1.315 +++ string.c 7 Oct 2002 21:11:46 -0000 @@ -2427,17 +2427,19 @@ PHPAPI char *php_addslashes(char *str, i char *new_str; char *source, *target; char *end; - char c; if (!str) { *new_length = 0; return str; } new_str = (char *) emalloc((length?length:(length=strlen(str)))*2+1); + source = str; + end = source + length; + target = new_str; + if (PG(magic_quotes_sybase)) { - for (source = str, end = source+length, target = new_str; source < end; source++) { - c = *source; - switch (c) { + while (source<end) { + switch (*source) { case '\0': *target++ = '\\'; *target++ = '0'; @@ -2447,14 +2449,16 @@ PHPAPI char *php_addslashes(char *str, i *target++ = '\''; break; default: - *target++ = c; - break; + *target++ = *source; + break; } + source++; } - } else { - for (source = str, end = source+length, target = new_str; source < end; source++) { - c = *source; - switch (c) { + } + else { + while (source<end) { + switch (*source) + { case '\0': *target++ = '\\'; *target++ = '0'; @@ -2465,11 +2469,14 @@ PHPAPI char *php_addslashes(char *str, i *target++ = '\\'; /* break is missing *intentionally* */ default: - *target++ = c; - break; + *target++ = *source; + break; } + + source++; } } + *target = 0; if (new_length) { *new_length = target - new_str; @@ -3805,7 +3812,7 @@ PHP_FUNCTION(strnatcasecmp) PHP_FUNCTION(substr_count) { zval **haystack, **needle; - int i, length, count = 0; + int count = 0; char *p, *endp, cmp; if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &haystack, &needle) == FAILURE) { @@ -3818,25 +3825,23 @@ PHP_FUNCTION(substr_count) if (Z_STRLEN_PP(needle) == 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty substring."); RETURN_FALSE; - } else if (Z_STRLEN_PP(needle) == 1) { - /* Special optimized case to avoid calls to php_memnstr(). */ - for (i = 0, p = Z_STRVAL_PP(haystack), - length = Z_STRLEN_PP(haystack), cmp = Z_STRVAL_PP(needle)[0]; - i < length; i++) { - if (p[i] == cmp) { - count++; + } + + p = Z_STRVAL_PP(haystack); + endp = p + Z_STRLEN_PP(haystack); + + if (Z_STRLEN_PP(needle) == 1) { + cmp = Z_STRVAL_PP(needle)[0]; + + while (p < endp) { + if (*(p++) == cmp) { + count++; } } } else { - p = Z_STRVAL_PP(haystack); - endp = p + Z_STRLEN_PP(haystack); - while (p <= endp) { - if ( (p = php_memnstr(p, Z_STRVAL_PP(needle), Z_STRLEN_PP(needle), endp)) != NULL ) { - p += Z_STRLEN_PP(needle); - count++; - } else { - break; - } + while ((p = php_memnstr(p, Z_STRVAL_PP(needle), Z_STRLEN_PP(needle), +endp))) { + p += Z_STRLEN_PP(needle); + count++; } } Index: php_string.h =================================================================== RCS file: /repository/php4/ext/standard/php_string.h,v retrieving revision 1.61 diff -u -3 -p -r1.61 php_string.h --- php_string.h 25 Sep 2002 18:06:05 -0000 1.61 +++ php_string.h 7 Oct 2002 21:11:46 -0000 @@ -133,19 +133,24 @@ static inline char * php_memnstr(char *haystack, char *needle, int needle_len, char *end) { char *p = haystack; - char first = *needle; + char ne = needle[needle_len-1]; - /* let end point to the last character where needle may start */ end -= needle_len; - + while (p <= end) { - while (*p != first) - if (++p > end) - return NULL; - if (memcmp(p, needle, needle_len) == 0) - return p; + if ((p = strchr(p, *needle)) && ne == p[needle_len-1]) { + if (!memcmp(needle, p, needle_len-1)) { + return p; + } + } + + if (p == NULL) { + return NULL; + } + p++; } + return NULL; }
-- PHP Development Mailing List <http://www.php.net/> To unsubscribe, visit: http://www.php.net/unsub.php