Skip to content

Commit 76362f9

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)
1 parent fbeed18 commit 76362f9

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
@@ -79,7 +79,7 @@
7979
#define FORMAT_IPV4 4
8080
#define FORMAT_IPV6 6
8181

82-
static int _php_filter_validate_ipv6(char *str, size_t str_len);
82+
static int _php_filter_validate_ipv6(const char *str, size_t str_len);
8383

8484
static int php_filter_parse_int(const char *str, size_t str_len, zend_long *ret) { /* {{{ */
8585
zend_long ctx_value;
@@ -548,6 +548,14 @@ static int is_userinfo_valid(zend_string *str)
548548
return 1;
549549
}
550550

551+
static zend_bool php_filter_is_valid_ipv6_hostname(const char *s, size_t l)
552+
{
553+
const char *e = s + l;
554+
const char *t = e - 1;
555+
556+
return *s == '[' && *t == ']' && _php_filter_validate_ipv6(s + 1, l - 2);
557+
}
558+
551559
void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
552560
{
553561
php_url *url;
@@ -573,7 +581,7 @@ void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
573581

574582
if (url->scheme != NULL &&
575583
(zend_string_equals_literal_ci(url->scheme, "http") || zend_string_equals_literal_ci(url->scheme, "https"))) {
576-
char *e, *s, *t;
584+
const char *s;
577585
size_t l;
578586

579587
if (url->host == NULL) {
@@ -582,17 +590,14 @@ void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
582590

583591
s = ZSTR_VAL(url->host);
584592
l = ZSTR_LEN(url->host);
585-
e = s + l;
586-
t = e - 1;
587-
588-
/* An IPv6 enclosed by square brackets is a valid hostname */
589-
if (*s == '[' && *t == ']' && _php_filter_validate_ipv6((s + 1), l - 2)) {
590-
php_url_free(url);
591-
return;
592-
}
593593

594-
// Validate domain
595-
if (!_php_filter_validate_domain(ZSTR_VAL(url->host), l, FILTER_FLAG_HOSTNAME)) {
594+
if (
595+
/* An IPv6 enclosed by square brackets is a valid hostname.*/
596+
!php_filter_is_valid_ipv6_hostname(s, l) &&
597+
/* Validate domain.
598+
* This includes a loose check for an IPv4 address. */
599+
!_php_filter_validate_domain(ZSTR_VAL(url->host), l, FILTER_FLAG_HOSTNAME)
600+
) {
596601
php_url_free(url);
597602
RETURN_VALIDATION_FAILED
598603
}
@@ -726,15 +731,15 @@ static int _php_filter_validate_ipv4(char *str, size_t str_len, int *ip) /* {{{
726731
}
727732
/* }}} */
728733

729-
static int _php_filter_validate_ipv6(char *str, size_t str_len) /* {{{ */
734+
static int _php_filter_validate_ipv6(const char *str, size_t str_len) /* {{{ */
730735
{
731736
int compressed = 0;
732737
int blocks = 0;
733738
int n;
734739
char *ipv4;
735-
char *end;
740+
const char *end;
736741
int ip4elm[4];
737-
char *s = str;
742+
const char *s = str;
738743

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