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