Skip to content

Commit 87a7b8d

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) (cherry picked from commit 08be64e) (cherry picked from commit 76362f9)
1 parent be83060 commit 87a7b8d

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
@@ -81,7 +81,7 @@
8181
#define FORMAT_IPV4 4
8282
#define FORMAT_IPV6 6
8383

84-
static int _php_filter_validate_ipv6(char *str, size_t str_len);
84+
static int _php_filter_validate_ipv6(const char *str, size_t str_len);
8585

8686
static int php_filter_parse_int(const char *str, size_t str_len, zend_long *ret) { /* {{{ */
8787
zend_long ctx_value;
@@ -532,6 +532,14 @@ static int is_userinfo_valid(char *str)
532532
return 1;
533533
}
534534

535+
static zend_bool php_filter_is_valid_ipv6_hostname(const char *s, size_t l)
536+
{
537+
const char *e = s + l;
538+
const char *t = e - 1;
539+
540+
return *s == '[' && *t == ']' && _php_filter_validate_ipv6(s + 1, l - 2);
541+
}
542+
535543
void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
536544
{
537545
php_url *url;
@@ -551,7 +559,7 @@ void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
551559
}
552560

553561
if (url->scheme != NULL && (!strcasecmp(url->scheme, "http") || !strcasecmp(url->scheme, "https"))) {
554-
char *e, *s, *t;
562+
const char *s;
555563
size_t l;
556564

557565
if (url->host == NULL) {
@@ -560,17 +568,14 @@ void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
560568

561569
s = url->host;
562570
l = strlen(s);
563-
e = url->host + l;
564-
t = e - 1;
565-
566-
/* An IPv6 enclosed by square brackets is a valid hostname */
567-
if (*s == '[' && *t == ']' && _php_filter_validate_ipv6((s + 1), l - 2)) {
568-
php_url_free(url);
569-
return;
570-
}
571571

572-
// Validate domain
573-
if (!_php_filter_validate_domain(url->host, l, FILTER_FLAG_HOSTNAME)) {
572+
if (
573+
/* An IPv6 enclosed by square brackets is a valid hostname.*/
574+
!php_filter_is_valid_ipv6_hostname(s, l) &&
575+
/* Validate domain.
576+
* This includes a loose check for an IPv4 address. */
577+
!_php_filter_validate_domain(url->host, l, FILTER_FLAG_HOSTNAME)
578+
) {
574579
php_url_free(url);
575580
RETURN_VALIDATION_FAILED
576581
}
@@ -701,15 +706,15 @@ static int _php_filter_validate_ipv4(char *str, size_t str_len, int *ip) /* {{{
701706
}
702707
/* }}} */
703708

704-
static int _php_filter_validate_ipv6(char *str, size_t str_len) /* {{{ */
709+
static int _php_filter_validate_ipv6(const char *str, size_t str_len) /* {{{ */
705710
{
706711
int compressed = 0;
707712
int blocks = 0;
708713
int n;
709714
char *ipv4;
710-
char *end;
715+
const char *end;
711716
int ip4elm[4];
712-
char *s = str;
717+
const char *s = str;
713718

714719
if (!memchr(str, ':', str_len)) {
715720
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)