Merge branch 'PHP-8.0' into PHP-8.1

* PHP-8.0:
  Fix #61700: FILTER_FLAG_IPV6/FILTER_FLAG_NO_PRIV|RES_RANGE failing
This commit is contained in:
Christoph M. Becker 2021-09-20 17:43:03 +02:00
commit 1dcc0ff5f6
No known key found for this signature in database
GPG Key ID: D66C9593118BCCB6
4 changed files with 78 additions and 52 deletions

4
NEWS
View File

@ -2,6 +2,10 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? ????, PHP 8.1.0RC3
- Filter:
. Fixed bug #61700 (FILTER_FLAG_IPV6/FILTER_FLAG_NO_PRIV|RES_RANGE failing).
(cmb, Nikita)
- Reflection:
. Fixed bug #81457 (Enum: ReflectionMethod->getDeclaringClass() return a
ReflectionClass). (Nikita)

View File

@ -89,7 +89,7 @@
#define FORMAT_IPV4 4
#define FORMAT_IPV6 6
static int _php_filter_validate_ipv6(char *str, size_t str_len);
static int _php_filter_validate_ipv6(char *str, size_t str_len, int ip[8]);
static int php_filter_parse_int(const char *str, size_t str_len, zend_long *ret) { /* {{{ */
zend_long ctx_value;
@ -613,7 +613,7 @@ void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
t = e - 1;
/* An IPv6 enclosed by square brackets is a valid hostname */
if (*s == '[' && *t == ']' && _php_filter_validate_ipv6((s + 1), l - 2)) {
if (*s == '[' && *t == ']' && _php_filter_validate_ipv6((s + 1), l - 2, NULL)) {
php_url_free(url);
return;
}
@ -753,11 +753,11 @@ static int _php_filter_validate_ipv4(char *str, size_t str_len, int *ip) /* {{{
}
/* }}} */
static int _php_filter_validate_ipv6(char *str, size_t str_len) /* {{{ */
static int _php_filter_validate_ipv6(char *str, size_t str_len, int ip[8]) /* {{{ */
{
int compressed = 0;
int compressed_pos = -1;
int blocks = 0;
int n;
int num, n, i;
char *ipv4;
char *end;
int ip4elm[4];
@ -800,35 +800,67 @@ static int _php_filter_validate_ipv6(char *str, size_t str_len) /* {{{ */
return 0;
}
if (*str == ':') {
if (compressed) {
if (compressed_pos >= 0) {
return 0;
}
blocks++; /* :: means 1 or more 16-bit 0 blocks */
compressed = 1;
if (ip && blocks < 8) {
ip[blocks] = -1;
}
compressed_pos = blocks++; /* :: means 1 or more 16-bit 0 blocks */
if (++str == end) {
return (blocks <= 8);
if (blocks > 8) {
return 0;
}
goto fixup_ip;
}
} else if ((str - 1) == s) {
/* don't allow leading : without another : following */
return 0;
}
}
n = 0;
while ((str < end) &&
((*str >= '0' && *str <= '9') ||
(*str >= 'a' && *str <= 'f') ||
(*str >= 'A' && *str <= 'F'))) {
num = n = 0;
while (str < end) {
if (*str >= '0' && *str <= '9') {
num = 16 * num + (*str - '0');
} else if (*str >= 'a' && *str <= 'f') {
num = 16 * num + (*str - 'a') + 10;
} else if (*str >= 'A' && *str <= 'F') {
num = 16 * num + (*str - 'A') + 10;
} else {
break;
}
n++;
str++;
}
if (ip && blocks < 8) {
ip[blocks] = num;
}
if (n < 1 || n > 4) {
return 0;
}
if (++blocks > 8)
return 0;
}
return ((compressed && blocks <= 8) || blocks == 8);
fixup_ip:
if (ip && ipv4) {
for (i = 0; i < 5; i++) {
ip[i] = 0;
}
ip[i++] = 0xffff;
ip[i++] = 256 * ip4elm[0] + ip4elm[1];
ip[i++] = 256 * ip4elm[2] + ip4elm[3];
} else if (ip && compressed_pos >= 0 && blocks <= 8) {
int offset = 8 - blocks;
for (i = 7; i > compressed_pos + offset; i--) {
ip[i] = ip[i - offset];
}
for (i = compressed_pos + offset; i >= compressed_pos; i--) {
ip[i] = 0;
}
}
return (compressed_pos >= 0 && blocks <= 8) || blocks == 8;
}
/* }}} */
@ -839,7 +871,7 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
* allow_ipv4 and allow_ipv6 flags flag are used, then the first dot or
* colon determine the format */
int ip[4];
int ip[8];
int mode;
if (memchr(Z_STRVAL_P(value), ':', Z_STRLEN_P(value))) {
@ -890,52 +922,28 @@ void php_filter_validate_ip(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
case FORMAT_IPV6:
{
int res = 0;
res = _php_filter_validate_ipv6(Z_STRVAL_P(value), Z_STRLEN_P(value));
res = _php_filter_validate_ipv6(Z_STRVAL_P(value), Z_STRLEN_P(value), ip);
if (res < 1) {
RETURN_VALIDATION_FAILED
}
/* Check flags */
if (flags & FILTER_FLAG_NO_PRIV_RANGE) {
if (Z_STRLEN_P(value) >=2 && (!strncasecmp("FC", Z_STRVAL_P(value), 2) || !strncasecmp("FD", Z_STRVAL_P(value), 2))) {
if (ip[0] >= 0xfc00 && ip[0] <= 0xfdff) {
RETURN_VALIDATION_FAILED
}
}
if (flags & FILTER_FLAG_NO_RES_RANGE) {
switch (Z_STRLEN_P(value)) {
case 1: case 0:
break;
case 2:
if (zend_string_equals_literal(Z_STR_P(value), "::")) {
RETURN_VALIDATION_FAILED
}
break;
case 3:
if (zend_string_equals_literal(Z_STR_P(value), "::1") || zend_string_equals_literal(Z_STR_P(value), "5f:")) {
RETURN_VALIDATION_FAILED
}
break;
default:
if (Z_STRLEN_P(value) >= 5) {
if (
!strncasecmp("fe8", Z_STRVAL_P(value), 3) ||
!strncasecmp("fe9", Z_STRVAL_P(value), 3) ||
!strncasecmp("fea", Z_STRVAL_P(value), 3) ||
!strncasecmp("feb", Z_STRVAL_P(value), 3)
if ((ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0
&& ip[4] == 0 && ip[5] == 0 && ip[6] == 0 && (ip[7] == 0 || ip[7] == 1))
|| (ip[0] == 0x5f)
|| (ip[0] >= 0xfe80 && ip[0] <= 0xfebf)
|| ((ip[0] == 0x2001 && ip[1] == 0x0db8) || (ip[1] >= 0x0010 && ip[1] <= 0x001f))
|| (ip[0] == 0x3ff3)
) {
RETURN_VALIDATION_FAILED
}
}
if (
(Z_STRLEN_P(value) >= 9 && !strncasecmp("2001:0db8", Z_STRVAL_P(value), 9)) ||
(Z_STRLEN_P(value) >= 2 && !strncasecmp("5f", Z_STRVAL_P(value), 2)) ||
(Z_STRLEN_P(value) >= 4 && !strncasecmp("3ff3", Z_STRVAL_P(value), 4)) ||
(Z_STRLEN_P(value) >= 8 && !strncasecmp("2001:001", Z_STRVAL_P(value), 8))
) {
RETURN_VALIDATION_FAILED
}
}
}
}
break;
}
}

View File

@ -10,8 +10,8 @@ var_dump(filter_var("::", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6));
var_dump(filter_var("::", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE));
var_dump(filter_var("::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6));
var_dump(filter_var("::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE));
var_dump(filter_var("fe8:5:6::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6));
var_dump(filter_var("fe8:5:6::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE));
var_dump(filter_var("fe80:5:6::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6));
var_dump(filter_var("fe80:5:6::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE));
var_dump(filter_var("2001:0db8::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6));
var_dump(filter_var("2001:0db8::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6 | FILTER_FLAG_NO_RES_RANGE));
var_dump(filter_var("5f::1", FILTER_VALIDATE_IP, FILTER_FLAG_IPV6));
@ -26,7 +26,7 @@ string(2) "::"
bool(false)
string(3) "::1"
bool(false)
string(10) "fe8:5:6::1"
string(11) "fe80:5:6::1"
bool(false)
string(12) "2001:0db8::1"
bool(false)

View File

@ -0,0 +1,14 @@
--TEST--
Bug #61700 (FILTER_FLAG_IPV6/FILTER_FLAG_NO_PRIV|RES_RANGE failing)
--EXTENSIONS--
filter
--FILE--
<?php
var_dump(filter_var('::ffff:192.168.1.1', FILTER_VALIDATE_IP, FILTER_FLAG_IPV4));
var_dump(filter_var('::ffff:192.168.1.1', FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE));
var_dump(filter_var('0:0:0:0:0:0:0:1', FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE));
?>
--EXPECT--
bool(false)
string(18) "::ffff:192.168.1.1"
bool(false)