Skip to content

Commit f232d87

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) (cherry picked from commit 87a7b8d) (cherry picked from commit b919ad0)
1 parent d339e61 commit f232d87

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
}
@@ -691,15 +696,15 @@ static int _php_filter_validate_ipv4(char *str, size_t str_len, int *ip) /* {{{
691696
}
692697
/* }}} */
693698

694-
static int _php_filter_validate_ipv6(char *str, size_t str_len) /* {{{ */
699+
static int _php_filter_validate_ipv6(const char *str, size_t str_len) /* {{{ */
695700
{
696701
int compressed = 0;
697702
int blocks = 0;
698703
int n;
699704
char *ipv4;
700-
char *end;
705+
const char *end;
701706
int ip4elm[4];
702-
char *s = str;
707+
const char *s = str;
703708

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