forked from pool/python39
CVE-2025-4516 (bsc#1243273) blocking DecodeError handling
vulnerability, which could lead to DoS.
%%files.
- Use python3 modules to build the documentation.
* Support Expat >= 2.4.5
- allow build with Sphinx >= 3.x
* remove importlib_resources and importlib-metadata
- bpo-41304: Fixes python3x._pth being ignored on Windows, caused
- bpo-29778: Ensure python3.dll is loaded from correct locations
- bpo-39603: Prevent http header injection by rejecting control
“__setattr__” in a multi-inheritance setup and
- bpo-41247: Always cache the running loop holder when running
- bpo-41252: Fix incorrect refcounting in
- bpo-41215: Use non-NULL default values in the PEG parser
- bpo-41218: Python 3.8.3 had a regression where compiling with
ast.PyCF_ALLOW_TOP_LEVEL_AWAIT would
- bpo-41175: Guard against a NULL pointer dereference within
- bpo-39960: The “hackcheck” that prevents sneaking around a type’s
__setattr__() by calling the superclass method was
- bpo-41288: Unpickling invalid NEWOBJ_EX opcode with the
- bpo-39017: Avoid infinite loop when reading specially crafted
- bpo-41207: In distutils.spawn, restore expectation that
- bpo-41194: Fix a crash in the _ast module: it can no longer be
- bpo-39384: Fixed email.contentmanager to allow set_content() to set a
- bpo-41300: Save files with non-ascii chars.
- bpo-37765: Add keywords to module name completion list.
- bpo-40170: Revert PyType_HasFeature() change: it reads
again directly the PyTypeObject.tp_flags
member when the limited C API is not used, rather than always calling
OBS-URL: https://build.opensuse.org/package/show/devel:languages:python:Factory/python39?expand=0&rev=231
98 lines
4.9 KiB
Diff
98 lines
4.9 KiB
Diff
From 37bc08c699f48461be5e000b2da9212237a1ca0f Mon Sep 17 00:00:00 2001
|
|
From: JohnJamesUtley <jjutley231@gmail.com>
|
|
Date: Tue, 25 Apr 2023 16:01:03 -0400
|
|
Subject: [PATCH 1/4] Adds checks to ensure that bracketed hosts found by
|
|
urlsplit are of IPv6 or IPvFuture format
|
|
|
|
---
|
|
Lib/test/test_urlparse.py | 26 ++++++++++
|
|
Lib/urllib/parse.py | 16 +++++-
|
|
Misc/NEWS.d/next/Library/2023-04-26-09-54-25.gh-issue-103848.aDSnpR.rst | 2
|
|
3 files changed, 43 insertions(+), 1 deletion(-)
|
|
create mode 100644 Misc/NEWS.d/next/Library/2023-04-26-09-54-25.gh-issue-103848.aDSnpR.rst
|
|
|
|
--- a/Lib/test/test_urlparse.py
|
|
+++ b/Lib/test/test_urlparse.py
|
|
@@ -1135,6 +1135,32 @@ class UrlParseTestCase(unittest.TestCase
|
|
self.assertEqual(p2.scheme, 'tel')
|
|
self.assertEqual(p2.path, '+31641044153')
|
|
|
|
+ def test_invalid_bracketed_hosts(self):
|
|
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[192.0.2.146]/Path?Query')
|
|
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[important.com:8000]/Path?Query')
|
|
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v123r.IP]/Path?Query')
|
|
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v12ae]/Path?Query')
|
|
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v.IP]/Path?Query')
|
|
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v123.]/Path?Query')
|
|
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[v]/Path?Query')
|
|
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[0439:23af::2309::fae7:1234]/Path?Query')
|
|
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[0439:23af:2309::fae7:1234:2342:438e:192.0.2.146]/Path?Query')
|
|
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@]v6a.ip[/Path')
|
|
+
|
|
+ def test_splitting_bracketed_hosts(self):
|
|
+ p1 = urllib.parse.urlsplit('scheme://user@[v6a.ip]/path?query')
|
|
+ self.assertEqual(p1.hostname, 'v6a.ip')
|
|
+ self.assertEqual(p1.username, 'user')
|
|
+ self.assertEqual(p1.path, '/path')
|
|
+ p2 = urllib.parse.urlsplit('scheme://user@[0439:23af:2309::fae7%test]/path?query')
|
|
+ self.assertEqual(p2.hostname, '0439:23af:2309::fae7%test')
|
|
+ self.assertEqual(p2.username, 'user')
|
|
+ self.assertEqual(p2.path, '/path')
|
|
+ p3 = urllib.parse.urlsplit('scheme://user@[0439:23af:2309::fae7:1234:192.0.2.146%test]/path?query')
|
|
+ self.assertEqual(p3.hostname, '0439:23af:2309::fae7:1234:192.0.2.146%test')
|
|
+ self.assertEqual(p3.username, 'user')
|
|
+ self.assertEqual(p3.path, '/path')
|
|
+
|
|
def test_port_casting_failure_message(self):
|
|
message = "Port could not be cast to integer value as 'oracle'"
|
|
p1 = urllib.parse.urlparse('http://Server=sde; Service=sde:oracle')
|
|
--- a/Lib/urllib/parse.py
|
|
+++ b/Lib/urllib/parse.py
|
|
@@ -36,6 +36,7 @@ import sys
|
|
import types
|
|
import collections
|
|
import warnings
|
|
+import ipaddress
|
|
|
|
__all__ = ["urlparse", "urlunparse", "urljoin", "urldefrag",
|
|
"urlsplit", "urlunsplit", "urlencode", "parse_qs",
|
|
@@ -442,6 +443,17 @@ def _checknetloc(netloc):
|
|
raise ValueError("netloc '" + netloc + "' contains invalid " +
|
|
"characters under NFKC normalization")
|
|
|
|
+# Valid bracketed hosts are defined in
|
|
+# https://www.rfc-editor.org/rfc/rfc3986#page-49 and https://url.spec.whatwg.org/
|
|
+def _check_bracketed_host(hostname):
|
|
+ if hostname.startswith('v'):
|
|
+ if not re.match(r"\Av[a-fA-F0-9]+\..+\Z", hostname):
|
|
+ raise ValueError(f"IPvFuture address is invalid")
|
|
+ else:
|
|
+ ip = ipaddress.ip_address(hostname) # Throws Value Error if not IPv6 or IPv4
|
|
+ if isinstance(ip, ipaddress.IPv4Address):
|
|
+ raise ValueError(f"An IPv4 address cannot be in brackets")
|
|
+
|
|
def urlsplit(url, scheme='', allow_fragments=True):
|
|
"""Parse a URL into 5 components:
|
|
<scheme>://<netloc>/<path>?<query>#<fragment>
|
|
@@ -488,12 +500,14 @@ def urlsplit(url, scheme='', allow_fragm
|
|
break
|
|
else:
|
|
scheme, url = url[:i].lower(), url[i+1:]
|
|
-
|
|
if url[:2] == '//':
|
|
netloc, url = _splitnetloc(url, 2)
|
|
if (('[' in netloc and ']' not in netloc) or
|
|
(']' in netloc and '[' not in netloc)):
|
|
raise ValueError("Invalid IPv6 URL")
|
|
+ if '[' in netloc and ']' in netloc:
|
|
+ bracketed_host = netloc.partition('[')[2].partition(']')[0]
|
|
+ _check_bracketed_host(bracketed_host)
|
|
if allow_fragments and '#' in url:
|
|
url, fragment = url.split('#', 1)
|
|
if '?' in url:
|
|
--- /dev/null
|
|
+++ b/Misc/NEWS.d/next/Library/2023-04-26-09-54-25.gh-issue-103848.aDSnpR.rst
|
|
@@ -0,0 +1,2 @@
|
|
+Add checks to ensure that ``[`` bracketed ``]`` hosts found by
|
|
+:func:`urllib.parse.urlsplit` are of IPv6 or IPvFuture format.
|