mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Fix GHSA-w8qr-v226-r27w
We should not early-out with success status if we found an ipv6 hostname, we should keep checking the rest of the conditions. Because integrating the if-check of the ipv6 hostname in the "Validate domain" if-check made the code hard to read, I extracted the condition out to a separate function. This also required to make a few pointers const in order to have some clean code.
This commit is contained in:
parent
88315f263d
commit
ec803292c2
2 changed files with 61 additions and 15 deletions
|
@ -89,7 +89,7 @@
|
||||||
#define FORMAT_IPV4 4
|
#define FORMAT_IPV4 4
|
||||||
#define FORMAT_IPV6 6
|
#define FORMAT_IPV6 6
|
||||||
|
|
||||||
static int _php_filter_validate_ipv6(char *str, size_t str_len, int ip[8]);
|
static int _php_filter_validate_ipv6(const 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) { /* {{{ */
|
static int php_filter_parse_int(const char *str, size_t str_len, zend_long *ret) { /* {{{ */
|
||||||
zend_long ctx_value;
|
zend_long ctx_value;
|
||||||
|
@ -580,6 +580,14 @@ static int is_userinfo_valid(zend_string *str)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool php_filter_is_valid_ipv6_hostname(const char *s, size_t l)
|
||||||
|
{
|
||||||
|
const char *e = s + l;
|
||||||
|
const char *t = e - 1;
|
||||||
|
|
||||||
|
return *s == '[' && *t == ']' && _php_filter_validate_ipv6(s + 1, l - 2, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
|
void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
|
||||||
{
|
{
|
||||||
php_url *url;
|
php_url *url;
|
||||||
|
@ -600,7 +608,7 @@ void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
|
||||||
|
|
||||||
if (url->scheme != NULL &&
|
if (url->scheme != NULL &&
|
||||||
(zend_string_equals_literal_ci(url->scheme, "http") || zend_string_equals_literal_ci(url->scheme, "https"))) {
|
(zend_string_equals_literal_ci(url->scheme, "http") || zend_string_equals_literal_ci(url->scheme, "https"))) {
|
||||||
char *e, *s, *t;
|
const char *s;
|
||||||
size_t l;
|
size_t l;
|
||||||
|
|
||||||
if (url->host == NULL) {
|
if (url->host == NULL) {
|
||||||
|
@ -609,17 +617,14 @@ void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
|
||||||
|
|
||||||
s = ZSTR_VAL(url->host);
|
s = ZSTR_VAL(url->host);
|
||||||
l = ZSTR_LEN(url->host);
|
l = ZSTR_LEN(url->host);
|
||||||
e = s + l;
|
|
||||||
t = e - 1;
|
|
||||||
|
|
||||||
/* An IPv6 enclosed by square brackets is a valid hostname */
|
if (
|
||||||
if (*s == '[' && *t == ']' && _php_filter_validate_ipv6((s + 1), l - 2, NULL)) {
|
/* An IPv6 enclosed by square brackets is a valid hostname.*/
|
||||||
php_url_free(url);
|
!php_filter_is_valid_ipv6_hostname(s, l) &&
|
||||||
return;
|
/* Validate domain.
|
||||||
}
|
* This includes a loose check for an IPv4 address. */
|
||||||
|
!_php_filter_validate_domain(ZSTR_VAL(url->host), l, FILTER_FLAG_HOSTNAME)
|
||||||
// Validate domain
|
) {
|
||||||
if (!_php_filter_validate_domain(ZSTR_VAL(url->host), l, FILTER_FLAG_HOSTNAME)) {
|
|
||||||
php_url_free(url);
|
php_url_free(url);
|
||||||
RETURN_VALIDATION_FAILED
|
RETURN_VALIDATION_FAILED
|
||||||
}
|
}
|
||||||
|
@ -753,15 +758,15 @@ 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, int ip[8]) /* {{{ */
|
static int _php_filter_validate_ipv6(const char *str, size_t str_len, int ip[8]) /* {{{ */
|
||||||
{
|
{
|
||||||
int compressed_pos = -1;
|
int compressed_pos = -1;
|
||||||
int blocks = 0;
|
int blocks = 0;
|
||||||
int num, n, i;
|
int num, n, i;
|
||||||
char *ipv4;
|
char *ipv4;
|
||||||
char *end;
|
const char *end;
|
||||||
int ip4elm[4];
|
int ip4elm[4];
|
||||||
char *s = str;
|
const char *s = str;
|
||||||
|
|
||||||
if (!memchr(str, ':', str_len)) {
|
if (!memchr(str, ':', str_len)) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
41
ext/filter/tests/ghsa-w8qr-v226-r27w.phpt
Normal file
41
ext/filter/tests/ghsa-w8qr-v226-r27w.phpt
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
--TEST--
|
||||||
|
GHSA-w8qr-v226-r27w
|
||||||
|
--EXTENSIONS--
|
||||||
|
filter
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function test(string $input) {
|
||||||
|
var_dump(filter_var($input, FILTER_VALIDATE_URL));
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "--- These ones should fail ---\n";
|
||||||
|
test("http://t[est@127.0.0.1");
|
||||||
|
test("http://t[est@[::1]");
|
||||||
|
test("http://t[est@[::1");
|
||||||
|
test("http://t[est@::1]");
|
||||||
|
test("http://php.net\\@aliyun.com/aaa.do");
|
||||||
|
test("http://test[@2001:db8:3333:4444:5555:6666:1.2.3.4]");
|
||||||
|
test("http://te[st@2001:db8:3333:4444:5555:6666:1.2.3.4]");
|
||||||
|
test("http://te[st@2001:db8:3333:4444:5555:6666:1.2.3.4");
|
||||||
|
|
||||||
|
echo "--- These ones should work ---\n";
|
||||||
|
test("http://test@127.0.0.1");
|
||||||
|
test("http://test@[2001:db8:3333:4444:5555:6666:1.2.3.4]");
|
||||||
|
test("http://test@[::1]");
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
--- These ones should fail ---
|
||||||
|
bool(false)
|
||||||
|
bool(false)
|
||||||
|
bool(false)
|
||||||
|
bool(false)
|
||||||
|
bool(false)
|
||||||
|
bool(false)
|
||||||
|
bool(false)
|
||||||
|
bool(false)
|
||||||
|
--- These ones should work ---
|
||||||
|
string(21) "http://test@127.0.0.1"
|
||||||
|
string(50) "http://test@[2001:db8:3333:4444:5555:6666:1.2.3.4]"
|
||||||
|
string(17) "http://test@[::1]"
|
Loading…
Add table
Add a link
Reference in a new issue