Author: seanius Date: 2007-04-23 17:41:51 +0000 (Mon, 23 Apr 2007) New Revision: 5715 Added: data/patches/MOPB/MOPB-19-php5.diff Log: 19, maybe Added: data/patches/MOPB/MOPB-19-php5.diff ==================================================================--- data/patches/MOPB/MOPB-19-php5.diff 2007-04-23 17:15:18 UTC (rev 5714) +++ data/patches/MOPB/MOPB-19-php5.diff 2007-04-23 17:41:51 UTC (rev 5715) @@ -0,0 +1,807 @@ +--- logical_filters.c 2006/12/20 19:48:12 1.1.2.17 ++++ logical_filters.c 2006/12/26 09:16:24 1.1.2.18 +@@ -24,10 +24,14 @@ + #include "ext/standard/url.h" + #include "ext/pcre/php_pcre.h" + ++#include "zend_multiply.h" ++ + #if HAVE_ARPA_INET_H + # include <arpa/inet.h> + #endif + ++#define LONG_SIGN_MASK (1L << (8*sizeof(long)-1)) ++ + #ifndef INADDR_NONE + # define INADDR_NONE ((unsigned long int) -1) + #endif +@@ -39,8 +43,7 @@ + var_name##_set = 0; \ + if (option_array) { \ + if (zend_hash_find(HASH_OF(option_array), option_name, sizeof(option_name), (void **) &option_val) == SUCCESS) { \ +- convert_to_long(*option_val); \ +- var_name = Z_LVAL_PP(option_val); \ ++ PHP_FILTER_GET_LONG_OPT(option_val, var_name); \ + var_name##_set = 1; \ + } \ + } +@@ -53,10 +56,11 @@ + var_name##_len = 0; \ + if (option_array) { \ + if (zend_hash_find(HASH_OF(option_array), option_name, sizeof(option_name), (void **) &option_val) == SUCCESS) { \ +- convert_to_string(*option_val); \ +- var_name = Z_STRVAL_PP(option_val); \ +- var_name##_set = 1; \ +- var_name##_len = Z_STRLEN_PP(option_val); \ ++ if (Z_TYPE_PP(option_val) == IS_STRING) { \ ++ var_name = Z_STRVAL_PP(option_val); \ ++ var_name##_len = Z_STRLEN_PP(option_val); \ ++ var_name##_set = 1; \ ++ } \ + } \ + } + /* }}} */ +@@ -65,14 +69,13 @@ + #define FORMAT_IPV6 6 + + static int php_filter_parse_int(const char *str, unsigned int str_len, long *ret TSRMLS_DC) { /* {{{ */ +- long ctx_value = 0; ++ long ctx_value; + long sign = 1; +- int error = 0; +- const char *end; ++ const char *end = str + str_len; ++ double dval; ++ long overflow; + +- end = str + str_len; +- +- switch(*str) { ++ switch (*str) { + case ''-'': + sign = -1; + case ''+'': +@@ -82,88 +85,79 @@ + } + + /* must start with 1..9*/ +- if (*str >= ''1'' && *str <= ''9'') { +- ctx_value += ((*str) - ''0''); +- str++; ++ if (str < end && *str >= ''1'' && *str <= ''9'') { ++ ctx_value = ((*(str++)) - ''0''); + } else { + return -1; + } + +- if (str_len == 1 ) { +- *ret = ctx_value; +- return 1; +- } +- +- while (*str) { ++ while (str < end) { + if (*str >= ''0'' && *str <= ''9'') { +- ctx_value *= 10; +- ctx_value += ((*str) - ''0''); +- str++; ++ ZEND_SIGNED_MULTIPLY_LONG(ctx_value, 10, ctx_value, dval, overflow); ++ if (overflow) { ++ return -1; ++ } ++ ctx_value += ((*(str++)) - ''0''); ++ if (ctx_value & LONG_SIGN_MASK) { ++ return -1; ++ } + } else { +- error = 1; +- break; ++ return -1; + } + } + +- /* state "tail" */ +- if (!error && *str == ''\0'' && str == end) { +- *ret = ctx_value * sign; +- return 1; +- } else { +- return -1; +- } ++ *ret = ctx_value * sign; ++ return 1; + } + /* }}} */ + + static int php_filter_parse_octal(const char *str, unsigned int str_len, long *ret TSRMLS_DC) { /* {{{ */ +- long ctx_value = 0; +- int error = 0; ++ unsigned long ctx_value = 0; ++ const char *end = str + str_len; + +- while (*str) { ++ while (str < end) { + if (*str >= ''0'' && *str <= ''7'') { +- ctx_value *= 8; +- ctx_value += ((*str) - ''0''); +- str++; ++ unsigned long n = ((*(str++)) - ''0''); ++ ++ if ((ctx_value > ((unsigned long)(~(long)0)) / 8) || ++ ((ctx_value = ctx_value * 8) > ((unsigned long)(~(long)0)) - n)) { ++ return -1; ++ } ++ ctx_value += n; + } else { +- error = 1; +- break; ++ return -1; + } + } +- if (!error && *str == ''\0'') { +- *ret = ctx_value; +- return 1; +- } else { +- return -1; +- } ++ ++ *ret = (long)ctx_value; ++ return 1; + } + /* }}} */ + + static int php_filter_parse_hex(const char *str, unsigned int str_len, long *ret TSRMLS_DC) { /* {{{ */ +- long ctx_value = 0; +- int error = 0; ++ unsigned long ctx_value = 0; ++ const char *end = str + str_len; ++ unsigned long n; + +- while (*str) { +- if ((*str >= ''0'' && *str <= ''9'') || (*str >= ''a'' && *str <= ''f'') || (*str >= ''A'' && *str <= ''F'')) { +- ctx_value *= 16; +- if (*str >= ''0'' && *str <= ''9'') { +- ctx_value += ((*str) - ''0''); +- } else if (*str >= ''a'' && *str <= ''f'') { +- ctx_value += 10 + ((*str) - ''a''); +- } else if (*str >= ''A'' && *str <= ''F'') { +- ctx_value += 10 + ((*str) - ''A''); +- } +- str++; ++ while (str < end) { ++ if (*str >= ''0'' && *str <= ''9'') { ++ n = ((*(str++)) - ''0''); ++ } else if (*str >= ''a'' && *str <= ''f'') { ++ n = ((*(str++)) - (''a'' - 10)); ++ } else if (*str >= ''A'' && *str <= ''F'') { ++ n = ((*(str++)) - (''A'' - 10)); + } else { +- error = 1; +- break; ++ return -1; + } ++ if ((ctx_value > ((unsigned long)(~(long)0)) / 16) || ++ ((ctx_value = ctx_value * 16) > ((unsigned long)(~(long)0)) - n)) { ++ return -1; ++ } ++ ctx_value += n; + } +- if (!error && *str == ''\0'') { +- *ret = ctx_value; +- return 1; +- } else { +- return -1; +- } ++ ++ *ret = (long)ctx_value; ++ return 1; + } + /* }}} */ + +@@ -175,7 +169,7 @@ + int allow_octal = 0, allow_hex = 0; + int len, error = 0; + long ctx_value; +- char *p, *start, *end; ++ char *p; + + /* Parse options */ + FETCH_LONG_OPTION(min_range, "min_range"); +@@ -200,12 +194,12 @@ + p = Z_STRVAL_P(value); + ctx_value = 0; + +- PHP_FILTER_TRIM_DEFAULT(p, len, end); ++ PHP_FILTER_TRIM_DEFAULT(p, len); + + if (*p == ''0'') { +- p++; ++ p++; len--; + if (allow_hex && (*p == ''x'' || *p == ''X'')) { +- p++; ++ p++; len--; + if (php_filter_parse_hex(p, len, &ctx_value TSRMLS_CC) < 0) { + error = 1; + } +@@ -213,7 +207,7 @@ + if (php_filter_parse_octal(p, len, &ctx_value TSRMLS_CC) < 0) { + error = 1; + } +- } else if (len != 1) { ++ } else if (len != 0) { + error = 1; + } + } else { +@@ -236,34 +230,65 @@ + void php_filter_boolean(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ + { + char *str = Z_STRVAL_P(value); +- char *start, *end; + int len = Z_STRLEN_P(value); ++ int ret; + +- if (len>0) { +- PHP_FILTER_TRIM_DEFAULT(str, len, end); +- } else { +- RETURN_VALIDATION_FAILED +- } ++ PHP_FILTER_TRIM_DEFAULT(str, len); + + /* returns true for "1", "true", "on" and "yes" + * returns false for "0", "false", "off", "no", and "" + * null otherwise. */ +- if ((strncasecmp(str, "true", sizeof("true")) == 0) || +- (strncasecmp(str, "yes", sizeof("yes")) == 0) || +- (strncasecmp(str, "on", sizeof("on")) == 0) || +- (strncmp(str, "1", sizeof("1")) == 0)) +- { +- zval_dtor(value); +- ZVAL_BOOL(value, 1); +- } else if ((strncasecmp(str, "false", sizeof("false")) == 0) || +- (strncasecmp(str, "no", sizeof("no")) == 0) || +- (strncasecmp(str, "off", sizeof("off")) == 0) || +- (strncmp(str, "0", sizeof("0")) == 0)) +- { +- zval_dtor(value); +- ZVAL_BOOL(value, 0); +- } else { ++ switch (len) { ++ case 1: ++ if (*str == ''1'') { ++ ret = 1; ++ } else if (*str == ''0'') { ++ ret = 0; ++ } else { ++ ret = -1; ++ } ++ break; ++ case 2: ++ if (strncasecmp(str, "on", 2) == 0) { ++ ret = 1; ++ } else if (strncasecmp(str, "no", 2) == 0) { ++ ret = 0; ++ } else { ++ ret = -1; ++ } ++ break; ++ case 3: ++ if (strncasecmp(str, "yes", 3) == 0) { ++ ret = 1; ++ } else if (strncasecmp(str, "off", 3) == 0) { ++ ret = 0; ++ } else { ++ ret = -1; ++ } ++ break; ++ case 4: ++ if (strncasecmp(str, "true", 4) == 0) { ++ ret = 1; ++ } else { ++ ret = -1; ++ } ++ break; ++ case 5: ++ if (strncasecmp(str, "false", 5) == 0) { ++ ret = 0; ++ } else { ++ ret = -1; ++ } ++ break; ++ default: ++ ret = -1; ++ } ++ ++ if (ret == -1) { + RETURN_VALIDATION_FAILED ++ } else { ++ zval_dtor(value); ++ ZVAL_BOOL(value, ret); + } + } + /* }}} */ +@@ -271,169 +296,102 @@ + void php_filter_float(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */ + { + int len; +- char *str, *start, *end; ++ char *str, *end; ++ char *num, *p; + + zval **option_val; + char *decimal; +- char dec_sep = ''\0''; +- +- const char default_decimal[] = "."; + int decimal_set, decimal_len; +- ++ char dec_sep = ''.''; + char tsd_sep[3] = "'',."; + +- long options_flag; +- int options_flag_set; ++ long lval; ++ double dval; + +- int sign = 1; +- +- double ret_val = 0; +- double factor; +- +- int exp_value = 0, exp_multiply = 1; ++ int first, n; + + len = Z_STRLEN_P(value); +- +- if (len < 1) { +- RETURN_VALIDATION_FAILED +- } +- + str = Z_STRVAL_P(value); + +- PHP_FILTER_TRIM_DEFAULT(str, len, end); +- +- start = str; +- +- if (len == 1) { +- if (*str >= ''0'' && *str <= ''9'') { +- ret_val = (double)*str - ''0''; +- } else if (*str == ''E'' || *str == ''e'') { +- ret_val = 0; +- } +- zval_dtor(value); +- Z_TYPE_P(value) = IS_DOUBLE; +- Z_DVAL_P(value) = ret_val; +- return; +- } ++ PHP_FILTER_TRIM_DEFAULT(str, len); ++ end = str + len; + + FETCH_STRING_OPTION(decimal, "decimal"); +- FETCH_LONG_OPTION(options_flag, "flags"); + + if (decimal_set) { +- if (decimal_len > 1) { ++ if (decimal_len != 1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "decimal separator must be one char"); ++ RETURN_VALIDATION_FAILED + } else { + dec_sep = *decimal; + } +- } else { +- dec_sep = *default_decimal; +- } +- +- if (*str == ''-'') { +- sign = -1; +- str++; +- start = str; +- } else if (*str == ''+'') { +- sign = 1; +- str++; +- start = str; +- } +- +- ret_val = 0.0; +- +- while (*str == ''0'') { +- str++; +- } +- +- if (*str == dec_sep) { +- str++; +- goto stateDot; +- } +- +- ret_val = 0; +- +- if (str != start) { +- str--; +- } +- +- while (*str && *str != dec_sep) { +- if ((options_flag & FILTER_FLAG_ALLOW_THOUSAND) && (*str == tsd_sep[0] || *str == tsd_sep[1] || *str == tsd_sep[2])) { +- str++; +- continue; +- } +- +- if (*str == ''e'' || *str == ''E'') { +- goto stateExp; +- } +- +- if (*str < ''0'' || *str > ''9'') { +- goto stateError; +- } +- +- ret_val *=10; ret_val += (*str - ''0''); +- str++; +- } +- if (!(*str)) { +- goto stateT; + } +- str++; + +-stateDot: +- factor = 0.1; +- while (*str) { +- if (*str == ''e'' || *str == ''E'') { +- goto stateExp; ++ num = p = emalloc(len+1); ++ if (str < end && (*str == ''+'' || *str == ''-'')) { ++ *p++ = *str++; ++ } ++ first = 1; ++ while (1) { ++ n = 0; ++ while (str < end && *str >= ''0'' && *str <= ''9'') { ++ ++n; ++ *p++ = *str++; ++ } ++ if (str == end || *str == dec_sep || *str == ''e'' || *str == ''E'') { ++ if (!first && n != 3) { ++ goto error; ++ } ++ if (*str == dec_sep) { ++ *p++ = ''.''; ++ str++; ++ while (str < end && *str >= ''0'' && *str <= ''9'') { ++ *p++ = *str++; ++ } ++ } ++ if (*str == ''e'' || *str == ''E'') { ++ *p++ = *str++; ++ if (str < end && (*str == ''+'' || *str == ''-'')) { ++ *p++ = *str++; ++ } ++ while (str < end && *str >= ''0'' && *str <= ''9'') { ++ *p++ = *str++; ++ } ++ } ++ break; + } +- +- if (*str < ''0'' || *str > ''9'') { +- goto stateError; ++ if ((flags & FILTER_FLAG_ALLOW_THOUSAND) && (*str == tsd_sep[0] || *str == tsd_sep[1] || *str == tsd_sep[2])) { ++ if (first?(n < 1 || n > 3):(n != 3)) { ++ goto error; ++ } ++ first = 0; ++ str++; ++ } else { ++ goto error; + } +- +- ret_val += factor * (*str - ''0''); +- factor /= 10; +- str++; + } +- if (!(*str)) { +- goto stateT; ++ if (str != end) { ++ goto error; + } ++ *p = 0; + +-stateExp: +- str++; +- switch (*str) { +- case ''-'': +- exp_multiply = -1; +- str++; ++ switch (is_numeric_string(num, p - num, &lval, &dval, 0)) { ++ case IS_LONG: ++ zval_dtor(value); ++ Z_TYPE_P(value) = IS_DOUBLE; ++ Z_DVAL_P(value) = lval; + break; +- case ''+'': +- exp_multiply = 1; +- str++; +- } +- +- while (*str) { +- if (*str < ''0'' || *str > ''9'') { +- goto stateError; +- } +- exp_value *= 10; +- exp_value += ((*str) - ''0''); +- str++; +- } +- +-stateT: +- if ((str -1) != end) { +- goto stateError; +- } +- if (exp_value) { +- exp_value *= exp_multiply; +- ret_val *= pow(10, exp_value); ++ case IS_DOUBLE: ++ zval_dtor(value); ++ Z_TYPE_P(value) = IS_DOUBLE; ++ Z_DVAL_P(value) = dval; ++ break; ++ default: ++error: ++ efree(num); ++ RETURN_VALIDATION_FAILED + } +- +- zval_dtor(value); +- Z_TYPE_P(value) = IS_DOUBLE; +- Z_DVAL_P(value) = sign * ret_val; +- return; +- +-stateError: +- RETURN_VALIDATION_FAILED ++ efree(num); + } + /* }}} */ + +@@ -533,179 +491,95 @@ + + static int _php_filter_validate_ipv4(char *str, int str_len, int *ip) /* {{{ */ + { +- unsigned long int i = inet_addr(str); +- char ip_chk[16]; +- int l; +- +- if (i == INADDR_NONE) { +- if (!strcmp(str, "255.255.255.255")) { +- ip[0] = ip[1] = ip[2] = ip[3] = 255; +- return 1; +- } else { ++ const char *end = str + str_len; ++ int num, m; ++ int n = 0; ++ ++ while (str < end) { ++ if (*str < ''0'' || *str > ''9'') { ++ return 0; ++ } ++ m = 1; ++ num = ((*(str++)) - ''0''); ++ while (str < end && (*str >= ''0'' && *str <= ''9'')) { ++ num = num * 10 + ((*(str++)) - ''0''); ++ if (num > 255 || ++m > 3) { ++ return 0; ++ } ++ } ++ ip[n++] = num; ++ if (n == 4) { ++ return str == end; ++ } else if (str >= end || *(str++) != ''.'') { + return 0; + } + } +- ip[0] = i & 0xFF; +- ip[1] = (i & 0xFF00) / 256; +- ip[2] = (i & 0xFF0000) / 256 / 256; +- ip[3] = (i & 0xFF000000) / 256 / 256 / 256; +- +- /* make sure that the input does not have any trailing values */ +- l = sprintf(ip_chk, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); +- if (l != str_len || strcmp(ip_chk, str)) { +- return 0; +- } +- +- return 1; ++ return 0; + } + /* }}} */ + +-#define IS_HEX(s) if (!((s >= ''0'' && s <= ''9'') || (s >= ''a'' && s <= ''f'') ||(s >= ''A'' && s <= ''F''))) { \ +- return 0; \ +-} +- +-#define IPV6_LOOP_IN(str) \ +- if (*str == '':'') { \ +- if (hexcode_found > 4) { \ +- return -134; \ +- } \ +- hexcode_found = 0; \ +- col_fnd++; \ +- } else { \ +- IS_HEX(*str); \ +- hexcode_found++; \ +- } +- +-static int _php_filter_validate_ipv6_(char *str, int str_len TSRMLS_DC) /* {{{ */ ++static int _php_filter_validate_ipv6(char *str, int str_len TSRMLS_DC) /* {{{ */ + { +- int hexcode_found = 0; +- int compressed_2end = 0; +- int col_fnd = 0; +- char *start = str; +- char *compressed = NULL, *t = str; +- char *s2 = NULL, *ipv4=NULL; ++ int compressed = 0; ++ int blocks = 8; ++ int n; ++ char *ipv4; ++ char *end; + int ip4elm[4]; + + if (!memchr(str, '':'', str_len)) { + return 0; + } + +- /* Check for compressed expression. only one is allowed */ +- compressed = php_memnstr(str, "::", sizeof("::")-1, str+str_len); +- if (compressed) { +- s2 = php_memnstr(compressed+1, "::", sizeof("::")-1, str + str_len); +- if (s2) { +- return 0; +- } +- } +- + /* check for bundled IPv4 */ + ipv4 = memchr(str, ''.'', str_len); +- + if (ipv4) { +- while (*ipv4 != '':'' && ipv4 >= start) { ++ while (ipv4 > str && *(ipv4-1) != '':'') { + ipv4--; + } + +- /* ::w.x.y.z */ +- if (compressed && ipv4 == (compressed + 1)) { +- compressed_2end = 1; +- } +- ipv4++; +- +- if (!_php_filter_validate_ipv4(ipv4, (str + str_len - ipv4), ip4elm)) { ++ if (!_php_filter_validate_ipv4(ipv4, (str_len - (ipv4 - str)), ip4elm)) { + return 0; + } +- +- if (compressed_2end) { +- return 1; ++ str_len = (ipv4 - str) - 1; ++ if (str_len == 1) { ++ return *str == '':''; + } ++ blocks = 6; + } + +- if (!compressed) { +- char *end; +- if (ipv4) { +- end = ipv4 - 1; +- } else { +- end = str + str_len; +- } +- +- while (*str && str <= end) { +- IPV6_LOOP_IN(str); +- str++; +- } +- +- if (!ipv4) { +- if (col_fnd != 7) { +- return 0; +- } else { +- return 1; +- } +- } else { +- if (col_fnd != 6) { +- return -1230; +- } else { +- return 1; +- } +- } +- } else { +- if (!ipv4) { +- t = compressed - 1; +- while (t >= start) { +- IPV6_LOOP_IN(t); +- t--; +- } +- +- if (hexcode_found > 4) { +- return 0; +- } +- +- t = compressed + 2; +- hexcode_found = 0; +- while (*t) { +- IPV6_LOOP_IN(t); +- t++; +- } +- +- if (hexcode_found > 4) { +- return 0; +- } +- +- if (col_fnd > 6) { +- return 0; +- } else { +- return 1; +- } +- } else { +- /* ipv4 part always at the end */ +- t = ipv4 - 1; +- while (t >= (compressed + 2)) { +- IPV6_LOOP_IN(t); +- t--; +- } +- +- if (hexcode_found > 4) { +- return 0; +- } +- +- hexcode_found = 0; +- t = compressed - 1; +- while (t >= start) { +- IPV6_LOOP_IN(t); +- t--; +- } +- if (hexcode_found > 4) { ++ end = str + str_len; ++ while (str < end) { ++ if (*str == '':'') { ++ if (--blocks == 0) { + return 0; +- } +- +- if (col_fnd > 6) { ++ } ++ if (++str >= end) { + return 0; +- } else { +- return 1; + } ++ if (*str == '':'') { ++ if (compressed || --blocks == 0) { ++ return 0; ++ } ++ if (++str == end) { ++ return 1; ++ } ++ compressed = 1; ++ } ++ } ++ n = 0; ++ while ((str < end) && ++ ((*str >= ''0'' && *str <= ''9'') || ++ (*str >= ''a'' && *str <= ''f'') || ++ (*str >= ''A'' && *str <= ''F''))) { ++ n++; ++ str++; ++ } ++ if (n < 1 || n > 4) { ++ return 0; + } + } +- return 0; ++ return (compressed || blocks == 1); + } + /* }}} */ + +@@ -770,7 +644,7 @@ + case FORMAT_IPV6: + { + int res = 0; +- res = _php_filter_validate_ipv6_(str, Z_STRLEN_P(value) TSRMLS_CC); ++ res = _php_filter_validate_ipv6(str, Z_STRLEN_P(value) TSRMLS_CC); + if (res < 1) { + RETURN_VALIDATION_FAILED + }