PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/filter - sanitizing_filters.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 160 164 97.6 %
Date: 2016-07-26 Functions: 16 16 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   +----------------------------------------------------------------------+
       3             :   | PHP Version 7                                                        |
       4             :   +----------------------------------------------------------------------+
       5             :   | Copyright (c) 1997-2016 The PHP Group                                |
       6             :   +----------------------------------------------------------------------+
       7             :   | This source file is subject to version 3.01 of the PHP license,      |
       8             :   | that is bundled with this package in the file LICENSE, and is        |
       9             :   | available through the world-wide-web at the following url:           |
      10             :   | http://www.php.net/license/3_01.txt                                  |
      11             :   | If you did not receive a copy of the PHP license and are unable to   |
      12             :   | obtain it through the world-wide-web, please send a note to          |
      13             :   | license@php.net so we can mail you a copy immediately.               |
      14             :   +----------------------------------------------------------------------+
      15             :   | Authors: Derick Rethans <derick@php.net>                             |
      16             :   +----------------------------------------------------------------------+
      17             : */
      18             : 
      19             : /* $Id$ */
      20             : 
      21             : #include "php_filter.h"
      22             : #include "filter_private.h"
      23             : #include "zend_smart_str.h"
      24             : 
      25             : /* {{{ STRUCTS */
      26             : typedef unsigned long filter_map[256];
      27             : /* }}} */
      28             : 
      29             : /* {{{ HELPER FUNCTIONS */
      30         367 : static void php_filter_encode_html(zval *value, const unsigned char *chars)
      31             : {
      32         367 :         smart_str str = {0};
      33         367 :         size_t len = Z_STRLEN_P(value);
      34         367 :         unsigned char *s = (unsigned char *)Z_STRVAL_P(value);
      35         367 :         unsigned char *e = s + len;
      36             : 
      37         367 :         if (Z_STRLEN_P(value) == 0) {
      38          10 :                 return;
      39             :         }
      40             : 
      41        2477 :         while (s < e) {
      42        1763 :                 if (chars[*s]) {
      43             :                         smart_str_appendl(&str, "&#", 2);
      44         242 :                         smart_str_append_unsigned(&str, (zend_ulong)*s);
      45             :                         smart_str_appendc(&str, ';');
      46             :                 } else {
      47             :                         /* XXX: this needs to be optimized to work with blocks of 'safe' chars */
      48        1521 :                         smart_str_appendc(&str, *s);
      49             :                 }
      50        1763 :                 s++;
      51             :         }
      52             : 
      53             :         smart_str_0(&str);
      54         357 :         zval_ptr_dtor(value);
      55         357 :         ZVAL_NEW_STR(value, str.s);
      56             : }
      57             : 
      58             : static const unsigned char hexchars[] = "0123456789ABCDEF";
      59             : 
      60             : #define LOWALPHA    "abcdefghijklmnopqrstuvwxyz"
      61             : #define HIALPHA     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
      62             : #define DIGIT       "0123456789"
      63             : 
      64             : #define DEFAULT_URL_ENCODE    LOWALPHA HIALPHA DIGIT "-._"
      65             : 
      66          28 : static void php_filter_encode_url(zval *value, const unsigned char* chars, const int char_len, int high, int low, int encode_nul)
      67             : {
      68             :         unsigned char *p;
      69             :         unsigned char tmp[256];
      70          28 :         unsigned char *s = (unsigned char *)chars;
      71          28 :         unsigned char *e = s + char_len;
      72             :         zend_string *str;
      73             : 
      74          28 :         memset(tmp, 1, sizeof(tmp)-1);
      75             : 
      76        1876 :         while (s < e) {
      77        1820 :                 tmp[*s++] = '\0';
      78             :         }
      79             : /* XXX: This is not needed since these chars in the allowed list never include the high/low/null value
      80             :         if (encode_nul) {
      81             :                 tmp[0] = 1;
      82             :         }
      83             :         if (high) {
      84             :                 memset(tmp + 127, 1, sizeof(tmp) - 127);
      85             :         }
      86             :         if (low) {
      87             :                 memset(tmp, 1, 32);
      88             :         }
      89             : */
      90          56 :         str = zend_string_safe_alloc(Z_STRLEN_P(value), 3, 0, 0);
      91          28 :         p = (unsigned char *) ZSTR_VAL(str);
      92          28 :         s = (unsigned char *) Z_STRVAL_P(value);
      93          28 :         e = s + Z_STRLEN_P(value);
      94             : 
      95         402 :         while (s < e) {
      96         346 :                 if (tmp[*s]) {
      97         108 :                         *p++ = '%';
      98         108 :                         *p++ = hexchars[(unsigned char) *s >> 4];
      99         108 :                         *p++ = hexchars[(unsigned char) *s & 15];
     100             :                 } else {
     101         238 :                         *p++ = *s;
     102             :                 }
     103         346 :                 s++;
     104             :         }
     105          28 :         *p = '\0';
     106          28 :         ZSTR_LEN(str) = p - (unsigned char *)ZSTR_VAL(str);
     107          28 :         zval_ptr_dtor(value);
     108          28 :         ZVAL_NEW_STR(value, str);
     109          28 : }
     110             : 
     111         395 : static void php_filter_strip(zval *value, zend_long flags)
     112             : {
     113             :         unsigned char *str;
     114             :         size_t i;
     115             :         int c;
     116             :         zend_string *buf;
     117             : 
     118             :         /* Optimization for if no strip flags are set */
     119         395 :         if (!(flags & (FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH | FILTER_FLAG_STRIP_BACKTICK))) {
     120         379 :                 return;
     121             :         }
     122             : 
     123          16 :         str = (unsigned char *)Z_STRVAL_P(value);
     124          32 :         buf = zend_string_alloc(Z_STRLEN_P(value) + 1, 0);
     125          16 :         c = 0;
     126         404 :         for (i = 0; i < Z_STRLEN_P(value); i++) {
     127         388 :                 if ((str[i] >= 127) && (flags & FILTER_FLAG_STRIP_HIGH)) {
     128         384 :                 } else if ((str[i] < 32) && (flags & FILTER_FLAG_STRIP_LOW)) {
     129         382 :                 } else if ((str[i] == '`') && (flags & FILTER_FLAG_STRIP_BACKTICK)) {
     130             :                 } else {
     131         364 :                         ZSTR_VAL(buf)[c] = str[i];
     132         364 :                         ++c;
     133             :                 }
     134             :         }
     135             :         /* update zval string data */
     136          16 :         ZSTR_VAL(buf)[c] = '\0';
     137          16 :         ZSTR_LEN(buf) = c;
     138          16 :         zval_ptr_dtor(value);
     139          16 :         ZVAL_NEW_STR(value, buf);
     140             : }
     141             : /* }}} */
     142             : 
     143             : /* {{{ FILTER MAP HELPERS */
     144         128 : static void filter_map_init(filter_map *map)
     145             : {
     146         128 :         memset(map, 0, sizeof(filter_map));
     147         128 : }
     148             : 
     149         138 : static void filter_map_update(filter_map *map, int flag, const unsigned char *allowed_list)
     150             : {
     151             :         size_t l, i;
     152             : 
     153         138 :         l = strlen((const char*)allowed_list);
     154        8998 :         for (i = 0; i < l; ++i) {
     155        8860 :                 (*map)[allowed_list[i]] = flag;
     156             :         }
     157         138 : }
     158             : 
     159         128 : static void filter_map_apply(zval *value, filter_map *map)
     160             : {
     161             :         unsigned char *str;
     162             :         size_t i;
     163             :         int c;
     164             :         zend_string *buf;
     165             : 
     166         128 :         str = (unsigned char *)Z_STRVAL_P(value);
     167         256 :         buf = zend_string_alloc(Z_STRLEN_P(value) + 1, 0);
     168         128 :         c = 0;
     169        2520 :         for (i = 0; i < Z_STRLEN_P(value); i++) {
     170        2392 :                 if ((*map)[str[i]]) {
     171        2156 :                         ZSTR_VAL(buf)[c] = str[i];
     172        2156 :                         ++c;
     173             :                 }
     174             :         }
     175             :         /* update zval string data */
     176         128 :         ZSTR_VAL(buf)[c] = '\0';
     177         128 :         ZSTR_LEN(buf) = c;
     178         128 :         zval_ptr_dtor(value);
     179         128 :         ZVAL_NEW_STR(value, buf);
     180         128 : }
     181             : /* }}} */
     182             : 
     183             : /* {{{ php_filter_string */
     184         312 : void php_filter_string(PHP_INPUT_FILTER_PARAM_DECL)
     185             : {
     186             :         size_t new_len;
     187         312 :         unsigned char enc[256] = {0};
     188             : 
     189         312 :         if (!Z_REFCOUNTED_P(value)) {
     190          46 :                 ZVAL_STRINGL(value, Z_STRVAL_P(value), Z_STRLEN_P(value));
     191             :         }
     192             : 
     193             :         /* strip high/strip low ( see flags )*/
     194         312 :         php_filter_strip(value, flags);
     195             : 
     196         312 :         if (!(flags & FILTER_FLAG_NO_ENCODE_QUOTES)) {
     197         309 :                 enc['\''] = enc['"'] = 1;
     198             :         }
     199         312 :         if (flags & FILTER_FLAG_ENCODE_AMP) {
     200         257 :                 enc['&'] = 1;
     201             :         }
     202         312 :         if (flags & FILTER_FLAG_ENCODE_LOW) {
     203         256 :                 memset(enc, 1, 32);
     204             :         }
     205         312 :         if (flags & FILTER_FLAG_ENCODE_HIGH) {
     206         256 :                 memset(enc + 127, 1, sizeof(enc) - 127);
     207             :         }
     208             : 
     209         312 :         php_filter_encode_html(value, enc);
     210             : 
     211             :         /* strip tags, implicitly also removes \0 chars */
     212         312 :         new_len = php_strip_tags_ex(Z_STRVAL_P(value), Z_STRLEN_P(value), NULL, NULL, 0, 1);
     213         312 :         Z_STRLEN_P(value) = new_len;
     214             : 
     215         312 :         if (new_len == 0) {
     216             :                 zval_dtor(value);
     217           7 :                 if (flags & FILTER_FLAG_EMPTY_STRING_NULL) {
     218           0 :                         ZVAL_NULL(value);
     219             :                 } else {
     220           7 :                         ZVAL_EMPTY_STRING(value);
     221             :                 }
     222           7 :                 return;
     223             :         }
     224             : }
     225             : /* }}} */
     226             : 
     227             : /* {{{ php_filter_encoded */
     228          28 : void php_filter_encoded(PHP_INPUT_FILTER_PARAM_DECL)
     229             : {
     230             :         /* apply strip_high and strip_low filters */
     231          28 :         php_filter_strip(value, flags);
     232             :         /* urlencode */
     233          28 :         php_filter_encode_url(value, (unsigned char *)DEFAULT_URL_ENCODE, sizeof(DEFAULT_URL_ENCODE)-1, flags & FILTER_FLAG_ENCODE_HIGH, flags & FILTER_FLAG_ENCODE_LOW, 1);
     234          28 : }
     235             : /* }}} */
     236             : 
     237             : /* {{{ php_filter_special_chars */
     238          29 : void php_filter_special_chars(PHP_INPUT_FILTER_PARAM_DECL)
     239             : {
     240          29 :         unsigned char enc[256] = {0};
     241             : 
     242          29 :         php_filter_strip(value, flags);
     243             : 
     244             :         /* encodes ' " < > & \0 to numerical entities */
     245          29 :         enc['\''] = enc['"'] = enc['<'] = enc['>'] = enc['&'] = enc[0] = 1;
     246             : 
     247             :         /* if strip low is not set, then we encode them as &#xx; */
     248          29 :         memset(enc, 1, 32);
     249             : 
     250          29 :         if (flags & FILTER_FLAG_ENCODE_HIGH) {
     251           4 :                 memset(enc + 127, 1, sizeof(enc) - 127);
     252             :         }
     253             : 
     254          29 :         php_filter_encode_html(value, enc);
     255          29 : }
     256             : /* }}} */
     257             : 
     258             : /* {{{ php_filter_full_special_chars */
     259          10 : void php_filter_full_special_chars(PHP_INPUT_FILTER_PARAM_DECL)
     260             : {
     261             :         zend_string *buf;
     262             :         int quotes;
     263             : 
     264          10 :         if (!(flags & FILTER_FLAG_NO_ENCODE_QUOTES)) {
     265          10 :                 quotes = ENT_QUOTES;
     266             :         } else {
     267           0 :                 quotes = ENT_NOQUOTES;
     268             :         }
     269          10 :         buf = php_escape_html_entities_ex((unsigned char *) Z_STRVAL_P(value), Z_STRLEN_P(value), 1, quotes, SG(default_charset), 0);
     270          10 :         zval_ptr_dtor(value);
     271          10 :         ZVAL_STR(value, buf);
     272          10 : }
     273             : /* }}} */
     274             : 
     275             : /* {{{ php_filter_unsafe_raw */
     276          31 : void php_filter_unsafe_raw(PHP_INPUT_FILTER_PARAM_DECL)
     277             : {
     278             :         /* Only if no flags are set (optimization) */
     279          57 :         if (flags != 0 && Z_STRLEN_P(value) > 0) {
     280          26 :                 unsigned char enc[256] = {0};
     281             : 
     282          26 :                 php_filter_strip(value, flags);
     283             : 
     284          26 :                 if (flags & FILTER_FLAG_ENCODE_AMP) {
     285           4 :                         enc['&'] = 1;
     286             :                 }
     287          26 :                 if (flags & FILTER_FLAG_ENCODE_LOW) {
     288           0 :                         memset(enc, 1, 32);
     289             :                 }
     290          26 :                 if (flags & FILTER_FLAG_ENCODE_HIGH) {
     291           0 :                         memset(enc + 127, 1, sizeof(enc) - 127);
     292             :                 }
     293             : 
     294          26 :                 php_filter_encode_html(value, enc);
     295           5 :         } else if (flags & FILTER_FLAG_EMPTY_STRING_NULL && Z_STRLEN_P(value) == 0) {
     296             :                 zval_dtor(value);
     297           1 :                 ZVAL_NULL(value);
     298             :         }
     299          31 : }
     300             : /* }}} */
     301             : 
     302             : /* {{{ php_filter_email */
     303             : #define SAFE        "$-_.+"
     304             : #define EXTRA       "!*'(),"
     305             : #define NATIONAL    "{}|\\^~[]`"
     306             : #define PUNCTUATION "<>#%\""
     307             : #define RESERVED    ";/?:@&="
     308             : 
     309          15 : void php_filter_email(PHP_INPUT_FILTER_PARAM_DECL)
     310             : {
     311             :         /* Check section 6 of rfc 822 http://www.faqs.org/rfcs/rfc822.html */
     312          15 :         const unsigned char allowed_list[] = LOWALPHA HIALPHA DIGIT "!#$%&'*+-=?^_`{|}~@.[]";
     313             :         filter_map     map;
     314             : 
     315          15 :         filter_map_init(&map);
     316          15 :         filter_map_update(&map, 1, allowed_list);
     317          15 :         filter_map_apply(value, &map);
     318          15 : }
     319             : /* }}} */
     320             : 
     321             : /* {{{ php_filter_url */
     322          76 : void php_filter_url(PHP_INPUT_FILTER_PARAM_DECL)
     323             : {
     324             :         /* Strip all chars not part of section 5 of
     325             :          * http://www.faqs.org/rfcs/rfc1738.html */
     326          76 :         const unsigned char allowed_list[] = LOWALPHA HIALPHA DIGIT SAFE EXTRA NATIONAL PUNCTUATION RESERVED;
     327             :         filter_map     map;
     328             : 
     329          76 :         filter_map_init(&map);
     330          76 :         filter_map_update(&map, 1, allowed_list);
     331          76 :         filter_map_apply(value, &map);
     332          76 : }
     333             : /* }}} */
     334             : 
     335             : /* {{{ php_filter_number_int */
     336          17 : void php_filter_number_int(PHP_INPUT_FILTER_PARAM_DECL)
     337             : {
     338             :         /* strip everything [^0-9+-] */
     339          17 :         const unsigned char allowed_list[] = "+-" DIGIT;
     340             :         filter_map     map;
     341             : 
     342          17 :         filter_map_init(&map);
     343          17 :         filter_map_update(&map, 1, allowed_list);
     344          17 :         filter_map_apply(value, &map);
     345          17 : }
     346             : /* }}} */
     347             : 
     348             : /* {{{ php_filter_number_float */
     349          20 : void php_filter_number_float(PHP_INPUT_FILTER_PARAM_DECL)
     350             : {
     351             :         /* strip everything [^0-9+-] */
     352          20 :         const unsigned char allowed_list[] = "+-" DIGIT;
     353             :         filter_map     map;
     354             : 
     355          20 :         filter_map_init(&map);
     356          20 :         filter_map_update(&map, 1, allowed_list);
     357             : 
     358             :         /* depending on flags, strip '.', 'e', ",", "'" */
     359          20 :         if (flags & FILTER_FLAG_ALLOW_FRACTION) {
     360           6 :                 filter_map_update(&map, 2, (const unsigned char *) ".");
     361             :         }
     362          20 :         if (flags & FILTER_FLAG_ALLOW_THOUSAND) {
     363           2 :                 filter_map_update(&map, 3,  (const unsigned char *) ",");
     364             :         }
     365          20 :         if (flags & FILTER_FLAG_ALLOW_SCIENTIFIC) {
     366           2 :                 filter_map_update(&map, 4,  (const unsigned char *) "eE");
     367             :         }
     368          20 :         filter_map_apply(value, &map);
     369          20 : }
     370             : /* }}} */
     371             : 
     372             : /* {{{ php_filter_magic_quotes */
     373          14 : void php_filter_magic_quotes(PHP_INPUT_FILTER_PARAM_DECL)
     374             : {
     375             :         zend_string *buf;
     376             : 
     377             :         /* just call php_addslashes quotes */
     378          14 :         buf = php_addslashes(Z_STR_P(value), 0);
     379             : 
     380          14 :         zval_ptr_dtor(value);
     381          14 :         ZVAL_STR(value, buf);
     382          14 : }
     383             : /* }}} */
     384             : 
     385             : /*
     386             :  * Local variables:
     387             :  * tab-width: 4
     388             :  * c-basic-offset: 4
     389             :  * End:
     390             :  * vim600: noet sw=4 ts=4 fdm=marker
     391             :  * vim<600: noet sw=4 ts=4
     392             :  */

Generated by: LCOV version 1.10

Generated at Tue, 26 Jul 2016 17:07:34 +0000 (31 hours ago)

Copyright © 2005-2016 The PHP Group
All rights reserved.