Skip to content

Commit 08be64e

Browse files
nielsdosremicollet
authored andcommitted
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. (cherry picked from commit 4066610)
1 parent f8f4596 commit 08be64e

File tree

2 files changed

+61
-15
lines changed

2 files changed

+61
-15
lines changed

ext/filter/logical_filters.c

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@
9191
#define FORMAT_IPV4 4
9292
#define FORMAT_IPV6 6
9393

94-
static int _php_filter_validate_ipv6(char *str, size_t str_len, int ip[8]);
94+
static int _php_filter_validate_ipv6(const char *str, size_t str_len, int ip[8]);
9595

9696
static int php_filter_parse_int(const char *str, size_t str_len, zend_long *ret) { /* {{{ */
9797
zend_long ctx_value;
@@ -571,6 +571,14 @@ static int is_userinfo_valid(zend_string *str)
571571
return 1;
572572
}
573573

574+
static zend_bool php_filter_is_valid_ipv6_hostname(const char *s, size_t l)
575+
{
576+
const char *e = s + l;
577+
const char *t = e - 1;
578+
579+
return *s == '[' && *t == ']' && _php_filter_validate_ipv6(s + 1, l - 2, NULL);
580+
}
581+
574582
void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
575583
{
576584
php_url *url;
@@ -596,7 +604,7 @@ void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
596604

597605
if (url->scheme != NULL &&
598606
(zend_string_equals_literal_ci(url->scheme, "http") || zend_string_equals_literal_ci(url->scheme, "https"))) {
599-
char *e, *s, *t;
607+
const char *s;
600608
size_t l;
601609

602610
if (url->host == NULL) {
@@ -605,17 +613,14 @@ void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
605613

606614
s = ZSTR_VAL(url->host);
607615
l = ZSTR_LEN(url->host);
608-
e = s + l;
609-
t = e - 1;
610-
611-
/* An IPv6 enclosed by square brackets is a valid hostname */
612-
if (*s == '[' && *t == ']' && _php_filter_validate_ipv6((s + 1), l - 2, NULL)) {
613-
php_url_free(url);
614-
return;
615-
}
616616

617-
// Validate domain
618-
if (!_php_filter_validate_domain(ZSTR_VAL(url->host), l, FILTER_FLAG_HOSTNAME)) {
617+
if (
618+
/* An IPv6 enclosed by square brackets is a valid hostname.*/
619+
!php_filter_is_valid_ipv6_hostname(s, l) &&
620+
/* Validate domain.
621+
* This includes a loose check for an IPv4 address. */
622+
!_php_filter_validate_domain(ZSTR_VAL(url->host), l, FILTER_FLAG_HOSTNAME)
623+
) {
619624
php_url_free(url);
620625
RETURN_VALIDATION_FAILED
621626
}
@@ -749,15 +754,15 @@ static int _php_filter_validate_ipv4(char *str, size_t str_len, int *ip) /* {{{
749754
}
750755
/* }}} */
751756

752-
static int _php_filter_validate_ipv6(char *str, size_t str_len, int ip[8]) /* {{{ */
757+
static int _php_filter_validate_ipv6(const char *str, size_t str_len, int ip[8]) /* {{{ */
753758
{
754759
int compressed_pos = -1;
755760
int blocks = 0;
756761
int num, n, i;
757762
char *ipv4;
758-
char *end;
763+
const char *end;
759764
int ip4elm[4];
760-
char *s = str;
765+
const char *s = str;
761766

762767
if (!memchr(str, ':', str_len)) {
763768
return 0;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
--TEST--
2+
GHSA-w8qr-v226-r27w
3+
--EXTENSIONS--
4+
filter
5+
--FILE--
6+
<?php
7+
8+
function test(string $input) {
9+
var_dump(filter_var($input, FILTER_VALIDATE_URL));
10+
}
11+
12+
echo "--- These ones should fail ---\n";
13+
test("http://t[[email protected]");
14+
test("http://t[est@[::1]");
15+
test("http://t[est@[::1");
16+
test("http://t[est@::1]");
17+
test("http://php.net\\@aliyun.com/aaa.do");
18+
test("http://test[@2001:db8:3333:4444:5555:6666:1.2.3.4]");
19+
test("http://te[st@2001:db8:3333:4444:5555:6666:1.2.3.4]");
20+
test("http://te[st@2001:db8:3333:4444:5555:6666:1.2.3.4");
21+
22+
echo "--- These ones should work ---\n";
23+
test("http://[email protected]");
24+
test("http://test@[2001:db8:3333:4444:5555:6666:1.2.3.4]");
25+
test("http://test@[::1]");
26+
27+
?>
28+
--EXPECT--
29+
--- These ones should fail ---
30+
bool(false)
31+
bool(false)
32+
bool(false)
33+
bool(false)
34+
bool(false)
35+
bool(false)
36+
bool(false)
37+
bool(false)
38+
--- These ones should work ---
39+
string(21) "http://[email protected]"
40+
string(50) "http://test@[2001:db8:3333:4444:5555:6666:1.2.3.4]"
41+
string(17) "http://test@[::1]"

0 commit comments

Comments
 (0)