Fixed #33367 -- Fixed URLValidator crash in some edge cases.
This commit is contained in:
parent
4fd3044ca0
commit
e8b4feddc3
|
@ -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})
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in New Issue