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

Reply via email to