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

LTP GCOV extension - code coverage report
Current view: directory - filter - logical_filters.c
Test: PHP Code Coverage
Date: 2009-11-23 Instrumented lines: 302
Code covered: 84.4 % Executed lines: 255
Legend: not executed executed

       1                 : /*
       2                 :   +----------------------------------------------------------------------+
       3                 :   | PHP Version 6                                                        |
       4                 :   +----------------------------------------------------------------------+
       5                 :   | Copyright (c) 1997-2009 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                 :   |          Pierre-A. Joye <pierre@php.net>                             |
      17                 :   +----------------------------------------------------------------------+
      18                 : */
      19                 : 
      20                 : /* $Id: logical_filters.c 290791 2009-11-15 16:53:40Z felipe $ */
      21                 : 
      22                 : #include "php_filter.h"
      23                 : #include "filter_private.h"
      24                 : #include "ext/standard/url.h"
      25                 : #include "ext/pcre/php_pcre.h"
      26                 : 
      27                 : #include "zend_multiply.h"
      28                 : 
      29                 : #if HAVE_ARPA_INET_H
      30                 : # include <arpa/inet.h>
      31                 : #endif
      32                 : 
      33                 : #ifndef INADDR_NONE
      34                 : # define INADDR_NONE ((unsigned long int) -1)
      35                 : #endif
      36                 : 
      37                 : 
      38                 : /* {{{ FETCH_LONG_OPTION(var_name, option_name) */
      39                 : #define FETCH_LONG_OPTION(var_name, option_name)                                                                         \
      40                 :         var_name = 0;                                                                                                        \
      41                 :         var_name##_set = 0;                                                                                                  \
      42                 :         if (option_array) {                                                                                                  \
      43                 :                 if (zend_ascii_hash_find(HASH_OF(option_array), option_name, sizeof(option_name), (void **) &option_val) == SUCCESS) { \
      44                 :                         PHP_FILTER_GET_LONG_OPT(option_val, var_name);                                                                                           \
      45                 :                         var_name##_set = 1;                                                                                          \
      46                 :                 }                                                                                                                \
      47                 :         }
      48                 : /* }}} */
      49                 : 
      50                 : /* {{{ FETCH_STRING_OPTION(var_name, option_name) */
      51                 : #define FETCH_STRING_OPTION(var_name, option_name)                                                                       \
      52                 :         var_name = NULL;                                                                                                     \
      53                 :         var_name##_set = 0;                                                                                                  \
      54                 :         var_name##_len = 0;                                                                                                  \
      55                 :         if (option_array) {                                                                                                  \
      56                 :                 if (zend_ascii_hash_find(HASH_OF(option_array), option_name, sizeof(option_name), (void **) &option_val) == SUCCESS) { \
      57                 :                         if (Z_TYPE_PP(option_val) == IS_STRING) {                                                                    \
      58                 :                                 var_name = Z_STRVAL_PP(option_val);                                                                      \
      59                 :                                 var_name##_len = Z_STRLEN_PP(option_val);                                                                \
      60                 :                                 var_name##_set = 1;                                                                                      \
      61                 :                         }                                                                                                            \
      62                 :                 }                                                                                                                \
      63                 :         }
      64                 : /* }}} */
      65                 : 
      66                 : #define FORMAT_IPV4    4
      67                 : #define FORMAT_IPV6    6
      68                 : 
      69              42 : static int php_filter_parse_int(const char *str, unsigned int str_len, long *ret TSRMLS_DC) { /* {{{ */
      70                 :         long ctx_value;
      71              42 :         int sign = 0;
      72              42 :         const char *end = str + str_len;
      73                 : 
      74              42 :         switch (*str) {
      75                 :                 case '-':
      76              14 :                         sign = 1;
      77                 :                 case '+':
      78              14 :                         str++;
      79                 :                 default:
      80                 :                         break;
      81                 :         }
      82                 : 
      83                 :         /* must start with 1..9*/
      84              42 :         if (str < end && *str >= '1' && *str <= '9') {
      85              28 :                 ctx_value = ((*(str++)) - '0');
      86                 :         } else {
      87              14 :                 return -1;
      88                 :         }
      89                 : 
      90              56 :         if ((end - str > MAX_LENGTH_OF_LONG - 1) /* number too long */
      91                 :          || (SIZEOF_LONG == 4 && end - str == MAX_LENGTH_OF_LONG - 1 && *str > '2')) {
      92                 :                 /* overflow */
      93               0 :                 return -1;
      94                 :         }
      95                 : 
      96             121 :         while (str < end) {
      97             134 :                 if (*str >= '0' && *str <= '9') {
      98              65 :                         ctx_value = (ctx_value * 10) + (*(str++) - '0');
      99                 :                 } else {
     100               4 :                         return -1;
     101                 :                 }
     102                 :         }
     103              24 :         if (sign) {
     104               7 :                 ctx_value = -ctx_value;
     105               7 :                 if (ctx_value > 0) { /* overflow */
     106               0 :                         return -1;
     107                 :                 }
     108              17 :         } else if (ctx_value < 0) { /* overflow */
     109               1 :                 return -1;
     110                 :         }
     111                 : 
     112              23 :         *ret = ctx_value;
     113              23 :         return 1;
     114                 : }
     115                 : /* }}} */
     116                 : 
     117               0 : static int php_filter_parse_octal(const char *str, unsigned int str_len, long *ret TSRMLS_DC) { /* {{{ */
     118               0 :         unsigned long ctx_value = 0;
     119               0 :         const char *end = str + str_len;
     120                 : 
     121               0 :         while (str < end) {
     122               0 :                 if (*str >= '0' && *str <= '7') {
     123               0 :                         unsigned long n = ((*(str++)) - '0');
     124                 : 
     125               0 :                         if ((ctx_value > ((unsigned long)(~(long)0)) / 8) ||
     126                 :                                 ((ctx_value = ctx_value * 8) > ((unsigned long)(~(long)0)) - n)) {
     127               0 :                                 return -1;
     128                 :                         }
     129               0 :                         ctx_value += n;
     130                 :                 } else {
     131               0 :                         return -1;
     132                 :                 }
     133                 :         }
     134                 :         
     135               0 :         *ret = (long)ctx_value;
     136               0 :         return 1;
     137                 : }
     138                 : /* }}} */
     139                 : 
     140               1 : static int php_filter_parse_hex(const char *str, unsigned int str_len, long *ret TSRMLS_DC) { /* {{{ */
     141               1 :         unsigned long ctx_value = 0;
     142               1 :         const char *end = str + str_len;
     143                 :         unsigned long n;
     144                 : 
     145               4 :         while (str < end) {
     146               2 :                 if (*str >= '0' && *str <= '9') {
     147               0 :                         n = ((*(str++)) - '0');
     148               4 :                 } else if (*str >= 'a' && *str <= 'f') {
     149               2 :                         n = ((*(str++)) - ('a' - 10));
     150               0 :                 } else if (*str >= 'A' && *str <= 'F') {
     151               0 :                         n = ((*(str++)) - ('A' - 10));
     152                 :                 } else {
     153               0 :                         return -1;
     154                 :                 }
     155               2 :                 if ((ctx_value > ((unsigned long)(~(long)0)) / 16) ||
     156                 :                         ((ctx_value = ctx_value * 16) > ((unsigned long)(~(long)0)) - n)) {
     157               0 :                         return -1;
     158                 :                 }
     159               2 :                 ctx_value += n;
     160                 :         }
     161                 : 
     162               1 :         *ret = (long)ctx_value;
     163               1 :         return 1;
     164                 : }
     165                 : /* }}} */
     166                 : 
     167                 : void php_filter_int(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
     168              71 : {
     169                 :         zval **option_val;
     170                 :         long   min_range, max_range, option_flags;
     171                 :         int    min_range_set, max_range_set;
     172              71 :         int    allow_octal = 0, allow_hex = 0;
     173              71 :         int        len, error = 0;
     174                 :         long   ctx_value;
     175                 :         char *p;
     176                 : 
     177                 :         /* Parse options */
     178              71 :         FETCH_LONG_OPTION(min_range,    "min_range");
     179              71 :         FETCH_LONG_OPTION(max_range,    "max_range");
     180              71 :         option_flags = flags;
     181                 : 
     182              71 :         len = Z_STRLEN_P(value);
     183                 : 
     184              71 :         if (len == 0) {
     185               5 :                 RETURN_VALIDATION_FAILED
     186                 :         }
     187                 : 
     188              66 :         if (option_flags & FILTER_FLAG_ALLOW_OCTAL) {
     189               0 :                 allow_octal = 1;
     190                 :         }
     191                 : 
     192              66 :         if (option_flags & FILTER_FLAG_ALLOW_HEX) {
     193               1 :                 allow_hex = 1;
     194                 :         }
     195                 : 
     196                 :         /* Start the validating loop */
     197              66 :         p = Z_STRVAL_P(value);
     198              66 :         ctx_value = 0;
     199                 : 
     200              66 :         PHP_FILTER_TRIM_DEFAULT(p, len);
     201                 : 
     202              66 :         if (*p == '0') {
     203              24 :                 p++; len--;
     204              25 :                 if (allow_hex && (*p == 'x' || *p == 'X')) {
     205               1 :                         p++; len--;
     206               1 :                         if (php_filter_parse_hex(p, len, &ctx_value TSRMLS_CC) < 0) {
     207               0 :                                 error = 1;
     208                 :                         }
     209              23 :                 } else if (allow_octal) {
     210               0 :                         if (php_filter_parse_octal(p, len, &ctx_value TSRMLS_CC) < 0) {
     211               0 :                                 error = 1;
     212                 :                         }
     213              23 :                 } else if (len != 0) {
     214              21 :                         error = 1;
     215                 :                 }
     216                 :         } else {
     217              42 :                 if (php_filter_parse_int(p, len, &ctx_value TSRMLS_CC) < 0) {
     218              19 :                         error = 1;
     219                 :                 }
     220                 :         }
     221                 : 
     222              66 :         if (error > 0 || (min_range_set && (ctx_value < min_range)) || (max_range_set && (ctx_value > max_range))) {
     223              40 :                 RETURN_VALIDATION_FAILED
     224                 :         } else {
     225              26 :                 zval_dtor(value);
     226              26 :                 Z_TYPE_P(value) = IS_LONG;
     227              26 :                 Z_LVAL_P(value) = ctx_value;
     228              26 :                 return;
     229                 :         }
     230                 : }
     231                 : /* }}} */
     232                 : 
     233                 : void php_filter_boolean(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
     234              54 : {
     235              54 :         char *str = Z_STRVAL_P(value);
     236              54 :         int len = Z_STRLEN_P(value);
     237                 :         int ret;
     238                 : 
     239              54 :         PHP_FILTER_TRIM_DEFAULT(str, len);
     240                 : 
     241                 :         /* returns true for "1", "true", "on" and "yes"
     242                 :          * returns false for "0", "false", "off", "no", and ""
     243                 :          * null otherwise. */
     244              48 :         switch (len) {
     245                 :                 case 1:
     246              14 :                         if (*str == '1') {
     247               7 :                                 ret = 1;
     248               7 :                         } else if (*str == '0') {
     249               5 :                                 ret = 0;
     250                 :                         } else {
     251               2 :                                 ret = -1;
     252                 :                         }
     253              14 :                         break;
     254                 :                 case 2:
     255               8 :                         if (strncasecmp(str, "on", 2) == 0) {
     256               4 :                                 ret = 1;
     257               4 :                         } else if (strncasecmp(str, "no", 2) == 0) {
     258               2 :                                 ret = 0;
     259                 :                         } else {
     260               2 :                                 ret = -1;
     261                 :                         }
     262               8 :                         break;
     263                 :                 case 3:
     264               9 :                         if (strncasecmp(str, "yes", 3) == 0) {
     265               2 :                                 ret = 1;
     266               7 :                         } else if (strncasecmp(str, "off", 3) == 0) {
     267               4 :                                 ret = 0;
     268                 :                         } else {
     269               3 :                                 ret = -1;
     270                 :                         }
     271               9 :                         break;
     272                 :                 case 4:
     273               6 :                         if (strncasecmp(str, "true", 4) == 0) {
     274               4 :                                 ret = 1;
     275                 :                         } else {
     276               2 :                                 ret = -1;
     277                 :                         }
     278               6 :                         break;
     279                 :                 case 5:
     280               4 :                         if (strncasecmp(str, "false", 5) == 0) {
     281               4 :                                 ret = 0;
     282                 :                         } else {
     283               0 :                                 ret = -1;
     284                 :                         }
     285               4 :                         break;
     286                 :                 default:
     287               7 :                         ret = -1;
     288                 :         }
     289                 : 
     290              48 :         if (ret == -1) {        
     291              16 :                 RETURN_VALIDATION_FAILED
     292                 :         } else {
     293              32 :                 zval_dtor(value);
     294              32 :                 ZVAL_BOOL(value, ret);
     295                 :         }
     296                 : }
     297                 : /* }}} */
     298                 : 
     299                 : void php_filter_float(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
     300              66 : {
     301                 :         int len;
     302                 :         char *str, *end;
     303                 :         char *num, *p;
     304                 : 
     305                 :         zval **option_val;
     306                 :         char *decimal;
     307                 :         int decimal_set, decimal_len;
     308              66 :         char dec_sep = '.';
     309              66 :         char tsd_sep[3] = "',.";
     310                 : 
     311                 :         long lval;
     312                 :         double dval;
     313                 : 
     314                 :         int first, n;
     315                 : 
     316              66 :         len = Z_STRLEN_P(value);
     317              66 :         str = Z_STRVAL_P(value);
     318                 : 
     319              66 :         PHP_FILTER_TRIM_DEFAULT(str, len);
     320              62 :         end = str + len;
     321                 : 
     322              62 :         FETCH_STRING_OPTION(decimal, "decimal");
     323                 : 
     324              62 :         if (decimal_set) {
     325               0 :                 if (decimal_len != 1) {
     326               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "decimal separator must be one char");
     327               0 :                         RETURN_VALIDATION_FAILED
     328                 :                 } else {
     329               0 :                         dec_sep = *decimal;
     330                 :                 }
     331                 :         }
     332                 : 
     333              62 :         num = p = emalloc(len+1);
     334              62 :         if (str < end && (*str == '+' || *str == '-')) {
     335               9 :                 *p++ = *str++;
     336                 :         }
     337              62 :         first = 1;
     338                 :         while (1) {
     339              62 :                 n = 0;
     340             226 :                 while (str < end && *str >= '0' && *str <= '9') {
     341             102 :                         ++n;
     342             102 :                         *p++ = *str++;
     343                 :                 }
     344              62 :                 if (str == end || *str == dec_sep || *str == 'e' || *str == 'E') {
     345              46 :                         if (!first && n != 3) {
     346               0 :                                 goto error;
     347                 :                         }
     348              46 :                         if (*str == dec_sep) {
     349              24 :                                 *p++ = '.';
     350              24 :                                 str++;
     351             107 :                                 while (str < end && *str >= '0' && *str <= '9') {
     352              59 :                                         *p++ = *str++;
     353                 :                                 }
     354                 :                         }
     355              46 :                         if (*str == 'e' || *str == 'E') {
     356              15 :                                 *p++ = *str++;
     357              15 :                                 if (str < end && (*str == '+' || *str == '-')) {
     358               7 :                                         *p++ = *str++;
     359                 :                                 }
     360              51 :                                 while (str < end && *str >= '0' && *str <= '9') {
     361              21 :                                         *p++ = *str++;
     362                 :                                 }
     363                 :                         }
     364                 :                         break;
     365                 :                 }
     366              16 :                 if ((flags & FILTER_FLAG_ALLOW_THOUSAND) && (*str == tsd_sep[0] || *str == tsd_sep[1] || *str == tsd_sep[2])) {
     367               0 :                         if (first?(n < 1 || n > 3):(n != 3)) {
     368               0 :                                 goto error;
     369                 :                         }
     370               0 :                         first = 0;
     371               0 :                         str++;
     372                 :                 } else {
     373                 :                         goto error;
     374                 :                 }
     375               0 :         }
     376              46 :         if (str != end) {
     377               2 :                 goto error;
     378                 :         }
     379              44 :         *p = 0;
     380                 : 
     381              44 :         switch (is_numeric_string(num, p - num, &lval, &dval, 0)) {
     382                 :                 case IS_LONG:
     383               7 :                         zval_dtor(value);
     384               7 :                         Z_TYPE_P(value) = IS_DOUBLE;
     385               7 :                         Z_DVAL_P(value) = lval;
     386               7 :                         break;
     387                 :                 case IS_DOUBLE:
     388              30 :                         if ((!dval && p - num > 1 && strpbrk(num, "123456789")) || !zend_finite(dval)) {
     389                 :                                 goto error;
     390                 :                         }
     391              30 :                         zval_dtor(value);
     392              30 :                         Z_TYPE_P(value) = IS_DOUBLE;
     393              30 :                         Z_DVAL_P(value) = dval;
     394              30 :                         break;
     395                 :                 default:
     396              25 : error:
     397              25 :                         efree(num);
     398              25 :                         RETURN_VALIDATION_FAILED
     399                 :         }
     400              37 :         efree(num);     
     401                 : }
     402                 : /* }}} */
     403                 : 
     404                 : void php_filter_validate_regexp(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
     405              15 : {
     406                 :         zval **option_val;
     407                 :         char  *regexp;
     408                 :         int regexp_len;
     409                 :         long   option_flags;
     410                 :         int    regexp_set, option_flags_set;
     411                 : 
     412              15 :         pcre       *re = NULL;
     413              15 :         pcre_extra *pcre_extra = NULL;
     414              15 :         int preg_options = 0;
     415                 : 
     416                 :         int         ovector[3];
     417                 :         int         matches;
     418                 : 
     419                 :         /* Parse options */
     420              15 :         FETCH_STRING_OPTION(regexp, "regexp");
     421              15 :         FETCH_LONG_OPTION(option_flags, "flags");
     422                 : 
     423              15 :         if (!regexp_set) {
     424              15 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "'regexp' option missing");
     425              15 :                 RETURN_VALIDATION_FAILED
     426                 :         }
     427                 : 
     428               0 :         re = pcre_get_compiled_regex(regexp, &pcre_extra, &preg_options TSRMLS_CC);
     429               0 :         if (!re) {
     430               0 :                 RETURN_VALIDATION_FAILED
     431                 :         }
     432               0 :         matches = pcre_exec(re, NULL, Z_STRVAL_P(value), Z_STRLEN_P(value), 0, 0, ovector, 3);
     433                 : 
     434                 :         /* 0 means that the vector is too small to hold all the captured substring offsets */
     435               0 :         if (matches < 0) {
     436               0 :                 RETURN_VALIDATION_FAILED
     437                 :         }
     438                 : }
     439                 : /* }}} */
     440                 : 
     441                 : void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
     442              39 : {
     443                 :         php_url *url;
     444              39 :         int old_len = Z_STRLEN_P(value);
     445                 :         
     446              39 :         php_filter_url(value, flags, option_array, charset TSRMLS_CC);
     447                 : 
     448              39 :         if (Z_TYPE_P(value) != IS_STRING || old_len != Z_STRLEN_P(value)) {
     449               1 :                 RETURN_VALIDATION_FAILED
     450                 :         }
     451                 : 
     452                 :         /* Use parse_url - if it returns false, we return NULL */
     453              38 :         url = php_url_parse_ex(Z_STRVAL_P(value), Z_STRLEN_P(value));
     454                 : 
     455              38 :         if (url == NULL) {
     456               2 :                 RETURN_VALIDATION_FAILED
     457                 :         }
     458                 : 
     459              36 :         if (
     460                 :                 url->scheme == NULL || 
     461                 :                 /* some schemas allow the host to be empty */
     462                 :                 (url->host == NULL && (strcmp(url->scheme, "mailto") && strcmp(url->scheme, "news") && strcmp(url->scheme, "file"))) ||
     463                 :                 ((flags & FILTER_FLAG_PATH_REQUIRED) && url->path == NULL) || ((flags & FILTER_FLAG_QUERY_REQUIRED) && url->query == NULL)
     464                 :         ) {
     465              21 :                 php_url_free(url);
     466              21 :                 RETURN_VALIDATION_FAILED
     467                 :         }
     468              15 :         php_url_free(url);
     469                 : }
     470                 : /* }}} */
     471                 : 
     472                 : void php_filter_validate_email(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
     473              31 : {
     474                 :         /* From http://cvs.php.net/co.php/pear/HTML_QuickForm/QuickForm/Rule/Email.php?r=1.4 */
     475              31 :         const char regexp[] = "/^((\\\"[^\\\"\\f\\n\\r\\t\\b]+\\\")|([A-Za-z0-9_][A-Za-z0-9_\\!\\#\\$\\%\\&\\'\\*\\+\\-\\~\\/\\=\\?\\^\\`\\|\\{\\}]*(\\.[A-Za-z0-9_\\!\\#\\$\\%\\&\\'\\*\\+\\-\\~\\/\\=\\?\\^\\`\\|\\{\\}]*)*))@((\\[(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))\\])|(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))|((([A-Za-z0-9])(([A-Za-z0-9\\-])*([A-Za-z0-9]))?(\\.(?=[A-Za-z0-9\\-]))?)+[A-Za-z]+))$/D";
     476                 : 
     477              31 :         pcre       *re = NULL;
     478              31 :         pcre_extra *pcre_extra = NULL;
     479              31 :         int preg_options = 0;
     480                 :         int         ovector[150]; /* Needs to be a multiple of 3 */
     481                 :         int         matches;
     482                 : 
     483                 : 
     484              31 :         re = pcre_get_compiled_regex((char *)regexp, &pcre_extra, &preg_options TSRMLS_CC);
     485              31 :         if (!re) {
     486               0 :                 RETURN_VALIDATION_FAILED
     487                 :         }
     488              31 :         matches = pcre_exec(re, NULL, Z_STRVAL_P(value), Z_STRLEN_P(value), 0, 0, ovector, 3);
     489                 : 
     490                 :         /* 0 means that the vector is too small to hold all the captured substring offsets */
     491              31 :         if (matches < 0) {
     492              20 :                 RETURN_VALIDATION_FAILED
     493                 :         }
     494                 : 
     495                 : }
     496                 : /* }}} */
     497                 : 
     498                 : static int _php_filter_validate_ipv4(char *str, int str_len, int *ip) /* {{{ */
     499              39 : {
     500              39 :         const char *end = str + str_len;
     501                 :         int num, m;
     502              39 :         int n = 0;
     503                 : 
     504             173 :         while (str < end) {
     505             134 :                 if (*str < '0' || *str > '9') {
     506               6 :                         return 0;
     507                 :                 }
     508             128 :                 m = 1;
     509             128 :                 num = ((*(str++)) - '0');
     510             381 :                 while (str < end && (*str >= '0' && *str <= '9')) {
     511             126 :                         num = num * 10 + ((*(str++)) - '0');
     512             126 :                         if (num > 255 || ++m > 3) {
     513               1 :                                 return 0;
     514                 :                         }
     515                 :                 }
     516             127 :                 ip[n++] = num;
     517             127 :                 if (n == 4) {
     518              31 :                         return str == end;
     519              96 :                 } else if (str >= end || *(str++) != '.') {
     520               1 :                         return 0;
     521                 :                 }
     522                 :         }
     523               0 :         return 0;               
     524                 : }
     525                 : /* }}} */
     526                 : 
     527                 : static int _php_filter_validate_ipv6(char *str, int str_len TSRMLS_DC) /* {{{ */
     528              34 : {
     529              34 :         int compressed = 0;
     530              34 :         int blocks = 8;
     531                 :         int n;
     532                 :         char *ipv4;
     533                 :         char *end;
     534                 :         int ip4elm[4];
     535              34 :         char *s = str;
     536                 : 
     537              34 :         if (!memchr(str, ':', str_len)) {
     538               0 :                 return 0;
     539                 :         }
     540                 : 
     541                 :         /* check for bundled IPv4 */
     542              34 :         ipv4 = memchr(str, '.', str_len);
     543              34 :         if (ipv4) {
     544              84 :                 while (ipv4 > str && *(ipv4-1) != ':') {
     545              48 :                         ipv4--;
     546                 :                 }
     547                 : 
     548              18 :                 if (!_php_filter_validate_ipv4(ipv4, (str_len - (ipv4 - str)), ip4elm)) {
     549               2 :                         return 0;
     550                 :                 }
     551              16 :                 str_len = (ipv4 - str) - 1;
     552              16 :                 if (str_len == 1) {
     553               2 :                         return *str == ':';
     554                 :                 }
     555              14 :                 blocks = 6;
     556                 :         }
     557                 : 
     558              30 :         end = str + str_len;
     559                 : 
     560             174 :         while (str < end) {
     561             127 :                 if (*str == ':') {
     562             106 :                         if (--blocks == 0) {
     563               6 :                                 return 0;
     564                 :                         }                       
     565             100 :                         if (++str >= end) {
     566               2 :                                 return 0;
     567                 :                         }
     568              98 :                         if (*str == ':') {
     569              22 :                                 if (compressed || --blocks == 0) {
     570               2 :                                         return 0;
     571                 :                                 }                       
     572              20 :                                 if (++str == end) {
     573               0 :                                         return 1;
     574                 :                                 }
     575              20 :                                 compressed = 1;
     576              76 :                         } else if ((str - 1) == s) {
     577               0 :                                 return 0;
     578                 :                         }                               
     579                 :                 }
     580             117 :                 n = 0;
     581             476 :                 while ((str < end) &&
     582                 :                        ((*str >= '0' && *str <= '9') ||
     583                 :                         (*str >= 'a' && *str <= 'f') ||
     584                 :                         (*str >= 'A' && *str <= 'F'))) {
     585             242 :                         n++;
     586             242 :                         str++;
     587                 :                 }
     588             117 :                 if (n < 1 || n > 4) {
     589               3 :                         return 0;
     590                 :                 }
     591                 :         }
     592              17 :         return (compressed || blocks == 1);
     593                 : }
     594                 : /* }}} */
     595                 : 
     596                 : void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
     597              65 : {
     598                 :         /* validates an ipv4 or ipv6 IP, based on the flag (4, 6, or both) add a
     599                 :          * flag to throw out reserved ranges; multicast ranges... etc. If both
     600                 :          * allow_ipv4 and allow_ipv6 flags flag are used, then the first dot or
     601                 :          * colon determine the format */
     602                 : 
     603                 :         int            ip[4];
     604                 :         int            mode;
     605                 : 
     606              65 :         if (memchr(Z_STRVAL_P(value), ':', Z_STRLEN_P(value))) {
     607              35 :                 mode = FORMAT_IPV6;
     608              30 :         } else if (memchr(Z_STRVAL_P(value), '.', Z_STRLEN_P(value))) {
     609              22 :                 mode = FORMAT_IPV4;
     610                 :         } else {
     611               8 :                 RETURN_VALIDATION_FAILED
     612                 :         }
     613                 : 
     614              57 :         if (flags & (FILTER_FLAG_IPV4 || FILTER_FLAG_IPV6)) {
     615                 :                 /* Both formats are cool */
     616              57 :         } else if ((flags & FILTER_FLAG_IPV4) && mode == FORMAT_IPV6) {
     617               1 :                 RETURN_VALIDATION_FAILED
     618              56 :         } else if ((flags & FILTER_FLAG_IPV6) && mode == FORMAT_IPV4) {
     619               1 :                 RETURN_VALIDATION_FAILED
     620                 :         }
     621                 : 
     622              55 :         switch (mode) {
     623                 :                 case FORMAT_IPV4:
     624              21 :                         if (!_php_filter_validate_ipv4(Z_STRVAL_P(value), Z_STRLEN_P(value), ip)) {
     625               9 :                                 RETURN_VALIDATION_FAILED
     626                 :                         }
     627                 : 
     628                 :                         /* Check flags */
     629              12 :                         if (flags & FILTER_FLAG_NO_PRIV_RANGE) {
     630               2 :                                 if (
     631                 :                                         (ip[0] == 10) ||
     632                 :                                         (ip[0] == 172 && (ip[1] >= 16 && ip[1] <= 31)) ||
     633                 :                                         (ip[0] == 192 && ip[1] == 168)
     634                 :                                 ) {
     635               1 :                                         RETURN_VALIDATION_FAILED
     636                 :                                 }
     637                 :                         }
     638                 : 
     639              11 :                         if (flags & FILTER_FLAG_NO_RES_RANGE) {
     640               3 :                                 if (
     641                 :                                         (ip[0] == 0) ||
     642                 :                                         (ip[0] == 169 && ip[1] == 254) ||
     643                 :                                         (ip[0] == 192 && ip[1] == 0 && ip[2] == 2) ||
     644                 :                                         (ip[0] >= 224 && ip[0] <= 255)
     645                 :                                 ) {
     646               1 :                                         RETURN_VALIDATION_FAILED
     647                 :                                 }
     648                 :                         }
     649              10 :                         break;
     650                 : 
     651                 :                 case FORMAT_IPV6:
     652                 :                         {
     653              34 :                                 int res = 0;
     654              34 :                                 res = _php_filter_validate_ipv6(Z_STRVAL_P(value), Z_STRLEN_P(value) TSRMLS_CC);
     655              34 :                                 if (res < 1) {
     656              16 :                                         RETURN_VALIDATION_FAILED
     657                 :                                 }
     658                 :                                 /* Check flags */
     659              18 :                                 if (flags & FILTER_FLAG_NO_PRIV_RANGE) {
     660               0 :                                         if (Z_STRLEN_P(value) >=2 && (!strncasecmp("FC", Z_STRVAL_P(value), 2) || !strncasecmp("FD", Z_STRVAL_P(value), 2))) {
     661               0 :                                                 RETURN_VALIDATION_FAILED
     662                 :                                         }
     663                 :                                 }
     664                 :                         }
     665                 :                         break;
     666                 :         }
     667                 : }
     668                 : /* }}} */
     669                 : 
     670                 : /*
     671                 :  * Local variables:
     672                 :  * tab-width: 4
     673                 :  * c-basic-offset: 4
     674                 :  * End:
     675                 :  * vim600: noet sw=4 ts=4 fdm=marker
     676                 :  * vim<600: noet sw=4 ts=4
     677                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:30 +0000 (33 hours ago)

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