dmitry Tue Dec 26 09:16:25 2006 UTC
Added files: (Branch: PHP_5_2)
/php-src/ext/filter/tests 045.phpt 046.phpt 047.phpt 048.phpt
049.phpt 050.phpt 051.phpt
Modified files:
/php-src/ext/filter filter.c filter_private.h logical_filters.c
/php-src/ext/filter/tests 030.phpt bug7733.phpt
Log:
Code review:
. fixed integer overflow
. fixed buffer overflow/underflow
. added more strict IP validation
. reimplemented float number validation
http://cvs.php.net/viewvc.cgi/php-src/ext/filter/filter.c?r1=1.52.2.36&r2=1.52.2.37&diff_format=u
Index: php-src/ext/filter/filter.c
diff -u php-src/ext/filter/filter.c:1.52.2.36
php-src/ext/filter/filter.c:1.52.2.37
--- php-src/ext/filter/filter.c:1.52.2.36 Sat Dec 9 14:14:29 2006
+++ php-src/ext/filter/filter.c Tue Dec 26 09:16:24 2006
@@ -19,7 +19,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: filter.c,v 1.52.2.36 2006/12/09 14:14:29 iliaa Exp $ */
+/* $Id: filter.c,v 1.52.2.37 2006/12/26 09:16:24 dmitry Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -275,7 +275,7 @@
{
php_info_print_table_start();
php_info_print_table_row( 2, "Input Validation and Filtering",
"enabled" );
- php_info_print_table_row( 2, "Revision", "$Revision: 1.52.2.36 $");
+ php_info_print_table_row( 2, "Revision", "$Revision: 1.52.2.37 $");
php_info_print_table_end();
DISPLAY_INI_ENTRIES();
@@ -331,6 +331,7 @@
if (zend_hash_find(HASH_OF(options), "default",
sizeof("default"), (void **)&tmp) == SUCCESS) {
**value = **tmp;
zval_copy_ctor(*value);
+ INIT_PZVAL(*value);
}
}
}
@@ -518,7 +519,6 @@
long arg;
char *var;
int var_len;
- zval **tmp;
zval *array_ptr = NULL;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ls", &arg, &var,
&var_len) == FAILURE) {
@@ -527,7 +527,7 @@
array_ptr = php_filter_get_storage(arg TSRMLS_CC);
- if (array_ptr && HASH_OF(array_ptr) &&
zend_hash_find(HASH_OF(array_ptr), var, var_len + 1, (void **)&tmp) == SUCCESS)
{
+ if (array_ptr && HASH_OF(array_ptr) &&
zend_hash_exists(HASH_OF(array_ptr), var, var_len + 1)) {
RETURN_TRUE;
}
@@ -542,22 +542,27 @@
char *charset = NULL;
if (filter_args && Z_TYPE_PP(filter_args) != IS_ARRAY) {
- convert_to_long_ex(filter_args);
+ long lval;
+
+ PHP_FILTER_GET_LONG_OPT(filter_args, lval);
+
if (filter != -1) { /* handler for array apply */
/* filter_args is the filter_flags */
- filter_flags = Z_LVAL_PP(filter_args);
+ filter_flags = lval;
+
+ if (!(filter_flags & FILTER_REQUIRE_ARRAY ||
filter_flags & FILTER_FORCE_ARRAY)) {
+ filter_flags |= FILTER_REQUIRE_SCALAR;
+ }
} else {
- filter = Z_LVAL_PP(filter_args);
+ filter = lval;
}
} else if (filter_args) {
if (zend_hash_find(HASH_OF(*filter_args), "filter",
sizeof("filter"), (void **)&option) == SUCCESS) {
- convert_to_long(*option);
- filter = Z_LVAL_PP(option);
+ PHP_FILTER_GET_LONG_OPT(option, filter);
}
if (zend_hash_find(HASH_OF(*filter_args), "flags",
sizeof("flags"), (void **)&option) == SUCCESS) {
- convert_to_long(*option);
- filter_flags = Z_LVAL_PP(option);
+ PHP_FILTER_GET_LONG_OPT(option, filter_flags);
if (!(filter_flags & FILTER_REQUIRE_ARRAY ||
filter_flags & FILTER_FORCE_ARRAY)) {
filter_flags |= FILTER_REQUIRE_SCALAR;
@@ -708,14 +713,15 @@
if (Z_TYPE_PP(filter_args) == IS_LONG) {
filter_flags = Z_LVAL_PP(filter_args);
} else if (Z_TYPE_PP(filter_args) == IS_ARRAY &&
zend_hash_find(HASH_OF(*filter_args), "flags", sizeof("flags"), (void
**)&option) == SUCCESS) {
- convert_to_long(*option);
- filter_flags = Z_LVAL_PP(option);
+ PHP_FILTER_GET_LONG_OPT(option, filter_flags);
} else if (Z_TYPE_PP(filter_args) == IS_ARRAY &&
zend_hash_find(HASH_OF(*filter_args),
"options", sizeof("options"), (void **)&opt) == SUCCESS &&
+ Z_TYPE_PP(opt) == IS_ARRAY &&
zend_hash_find(HASH_OF(*opt), "default",
sizeof("default"), (void **)&def) == SUCCESS
) {
*return_value = **def;
zval_copy_ctor(return_value);
+ INIT_PZVAL(return_value);
return;
}
}
@@ -728,6 +734,7 @@
*return_value = **tmp;
zval_copy_ctor(return_value); /* Watch out for empty strings */
+ INIT_PZVAL(return_value);
php_filter_call(&return_value, filter, filter_args, 1,
FILTER_REQUIRE_SCALAR TSRMLS_CC);
}
@@ -751,6 +758,7 @@
*return_value = *data;
zval_copy_ctor(data);
+ INIT_PZVAL(return_value);
php_filter_call(&return_value, filter, filter_args, 1,
FILTER_REQUIRE_SCALAR TSRMLS_CC);
}
@@ -782,8 +790,7 @@
if (Z_TYPE_PP(op) == IS_LONG) {
filter_flags = Z_LVAL_PP(op);
} else if (Z_TYPE_PP(op) == IS_ARRAY &&
zend_hash_find(HASH_OF(*op), "flags", sizeof("flags"), (void **)&option) ==
SUCCESS) {
- convert_to_long(*option);
- filter_flags = Z_LVAL_PP(option);
+ PHP_FILTER_GET_LONG_OPT(option, filter_flags);
}
}
if (filter_flags & FILTER_NULL_ON_FAILURE) {
http://cvs.php.net/viewvc.cgi/php-src/ext/filter/filter_private.h?r1=1.12.2.7&r2=1.12.2.8&diff_format=u
Index: php-src/ext/filter/filter_private.h
diff -u php-src/ext/filter/filter_private.h:1.12.2.7
php-src/ext/filter/filter_private.h:1.12.2.8
--- php-src/ext/filter/filter_private.h:1.12.2.7 Mon Dec 18 14:56:40 2006
+++ php-src/ext/filter/filter_private.h Tue Dec 26 09:16:24 2006
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: filter_private.h,v 1.12.2.7 2006/12/18 14:56:40 iliaa Exp $ */
+/* $Id: filter_private.h,v 1.12.2.8 2006/12/26 09:16:24 dmitry Exp $ */
#ifndef FILTER_PRIVATE_H
#define FILTER_PRIVATE_H
@@ -97,23 +97,29 @@
} \
return; \
-#define PHP_FILTER_TRIM_DEFAULT(p, len, end) { \
- while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\v' || *p ==
'\n') { \
+#define PHP_FILTER_TRIM_DEFAULT(p, len) { \
+ while ((len > 0) && (*p == ' ' || *p == '\t' || *p == '\r' || *p ==
'\v' || *p == '\n')) { \
p++; \
len--; \
} \
- if (len < 1) { \
- RETURN_VALIDATION_FAILED \
- } \
- start = p; \
- end = p + len - 1; \
- while (*end == ' ' || *end == '\t' || *end == '\r' || *end == '\v' ||
*end == '\n') { \
- end--; \
+ if (len < 1) { \
+ RETURN_VALIDATION_FAILED \
+ } \
+ while (p[len-1] == ' ' || p[len-1] == '\t' || p[len-1] == '\r' ||
p[len-1] == '\v' || p[len-1] == '\n') { \
+ len--; \
} \
- *(end + 1) = '\0'; \
- len = (end - p + 1); \
}
+#define PHP_FILTER_GET_LONG_OPT(zv, opt) { \
+ if (Z_TYPE_PP(zv) != IS_LONG) {
\
+ zval tmp = **zv;
\
+ zval_copy_ctor(&tmp);
\
+ convert_to_long(&tmp);
\
+ opt = Z_LVAL(tmp);
\
+ } else {
\
+ opt = Z_LVAL_PP(zv);
\
+ }
\
+}
#endif /* FILTER_PRIVATE_H */
http://cvs.php.net/viewvc.cgi/php-src/ext/filter/logical_filters.c?r1=1.1.2.17&r2=1.1.2.18&diff_format=u
Index: php-src/ext/filter/logical_filters.c
diff -u php-src/ext/filter/logical_filters.c:1.1.2.17
php-src/ext/filter/logical_filters.c:1.1.2.18
--- php-src/ext/filter/logical_filters.c:1.1.2.17 Wed Dec 20 19:48:12 2006
+++ php-src/ext/filter/logical_filters.c Tue Dec 26 09:16:24 2006
@@ -17,17 +17,21 @@
+----------------------------------------------------------------------+
*/
-/* $Id: logical_filters.c,v 1.1.2.17 2006/12/20 19:48:12 iliaa Exp $ */
+/* $Id: logical_filters.c,v 1.1.2.18 2006/12/26 09:16:24 dmitry Exp $ */
#include "php_filter.h"
#include "filter_private.h"
#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
}
http://cvs.php.net/viewvc.cgi/php-src/ext/filter/tests/030.phpt?r1=1.3.2.4&r2=1.3.2.5&diff_format=u
Index: php-src/ext/filter/tests/030.phpt
diff -u php-src/ext/filter/tests/030.phpt:1.3.2.4
php-src/ext/filter/tests/030.phpt:1.3.2.5
--- php-src/ext/filter/tests/030.phpt:1.3.2.4 Tue Dec 19 14:16:23 2006
+++ php-src/ext/filter/tests/030.phpt Tue Dec 26 09:16:25 2006
@@ -21,7 +21,13 @@
"0:0:0:0:0:FFFF:129.144.52.38" => true,
"0:0:0:0:0:0:13.1.68.3" => true,
"::13.1.68.3" => true,
- "::FFFF:129.144.52.38" => true
+ "::FFFF:129.144.52.38" => true,
+ "1:2:3:4:5:6::129.144.52.38" => false,
+ "::1:2:3:4:5:6:129.144.52.38" => false,
+ "1:2:3::4:5:6:129.144.52.38" => false,
+ "1:2:3:4:5:6:7:8::" => false,
+ "::1:2:3:4:5:6:7:8" => false,
+ "1:2:3:4::5:6:7:8" => false,
);
foreach ($ipv6_test as $ip => $exp) {
$out = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
http://cvs.php.net/viewvc.cgi/php-src/ext/filter/tests/bug7733.phpt?r1=1.1.2.3&r2=1.1.2.4&diff_format=u
Index: php-src/ext/filter/tests/bug7733.phpt
diff -u php-src/ext/filter/tests/bug7733.phpt:1.1.2.3
php-src/ext/filter/tests/bug7733.phpt:1.1.2.4
--- php-src/ext/filter/tests/bug7733.phpt:1.1.2.3 Tue Dec 19 14:16:23 2006
+++ php-src/ext/filter/tests/bug7733.phpt Tue Dec 26 09:16:25 2006
@@ -17,13 +17,13 @@
--EXPECTF--
array(5) {
[0]=>
- float(0)
+ bool(false)
[1]=>
- float(10)
+ bool(false)
[2]=>
- float(2)
+ bool(false)
[3]=>
- float(0)
+ bool(false)
[4]=>
- float(0)
+ bool(false)
}
http://cvs.php.net/viewvc.cgi/php-src/ext/filter/tests/045.phpt?view=markup&rev=1.1
Index: php-src/ext/filter/tests/045.phpt
+++ php-src/ext/filter/tests/045.phpt
http://cvs.php.net/viewvc.cgi/php-src/ext/filter/tests/046.phpt?view=markup&rev=1.1
Index: php-src/ext/filter/tests/046.phpt
+++ php-src/ext/filter/tests/046.phpt
http://cvs.php.net/viewvc.cgi/php-src/ext/filter/tests/047.phpt?view=markup&rev=1.1
Index: php-src/ext/filter/tests/047.phpt
+++ php-src/ext/filter/tests/047.phpt
http://cvs.php.net/viewvc.cgi/php-src/ext/filter/tests/048.phpt?view=markup&rev=1.1
Index: php-src/ext/filter/tests/048.phpt
+++ php-src/ext/filter/tests/048.phpt
http://cvs.php.net/viewvc.cgi/php-src/ext/filter/tests/049.phpt?view=markup&rev=1.1
Index: php-src/ext/filter/tests/049.phpt
+++ php-src/ext/filter/tests/049.phpt
http://cvs.php.net/viewvc.cgi/php-src/ext/filter/tests/050.phpt?view=markup&rev=1.1
Index: php-src/ext/filter/tests/050.phpt
+++ php-src/ext/filter/tests/050.phpt
http://cvs.php.net/viewvc.cgi/php-src/ext/filter/tests/051.phpt?view=markup&rev=1.1
Index: php-src/ext/filter/tests/051.phpt
+++ php-src/ext/filter/tests/051.phpt
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php