]> granicus.if.org Git - php/commitdiff
MFB: Filter fixes:
authorIlia Alshanetsky <iliaa@php.net>
Mon, 18 Dec 2006 04:24:38 +0000 (04:24 +0000)
committerIlia Alshanetsky <iliaa@php.net>
Mon, 18 Dec 2006 04:24:38 +0000 (04:24 +0000)
Fixed possible double encoding problem with sanitizing filters
Make use of space-strict strip_tags() function

ext/filter/sanitizing_filters.c
ext/filter/tests/025.phpt
ext/filter/tests/042.phpt [new file with mode: 0644]
ext/filter/tests/043.phpt [new file with mode: 0644]
ext/standard/string.c

index a390969b1c397d6b3dca2918dc1496f80803d051..3c2d9988f8e247ba3dc125025c07517be38459fa 100644 (file)
@@ -27,52 +27,29 @@ typedef unsigned long filter_map[256];
 /* }}} */
 
 /* {{{ HELPER FUNCTIONS */
-static void php_filter_encode_html(zval *value, const char* chars, int encode_nul)
+static void php_filter_encode_html(zval *value, const unsigned char *chars)
 {
-       register int x, y;
        smart_str str = {0};
        int len = Z_STRLEN_P(value);
-       char *s = Z_STRVAL_P(value);
+       unsigned char *s = (unsigned char *)Z_STRVAL_P(value);
+       unsigned char *e = s + len;
 
        if (Z_STRLEN_P(value) == 0) {
                return;
        }
 
-       for (x = 0, y = 0; len--; x++, y++) {
-               if (strchr(chars, s[x]) || (encode_nul && s[x] == 0)) {
+       while (s < e) {
+               if (chars[*s]) {
                        smart_str_appendl(&str, "&#", 2);
-                       smart_str_append_long(&str, s[x]);
+                       smart_str_append_unsigned(&str, (unsigned long)*s);
                        smart_str_appendc(&str, ';');
                } else {
-                       smart_str_appendc(&str, s[x]);
+                       /* XXX: this needs to be optimized to work with blocks of 'safe' chars */
+                       smart_str_appendc(&str, *s);
                }
+               s++;
        }
-       smart_str_0(&str);
-       efree(Z_STRVAL_P(value));
-       Z_STRVAL_P(value) = str.c;
-       Z_STRLEN_P(value) = str.len;
-}
-
-static void php_filter_encode_html_high_low(zval *value, long flags)
-{
-       register int x, y;
-       smart_str str = {0};
-       int len = Z_STRLEN_P(value);
-       unsigned char *s = (unsigned char *)Z_STRVAL_P(value);
 
-       if (Z_STRLEN_P(value) == 0) {
-               return;
-       }
-       
-       for (x = 0, y = 0; len--; x++, y++) {
-               if (((flags & FILTER_FLAG_ENCODE_LOW) && (s[x] < 32)) || ((flags & FILTER_FLAG_ENCODE_HIGH) && (s[x] > 127))) {
-                       smart_str_appendl(&str, "&#", 2);
-                       smart_str_append_unsigned(&str, s[x]);
-                       smart_str_appendc(&str, ';');
-               } else {
-                       smart_str_appendc(&str, s[x]);
-               }
-       }
        smart_str_0(&str);
        efree(Z_STRVAL_P(value));
        Z_STRVAL_P(value) = str.c;
@@ -181,9 +158,28 @@ static void filter_map_apply(zval *value, filter_map *map)
 void php_filter_string(PHP_INPUT_FILTER_PARAM_DECL)
 {
        size_t new_len;
-       
+       unsigned char enc[256] = {0};
+
+       /* strip high/strip low ( see flags )*/
+       php_filter_strip(value, flags);
+
+       if (!(flags & FILTER_FLAG_NO_ENCODE_QUOTES)) {
+               enc['\''] = enc['"'] = 1;
+       }
+       if (flags & FILTER_FLAG_ENCODE_AMP) {
+               enc['&'] = 1;
+       }
+       if (flags & FILTER_FLAG_ENCODE_LOW) {
+               memset(enc, 1, 32);
+       }
+       if (flags & FILTER_FLAG_ENCODE_HIGH) {
+               memset(enc + 127, 1, sizeof(enc) - 127);
+       }
+
+       php_filter_encode_html(value, enc);
+
        /* strip tags, implicitly also removes \0 chars */
-       new_len = php_strip_tags(Z_STRVAL_P(value), Z_STRLEN_P(value), NULL, NULL, 0);
+       new_len = php_strip_tags(Z_STRVAL_P(value), Z_STRLEN_P(value), NULL, NULL, -1);
        Z_STRLEN_P(value) = new_len;
 
        if (new_len == 0) {
@@ -191,21 +187,6 @@ void php_filter_string(PHP_INPUT_FILTER_PARAM_DECL)
                ZVAL_EMPTY_STRING(value);
                return;
        }
-
-       if (! (flags & FILTER_FLAG_NO_ENCODE_QUOTES)) {
-               /* encode ' and " to numerical entity */
-               php_filter_encode_html(value, "'\"", 0);
-       }
-       /* strip high/strip low ( see flags )*/
-       php_filter_strip(value, flags);
-
-       /* encode low/encode high flags */
-       php_filter_encode_html_high_low(value, flags);
-
-       /* also all the flags - & encode as %xx */
-       if (flags & FILTER_FLAG_ENCODE_AMP) {
-               php_filter_encode_html(value, "&", 0);
-       }
 }
 /* }}} */
 
@@ -222,11 +203,21 @@ void php_filter_encoded(PHP_INPUT_FILTER_PARAM_DECL)
 /* {{{ php_filter_special_chars */
 void php_filter_special_chars(PHP_INPUT_FILTER_PARAM_DECL)
 {
+       unsigned char enc[256] = {0};
+
+       php_filter_strip(value, flags);
+
        /* encodes ' " < > & \0 to numerical entities */
-       php_filter_encode_html(value, "'\"<>&", 1);
+       enc['\''] = enc['"'] = enc['<'] = enc['>'] = enc['&'] = enc[0] = 1;
+
        /* if strip low is not set, then we encode them as &#xx; */
-       php_filter_strip(value, flags);
-       php_filter_encode_html_high_low(value, FILTER_FLAG_ENCODE_LOW | flags);
+       memset(enc, 1, 32);
+
+       if (flags & FILTER_FLAG_ENCODE_HIGH) {
+               memset(enc + 127, 1, sizeof(enc) - 127);
+       }
+       
+       php_filter_encode_html(value, enc);     
 }
 /* }}} */
 
@@ -235,11 +226,21 @@ void php_filter_unsafe_raw(PHP_INPUT_FILTER_PARAM_DECL)
 {
        /* Only if no flags are set (optimization) */
        if (flags != 0 && Z_STRLEN_P(value) > 0) {
+               unsigned char enc[256] = {0};
+
                php_filter_strip(value, flags);
+
                if (flags & FILTER_FLAG_ENCODE_AMP) {
-                       php_filter_encode_html(value, "&", 0);
+                       enc['&'] = 1;
                }
-               php_filter_encode_html_high_low(value, flags);
+               if (flags & FILTER_FLAG_ENCODE_LOW) {
+                       memset(enc, 1, 32);
+               }
+               if (flags & FILTER_FLAG_ENCODE_HIGH) {
+                       memset(enc + 127, 1, sizeof(enc) - 127);
+               }
+
+               php_filter_encode_html(value, enc);     
        }
 }
 /* }}} */
index d1e94abf02dd2af13b0de1738280fb389cf3214d..bf85e3607159c2a4855e4f9d5c99e3f144071496 100644 (file)
@@ -17,7 +17,7 @@ echo "Done\n";
 string(0) ""
 string(0) ""
 string(12) "!@#$%^&*()'""
-string(32) "!@#$%^&#38;*()&#38;#39;&#38;#34;"
+string(24) "!@#$%^&#38;*()&#39;&#34;"
 string(11) "`1234567890"
 string(5) "`123`"
 string(1) "."
diff --git a/ext/filter/tests/042.phpt b/ext/filter/tests/042.phpt
new file mode 100644 (file)
index 0000000..b295e06
--- /dev/null
@@ -0,0 +1,10 @@
+--TEST--
+Combination of strip & sanitize filters
+--FILE--
+<?php 
+$var = 'XYZ< script>alert(/ext/filter+bypass/);< /script>ABC';
+$a = filter_var($var, FILTER_SANITIZE_STRING, array("flags" => FILTER_FLAG_STRIP_LOW));
+echo $a . "\n";
+?>
+--EXPECT--
+XYZalert(/ext/filter+bypass/);ABC
diff --git a/ext/filter/tests/043.phpt b/ext/filter/tests/043.phpt
new file mode 100644 (file)
index 0000000..b8d0eec
--- /dev/null
@@ -0,0 +1,267 @@
+--TEST--
+Character encoding test
+--FILE--
+<?php 
+$flags = FILTER_FLAG_ENCODE_AMP|FILTER_FLAG_ENCODE_LOW|FILTER_FLAG_ENCODE_HIGH;
+
+for ($i = 0; $i < 256; $i++) {
+       var_dump(filter_var(chr($i), FILTER_SANITIZE_STRING, array("flags" => $flags)));
+}
+?>
+--EXPECT--
+string(4) "&#0;"
+string(4) "&#1;"
+string(4) "&#2;"
+string(4) "&#3;"
+string(4) "&#4;"
+string(4) "&#5;"
+string(4) "&#6;"
+string(4) "&#7;"
+string(4) "&#8;"
+string(4) "&#9;"
+string(5) "&#10;"
+string(5) "&#11;"
+string(5) "&#12;"
+string(5) "&#13;"
+string(5) "&#14;"
+string(5) "&#15;"
+string(5) "&#16;"
+string(5) "&#17;"
+string(5) "&#18;"
+string(5) "&#19;"
+string(5) "&#20;"
+string(5) "&#21;"
+string(5) "&#22;"
+string(5) "&#23;"
+string(5) "&#24;"
+string(5) "&#25;"
+string(5) "&#26;"
+string(5) "&#27;"
+string(5) "&#28;"
+string(5) "&#29;"
+string(5) "&#30;"
+string(5) "&#31;"
+string(1) " "
+string(1) "!"
+string(5) "&#34;"
+string(1) "#"
+string(1) "$"
+string(1) "%"
+string(5) "&#38;"
+string(5) "&#39;"
+string(1) "("
+string(1) ")"
+string(1) "*"
+string(1) "+"
+string(1) ","
+string(1) "-"
+string(1) "."
+string(1) "/"
+string(1) "0"
+string(1) "1"
+string(1) "2"
+string(1) "3"
+string(1) "4"
+string(1) "5"
+string(1) "6"
+string(1) "7"
+string(1) "8"
+string(1) "9"
+string(1) ":"
+string(1) ";"
+string(0) ""
+string(1) "="
+string(1) ">"
+string(1) "?"
+string(1) "@"
+string(1) "A"
+string(1) "B"
+string(1) "C"
+string(1) "D"
+string(1) "E"
+string(1) "F"
+string(1) "G"
+string(1) "H"
+string(1) "I"
+string(1) "J"
+string(1) "K"
+string(1) "L"
+string(1) "M"
+string(1) "N"
+string(1) "O"
+string(1) "P"
+string(1) "Q"
+string(1) "R"
+string(1) "S"
+string(1) "T"
+string(1) "U"
+string(1) "V"
+string(1) "W"
+string(1) "X"
+string(1) "Y"
+string(1) "Z"
+string(1) "["
+string(1) "\"
+string(1) "]"
+string(1) "^"
+string(1) "_"
+string(1) "`"
+string(1) "a"
+string(1) "b"
+string(1) "c"
+string(1) "d"
+string(1) "e"
+string(1) "f"
+string(1) "g"
+string(1) "h"
+string(1) "i"
+string(1) "j"
+string(1) "k"
+string(1) "l"
+string(1) "m"
+string(1) "n"
+string(1) "o"
+string(1) "p"
+string(1) "q"
+string(1) "r"
+string(1) "s"
+string(1) "t"
+string(1) "u"
+string(1) "v"
+string(1) "w"
+string(1) "x"
+string(1) "y"
+string(1) "z"
+string(1) "{"
+string(1) "|"
+string(1) "}"
+string(1) "~"
+string(6) "&#127;"
+string(6) "&#128;"
+string(6) "&#129;"
+string(6) "&#130;"
+string(6) "&#131;"
+string(6) "&#132;"
+string(6) "&#133;"
+string(6) "&#134;"
+string(6) "&#135;"
+string(6) "&#136;"
+string(6) "&#137;"
+string(6) "&#138;"
+string(6) "&#139;"
+string(6) "&#140;"
+string(6) "&#141;"
+string(6) "&#142;"
+string(6) "&#143;"
+string(6) "&#144;"
+string(6) "&#145;"
+string(6) "&#146;"
+string(6) "&#147;"
+string(6) "&#148;"
+string(6) "&#149;"
+string(6) "&#150;"
+string(6) "&#151;"
+string(6) "&#152;"
+string(6) "&#153;"
+string(6) "&#154;"
+string(6) "&#155;"
+string(6) "&#156;"
+string(6) "&#157;"
+string(6) "&#158;"
+string(6) "&#159;"
+string(6) "&#160;"
+string(6) "&#161;"
+string(6) "&#162;"
+string(6) "&#163;"
+string(6) "&#164;"
+string(6) "&#165;"
+string(6) "&#166;"
+string(6) "&#167;"
+string(6) "&#168;"
+string(6) "&#169;"
+string(6) "&#170;"
+string(6) "&#171;"
+string(6) "&#172;"
+string(6) "&#173;"
+string(6) "&#174;"
+string(6) "&#175;"
+string(6) "&#176;"
+string(6) "&#177;"
+string(6) "&#178;"
+string(6) "&#179;"
+string(6) "&#180;"
+string(6) "&#181;"
+string(6) "&#182;"
+string(6) "&#183;"
+string(6) "&#184;"
+string(6) "&#185;"
+string(6) "&#186;"
+string(6) "&#187;"
+string(6) "&#188;"
+string(6) "&#189;"
+string(6) "&#190;"
+string(6) "&#191;"
+string(6) "&#192;"
+string(6) "&#193;"
+string(6) "&#194;"
+string(6) "&#195;"
+string(6) "&#196;"
+string(6) "&#197;"
+string(6) "&#198;"
+string(6) "&#199;"
+string(6) "&#200;"
+string(6) "&#201;"
+string(6) "&#202;"
+string(6) "&#203;"
+string(6) "&#204;"
+string(6) "&#205;"
+string(6) "&#206;"
+string(6) "&#207;"
+string(6) "&#208;"
+string(6) "&#209;"
+string(6) "&#210;"
+string(6) "&#211;"
+string(6) "&#212;"
+string(6) "&#213;"
+string(6) "&#214;"
+string(6) "&#215;"
+string(6) "&#216;"
+string(6) "&#217;"
+string(6) "&#218;"
+string(6) "&#219;"
+string(6) "&#220;"
+string(6) "&#221;"
+string(6) "&#222;"
+string(6) "&#223;"
+string(6) "&#224;"
+string(6) "&#225;"
+string(6) "&#226;"
+string(6) "&#227;"
+string(6) "&#228;"
+string(6) "&#229;"
+string(6) "&#230;"
+string(6) "&#231;"
+string(6) "&#232;"
+string(6) "&#233;"
+string(6) "&#234;"
+string(6) "&#235;"
+string(6) "&#236;"
+string(6) "&#237;"
+string(6) "&#238;"
+string(6) "&#239;"
+string(6) "&#240;"
+string(6) "&#241;"
+string(6) "&#242;"
+string(6) "&#243;"
+string(6) "&#244;"
+string(6) "&#245;"
+string(6) "&#246;"
+string(6) "&#247;"
+string(6) "&#248;"
+string(6) "&#249;"
+string(6) "&#250;"
+string(6) "&#251;"
+string(6) "&#252;"
+string(6) "&#253;"
+string(6) "&#254;"
+string(6) "&#255;"
\ No newline at end of file
index e4a97393e9d880244d593c5f191e9095905dcdff..f9c808efcc3cd72876205f73369344f816665f9c 100644 (file)
@@ -6532,7 +6532,7 @@ PHPAPI size_t php_strip_tags(char *rbuf, int len, int *stateptr, char *allow, in
                        case '\0':
                                break;
                        case '<':
-                               if (isspace(*(p + 1))) {
+                               if (isspace(*(p + 1)) && allow_len >=- 0) {
                                        goto reg_char;
                                }
                                if (state == 0) {