mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4: Fix #61700: FILTER_FLAG_IPV6/FILTER_FLAG_NO_PRIV|RES_RANGE failing
This commit is contained in:
commit
fbc922d55c
4 changed files with 82 additions and 54 deletions
4
NEWS
4
NEWS
|
@ -17,6 +17,10 @@ PHP NEWS
|
|||
- Fileinfo:
|
||||
. Fixed bug #78987 (High memory usage during encoding detection). (Anatol)
|
||||
|
||||
- Filter:
|
||||
. Fixed bug #61700 (FILTER_FLAG_IPV6/FILTER_FLAG_NO_PRIV|RES_RANGE failing).
|
||||
(cmb, Nikita)
|
||||
|
||||
- PCRE:
|
||||
. Fixed bug #81424 (PCRE2 10.35 JIT performance regression). (cmb)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
@ -605,7 +605,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;
|
||||
}
|
||||
|
@ -745,11 +745,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];
|
||||
|
@ -792,35 +792,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;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -831,7 +863,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))) {
|
||||
|
@ -882,51 +914,27 @@ 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 (!strcmp("::", Z_STRVAL_P(value))) {
|
||||
RETURN_VALIDATION_FAILED
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if (!strcmp("::1", Z_STRVAL_P(value)) || !strcmp("5f:", Z_STRVAL_P(value))) {
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
16
ext/filter/tests/bug61700.phpt
Normal file
16
ext/filter/tests/bug61700.phpt
Normal file
|
@ -0,0 +1,16 @@
|
|||
--TEST--
|
||||
Bug #61700 (FILTER_FLAG_IPV6/FILTER_FLAG_NO_PRIV|RES_RANGE failing)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded("filter")) die("skip filter extension not available");
|
||||
?>
|
||||
--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)
|
Loading…
Add table
Add a link
Reference in a new issue