Fixed #33367 -- Fixed URLValidator crash in some edge cases.

This commit is contained in:
mendespedro 2021-12-15 11:55:19 -03:00 committed by Mariusz Felisiak
parent 4fd3044ca0
commit e8b4feddc3
2 changed files with 11 additions and 6 deletions

View File

@ -108,15 +108,16 @@ class URLValidator(RegexValidator):
raise ValidationError(self.message, code=self.code, params={'value': value}) raise ValidationError(self.message, code=self.code, params={'value': value})
# Then check full URL # Then check full URL
try:
splitted_url = urlsplit(value)
except ValueError:
raise ValidationError(self.message, code=self.code, params={'value': value})
try: try:
super().__call__(value) super().__call__(value)
except ValidationError as e: except ValidationError as e:
# Trivial case failed. Try for possible IDN domain # Trivial case failed. Try for possible IDN domain
if value: if value:
try: scheme, netloc, path, query, fragment = splitted_url
scheme, netloc, path, query, fragment = urlsplit(value)
except ValueError: # for example, "Invalid IPv6 URL"
raise ValidationError(self.message, code=self.code, params={'value': value})
try: try:
netloc = punycode(netloc) # IDN -> ACE netloc = punycode(netloc) # IDN -> ACE
except UnicodeError: # invalid domain part except UnicodeError: # invalid domain part
@ -127,7 +128,7 @@ class URLValidator(RegexValidator):
raise raise
else: else:
# Now verify IPv6 in the netloc part # Now verify IPv6 in the netloc part
host_match = re.search(r'^\[(.+)\](?::\d{1,5})?$', urlsplit(value).netloc) host_match = re.search(r'^\[(.+)\](?::\d{1,5})?$', splitted_url.netloc)
if host_match: if host_match:
potential_ip = host_match[1] potential_ip = host_match[1]
try: try:
@ -139,7 +140,7 @@ class URLValidator(RegexValidator):
# section 3.1. It's defined to be 255 bytes or less, but this includes # section 3.1. It's defined to be 255 bytes or less, but this includes
# one byte for the length of the name and one byte for the trailing dot # one byte for the length of the name and one byte for the trailing dot
# that's used to indicate absolute names in DNS. # that's used to indicate absolute names in DNS.
if len(urlsplit(value).hostname) > 253: if splitted_url.hostname is None or len(splitted_url.hostname) > 253:
raise ValidationError(self.message, code=self.code, params={'value': value}) raise ValidationError(self.message, code=self.code, params={'value': value})

View File

@ -100,6 +100,10 @@ class URLFieldTest(FormFieldAssertionsMixin, SimpleTestCase):
# even on domains that don't fail the domain label length check in # even on domains that don't fail the domain label length check in
# the regex. # the regex.
'http://%s' % ("X" * 200,), 'http://%s' % ("X" * 200,),
# urlsplit() raises ValueError.
'////]@N.AN',
# Empty hostname.
'#@A.bO',
] ]
msg = "'Enter a valid URL.'" msg = "'Enter a valid URL.'"
for value in tests: for value in tests: