Re: stripslashes() improvements

From: Date: Wed, 09 Jun 2004 10:52:42 +0000
Subject: Re: stripslashes() improvements
References: 1 2  Groups: php.internals 
Request: Send a blank email to internals+get-10340@lists.php.net to get a copy of this message
On Tue, 8 Jun 2004 16:03:19 +0200 (CEST), Derick Rethans <derick@php.net> wrote:
You'll have to proof that by writing testcases, for example try it with the test cases in the current source and write new ones for things that we don't have a test case for yet.
-PHPAPI void php_stripslashes(char *str, int *len TSRMLS_DC) +PHPAPI void php_stripslashes(char *str, size_t *len TSRMLS_DC)
You can't just change the API call, that will break things. regards, Derick
Ok. First of all, my version of the stripslashes() solves following bugs: #9437 #19947 #27848 I have successfully tested my code with test case from current source /ext/standard/tests/strings/add-and-stripslashes.phpt And here is my testcase, related to mentioned bugs: <?php echo "Stripslashes test: "; ini_set('magic_quotes_sybase', 0); $s = 'c:\\windows\\system32'; $s1 = '\\'; if ($s == stripslashes($s) && $s1 == stripslashes($s1)) echo "OK\n"; else echo "FAILED\n"; ?> Here is corrected code with standart API call: ====================cut====================== PHPAPI void php_stripslashes(char *str, int *len TSRMLS_DC) {
    char *s, *t;
    size_t l;
    size_t dst_len; /* length of the stripped string */
    if (len != NULL) l = dst_len = (size_t) *len;
    else l = dst_len = strlen(str);
    if (l < 2) return; /* there is no characters to strip */
    s = t = str;
    if (PG(magic_quotes_sybase)) { /* sybase magic_quotes ( '' -> ', \0 -> NULL) */
        while (l > 1) {
            if (*t == '\'' && *(t + 1) == '\'') {
                *s++ = '\'';
                t += 2;
                l--;
                dst_len--;
            } else if (*t == '\\' && *(t + 1) == '0') {
                *s++ = '\0';
                t += 2;
                l--;
                dst_len--;
            } else *s++ = *t++;
            l--;
        }
    } else { /* ordinary magic_qoutes (not sybase) ( \\ -> \, \' -> ', \" -> ", \0 -> NULL) */
        while (l > 1) {
            if (*t == '\\') {
                t++;
                switch (*t) {
                    case '\\' :
                    case '\'' :
                    case '"' :
                        *s++ = *t++; dst_len--; break;
                    case '0' : *s++ = '\0'; t++; dst_len--; break;
                    default : *s++ = '\\'; *s++ = *t++; break;
                }
                l -= 2;
            } else {
                *s++ = *t++;
                l--;
            }
        }
    }
    if (l == 1) *s++ = *t; /* copy the last symbol */
    if (len != NULL) *len = (int) dst_len; /* set length of the stripped string */
    *s = '\0';
} ====================cut====================== diff: ====================cut======================
--- string.c    Thu May 13 20:44:32 2004
+++ string_new.c    Wed Jun 09 13:47:21 2004
@@ -2159,70 +2159,51 @@ PHPAPI void php_stripslashes(char *str, int *len TSRMLS_DC) {
    char *s, *t;
- int l; - - if (len != NULL) {
-       l = *len;
- } else {
-       l = strlen(str);
- } - s = str; - t = str;
+    size_t l;
+    size_t dst_len; /* length of the stripped string */
- if (PG(magic_quotes_sybase)) {
-       while (l > 0) {
-           if (*t == '\'') {
-               if ((l > 0) && (t[1] == '\'')) {
-                   t++;
-                   if (len != NULL)
-                       (*len)--;
+    if (len != NULL) l = dst_len = (size_t) *len;
+    else l = dst_len = strlen(str);
+    if (l < 2) return; /* there is no characters to strip */
+    s = t = str;
+
+    if (PG(magic_quotes_sybase)) { /* sybase magic_quotes ( '' -> ', \0 -> NULL) */
+        while (l > 1) {
+            if (*t == '\'' && *(t + 1) == '\'') {
+                *s++ = '\'';
+                t += 2;
                    l--;
-               }
-               *s++ = *t++;
-           } else if (*t == '\\' && l > 0 && t[1] == '0') {
+                dst_len--;
+            } else if (*t == '\\' && *(t + 1) == '0') {
                    *s++='\0';
                    t += 2;
-                   if (len != NULL)
-                       (*len)--;
                    l--;
-           } else {
-               *s++ = *t++;
-           }
+                dst_len--;
+            } else *s++ = *t++;
            l--;
        }
-       *s = '\0';
-
-       return;
- } - - while (l > 0) {
+    } else { /* ordinary magic_qoutes (not sybase) ( \\ -> \, \' -> ', \" -> ", \0 -> NULL) */
+        while (l > 1) {
        if (*t == '\\') {
-           t++;                /* skip the slash */
-           if (len != NULL)
-               (*len)--;
-           l--;
-           if (l > 0) {
-               if (*t == '0') {
-                   *s++='\0';
                    t++;
-               } else {
-                   *s++ = *t++;    /* preserve the next character */
-               }
-               l--;
+                switch (*t) {
+                    case '\\' :
+                    case '\'' :
+                    case '"' :
+                        *s++ = *t++; dst_len--; break;
+                    case '0' : *s++ = '\0'; t++; dst_len--; break;
+                    default : *s++ = '\\'; *s++ = *t++; break;
            }
+                l -= 2;
        } else {
-           if (s != t) {
                *s++ = *t++;
-           } else {
-               s++;
-               t++;
-           }
            l--;
        }
    }
- if (s != t) {
-       *s = '\0';
    }
+    if (l == 1) *s++ = *t; /* copy the last symbol */
+    if (len != NULL) *len = (int) dst_len; /* set length of the stripped string */
+    *s = '\0';
} /* }}} */ ====================cut====================== -- Using Opera's revolutionary e-mail client: http://www.opera.com/m2/

« previous php.internals (#10340) next »