Compare commits

...

10 Commits

Author SHA1 Message Date
openeuler-ci-bot
f2daa992e9
!413 fix CVE-2025-0938
From: @fundawang 
Reviewed-by: @yangyuan32 
Signed-off-by: @yangyuan32
2025-02-14 04:02:56 +00:00
Funda Wang
566cb3e5c1 fix CVE-2025-0938 2025-02-11 18:01:22 +08:00
openeuler-ci-bot
ed4eb3373d
!409 fix CVE-2024-11168
From: @xinsheng3 
Reviewed-by: @jack0240, @yangyuan32 
Signed-off-by: @yangyuan32
2024-12-25 08:29:45 +00:00
xinsheng3
89007601cc fix CVE-2024-11168 2024-12-25 15:01:59 +08:00
openeuler-ci-bot
dded90a5bc
!401 完善加密算法测试用例
From: @fuowang 
Reviewed-by: @yangyuan32 
Signed-off-by: @yangyuan32
2024-12-11 07:43:18 +00:00
wangshuo
5bc71843bd support TLS_SM4 2024-12-11 01:18:51 +08:00
openeuler-ci-bot
3a962a5013
!380 fix CVE-2024-9287
From: @fundawang 
Reviewed-by: @yangyuan32 
Signed-off-by: @yangyuan32
2024-11-22 09:07:52 +00:00
Funda Wang
6386f10883 fix CVE-2024-9287 2024-11-12 15:39:23 +08:00
openeuler-ci-bot
131ee7867c
!369 gh-107845: Fix symlink handling for tarfile.data_filter
From: @fuowang 
Reviewed-by: @dillon_chen 
Signed-off-by: @dillon_chen
2024-10-30 08:18:07 +00:00
wangshuo
039b4734e6 gh-107845: Fix symlink handling for tarfile.data_filter 2024-10-29 11:24:33 +08:00
6 changed files with 959 additions and 45 deletions

View File

@ -0,0 +1,24 @@
From 273a81e603e97af08186d697023182723aa2d69d Mon Sep 17 00:00:00 2001
From: wangshuo <wangshuo@kylinos.cn>
Date: Wed, 11 Dec 2024 01:15:08 +0800
Subject: [PATCH] expected_algs list to include TLS_SM4
---
Lib/test/test_ssl.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
index d95f0ef..775fc80 100644
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -4305,6 +4305,7 @@ class ThreadedTests(unittest.TestCase):
"AES256", "AES-256",
# TLS 1.3 ciphers are always enabled
"TLS_CHACHA20", "TLS_AES",
+ "TLS_SM4",
]
stats = server_params_test(client_context, server_context,
--
2.43.0

View File

@ -0,0 +1,302 @@
From 42deeab5b2efc2930d4eb73416e1dde9cf790dd2 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <encukou@gmail.com>
Date: Tue, 22 Aug 2023 20:28:10 +0200
Subject: [PATCH] [3.9] gh-107845: Fix symlink handling for tarfile.data_filter
(GH-107846) (#108274)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
(cherry picked from commit acbd3f9c5c5f23e95267714e41236140d84fe962)
Co-authored-by: Petr Viktorin <encukou@gmail.com>
Co-authored-by: Victor Stinner <vstinner@python.org>
Co-authored-by: Lumír 'Frenzy' Balhar <frenzy.madness@gmail.com>
---
Doc/library/tarfile.rst | 5 +
Lib/tarfile.py | 11 +-
Lib/test/test_tarfile.py | 144 +++++++++++++++++-
...-08-10-17-36-22.gh-issue-107845.dABiMJ.rst | 3 +
4 files changed, 154 insertions(+), 9 deletions(-)
create mode 100644 Misc/NEWS.d/next/Library/2023-08-10-17-36-22.gh-issue-107845.dABiMJ.rst
diff --git a/Doc/library/tarfile.rst b/Doc/library/tarfile.rst
index f1d9bd34536..165088529a8 100644
--- a/Doc/library/tarfile.rst
+++ b/Doc/library/tarfile.rst
@@ -732,6 +732,11 @@ A ``TarInfo`` object has the following public data attributes:
Name of the target file name, which is only present in :class:`TarInfo` objects
of type :const:`LNKTYPE` and :const:`SYMTYPE`.
+ For symbolic links (``SYMTYPE``), the *linkname* is relative to the directory
+ that contains the link.
+ For hard links (``LNKTYPE``), the *linkname* is relative to the root of
+ the archive.
+
.. attribute:: TarInfo.uid
:type: int
diff --git a/Lib/tarfile.py b/Lib/tarfile.py
index b6ad7dbe2a4..7a6158c2eb9 100755
--- a/Lib/tarfile.py
+++ b/Lib/tarfile.py
@@ -740,7 +740,7 @@ class SpecialFileError(FilterError):
class AbsoluteLinkError(FilterError):
def __init__(self, tarinfo):
self.tarinfo = tarinfo
- super().__init__(f'{tarinfo.name!r} is a symlink to an absolute path')
+ super().__init__(f'{tarinfo.name!r} is a link to an absolute path')
class LinkOutsideDestinationError(FilterError):
def __init__(self, tarinfo, path):
@@ -800,7 +800,14 @@ def _get_filtered_attrs(member, dest_path, for_data=True):
if member.islnk() or member.issym():
if os.path.isabs(member.linkname):
raise AbsoluteLinkError(member)
- target_path = os.path.realpath(os.path.join(dest_path, member.linkname))
+ if member.issym():
+ target_path = os.path.join(dest_path,
+ os.path.dirname(name),
+ member.linkname)
+ else:
+ target_path = os.path.join(dest_path,
+ member.linkname)
+ target_path = os.path.realpath(target_path)
if os.path.commonpath([target_path, dest_path]) != dest_path:
raise LinkOutsideDestinationError(member, target_path)
return new_attrs
diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
index a66f7efd2d6..3df64c78032 100644
--- a/Lib/test/test_tarfile.py
+++ b/Lib/test/test_tarfile.py
@@ -3169,10 +3169,12 @@ class ArchiveMaker:
self.bio = None
def add(self, name, *, type=None, symlink_to=None, hardlink_to=None,
- mode=None, **kwargs):
+ mode=None, size=None, **kwargs):
"""Add a member to the test archive. Call within `with`."""
name = str(name)
tarinfo = tarfile.TarInfo(name).replace(**kwargs)
+ if size is not None:
+ tarinfo.size = size
if mode:
tarinfo.mode = _filemode_to_int(mode)
if symlink_to is not None:
@@ -3236,7 +3238,8 @@ class TestExtractionFilters(unittest.TestCase):
raise self.raised_exception
self.assertEqual(self.expected_paths, set())
- def expect_file(self, name, type=None, symlink_to=None, mode=None):
+ def expect_file(self, name, type=None, symlink_to=None, mode=None,
+ size=None):
"""Check a single file. See check_context."""
if self.raised_exception:
raise self.raised_exception
@@ -3270,6 +3273,8 @@ class TestExtractionFilters(unittest.TestCase):
self.assertTrue(path.is_fifo())
else:
raise NotImplementedError(type)
+ if size is not None:
+ self.assertEqual(path.stat().st_size, size)
for parent in path.parents:
self.expected_paths.discard(parent)
@@ -3315,8 +3320,15 @@ class TestExtractionFilters(unittest.TestCase):
# Test interplaying symlinks
# Inspired by 'dirsymlink2a' in jwilk/traversal-archives
with ArchiveMaker() as arc:
+
+ # `current` links to `.` which is both:
+ # - the destination directory
+ # - `current` itself
arc.add('current', symlink_to='.')
+
+ # effectively points to ./../
arc.add('parent', symlink_to='current/..')
+
arc.add('parent/evil')
if support.can_symlink():
@@ -3357,9 +3369,46 @@ class TestExtractionFilters(unittest.TestCase):
def test_parent_symlink2(self):
# Test interplaying symlinks
# Inspired by 'dirsymlink2b' in jwilk/traversal-archives
+
+ # Posix and Windows have different pathname resolution:
+ # either symlink or a '..' component resolve first.
+ # Let's see which we are on.
+ if support.can_symlink():
+ testpath = os.path.join(TEMPDIR, 'resolution_test')
+ os.mkdir(testpath)
+
+ # testpath/current links to `.` which is all of:
+ # - `testpath`
+ # - `testpath/current`
+ # - `testpath/current/current`
+ # - etc.
+ os.symlink('.', os.path.join(testpath, 'current'))
+
+ # we'll test where `testpath/current/../file` ends up
+ with open(os.path.join(testpath, 'current', '..', 'file'), 'w'):
+ pass
+
+ if os.path.exists(os.path.join(testpath, 'file')):
+ # Windows collapses 'current\..' to '.' first, leaving
+ # 'testpath\file'
+ dotdot_resolves_early = True
+ elif os.path.exists(os.path.join(testpath, '..', 'file')):
+ # Posix resolves 'current' to '.' first, leaving
+ # 'testpath/../file'
+ dotdot_resolves_early = False
+ else:
+ raise AssertionError('Could not determine link resolution')
+
with ArchiveMaker() as arc:
+
+ # `current` links to `.` which is both the destination directory
+ # and `current` itself
arc.add('current', symlink_to='.')
+
+ # `current/parent` is also available as `./parent`,
+ # and effectively points to `./../`
arc.add('current/parent', symlink_to='..')
+
arc.add('parent/evil')
with self.check_context(arc.open(), 'fully_trusted'):
@@ -3373,6 +3422,7 @@ class TestExtractionFilters(unittest.TestCase):
with self.check_context(arc.open(), 'tar'):
if support.can_symlink():
+ # Fail when extracting a file outside destination
self.expect_exception(
tarfile.OutsideDestinationError,
"'parent/evil' would be extracted to "
@@ -3383,10 +3433,24 @@ class TestExtractionFilters(unittest.TestCase):
self.expect_file('parent/evil')
with self.check_context(arc.open(), 'data'):
- self.expect_exception(
- tarfile.LinkOutsideDestinationError,
- """'current/parent' would link to ['"].*['"], """
- + "which is outside the destination")
+ if support.can_symlink():
+ if dotdot_resolves_early:
+ # Fail when extracting a file outside destination
+ self.expect_exception(
+ tarfile.OutsideDestinationError,
+ "'parent/evil' would be extracted to "
+ + """['"].*evil['"], which is outside """
+ + "the destination")
+ else:
+ # Fail as soon as we have a symlink outside the destination
+ self.expect_exception(
+ tarfile.LinkOutsideDestinationError,
+ "'current/parent' would link to "
+ + """['"].*outerdir['"], which is outside """
+ + "the destination")
+ else:
+ self.expect_file('current/')
+ self.expect_file('parent/evil')
def test_absolute_symlink(self):
# Test symlink to an absolute path
@@ -3415,11 +3479,29 @@ class TestExtractionFilters(unittest.TestCase):
with self.check_context(arc.open(), 'data'):
self.expect_exception(
tarfile.AbsoluteLinkError,
- "'parent' is a symlink to an absolute path")
+ "'parent' is a link to an absolute path")
+
+ def test_absolute_hardlink(self):
+ # Test hardlink to an absolute path
+ # Inspired by 'dirsymlink' in https://github.com/jwilk/traversal-archives
+ with ArchiveMaker() as arc:
+ arc.add('parent', hardlink_to=self.outerdir / 'foo')
+
+ with self.check_context(arc.open(), 'fully_trusted'):
+ self.expect_exception(KeyError, ".*foo. not found")
+
+ with self.check_context(arc.open(), 'tar'):
+ self.expect_exception(KeyError, ".*foo. not found")
+
+ with self.check_context(arc.open(), 'data'):
+ self.expect_exception(
+ tarfile.AbsoluteLinkError,
+ "'parent' is a link to an absolute path")
def test_sly_relative0(self):
# Inspired by 'relative0' in jwilk/traversal-archives
with ArchiveMaker() as arc:
+ # points to `../../tmp/moo`
arc.add('../moo', symlink_to='..//tmp/moo')
try:
@@ -3469,6 +3551,54 @@ class TestExtractionFilters(unittest.TestCase):
+ """['"].*moo['"], which is outside the """
+ "destination")
+ def test_deep_symlink(self):
+ # Test that symlinks and hardlinks inside a directory
+ # point to the correct file (`target` of size 3).
+ # If links aren't supported we get a copy of the file.
+ with ArchiveMaker() as arc:
+ arc.add('targetdir/target', size=3)
+ # a hardlink's linkname is relative to the archive
+ arc.add('linkdir/hardlink', hardlink_to=os.path.join(
+ 'targetdir', 'target'))
+ # a symlink's linkname is relative to the link's directory
+ arc.add('linkdir/symlink', symlink_to=os.path.join(
+ '..', 'targetdir', 'target'))
+
+ for filter in 'tar', 'data', 'fully_trusted':
+ with self.check_context(arc.open(), filter):
+ self.expect_file('targetdir/target', size=3)
+ self.expect_file('linkdir/hardlink', size=3)
+ if support.can_symlink():
+ self.expect_file('linkdir/symlink', size=3,
+ symlink_to='../targetdir/target')
+ else:
+ self.expect_file('linkdir/symlink', size=3)
+
+ def test_chains(self):
+ # Test chaining of symlinks/hardlinks.
+ # Symlinks are created before the files they point to.
+ with ArchiveMaker() as arc:
+ arc.add('linkdir/symlink', symlink_to='hardlink')
+ arc.add('symlink2', symlink_to=os.path.join(
+ 'linkdir', 'hardlink2'))
+ arc.add('targetdir/target', size=3)
+ arc.add('linkdir/hardlink', hardlink_to='targetdir/target')
+ arc.add('linkdir/hardlink2', hardlink_to='linkdir/symlink')
+
+ for filter in 'tar', 'data', 'fully_trusted':
+ with self.check_context(arc.open(), filter):
+ self.expect_file('targetdir/target', size=3)
+ self.expect_file('linkdir/hardlink', size=3)
+ self.expect_file('linkdir/hardlink2', size=3)
+ if support.can_symlink():
+ self.expect_file('linkdir/symlink', size=3,
+ symlink_to='hardlink')
+ self.expect_file('symlink2', size=3,
+ symlink_to='linkdir/hardlink2')
+ else:
+ self.expect_file('linkdir/symlink', size=3)
+ self.expect_file('symlink2', size=3)
+
def test_modes(self):
# Test how file modes are extracted
# (Note that the modes are ignored on platforms without working chmod)
diff --git a/Misc/NEWS.d/next/Library/2023-08-10-17-36-22.gh-issue-107845.dABiMJ.rst b/Misc/NEWS.d/next/Library/2023-08-10-17-36-22.gh-issue-107845.dABiMJ.rst
new file mode 100644
index 00000000000..32c1fb93f4a
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-08-10-17-36-22.gh-issue-107845.dABiMJ.rst
@@ -0,0 +1,3 @@
+:func:`tarfile.data_filter` now takes the location of symlinks into account
+when determining their target, so it will no longer reject some valid
+tarballs with ``LinkOutsideDestinationError``.
--
2.25.1

View File

@ -0,0 +1,111 @@
From ddca2953191c67a12b1f19d6bca41016c6ae7132 Mon Sep 17 00:00:00 2001
From: Victor Stinner <vstinner@python.org>
Date: Mon, 2 Dec 2024 13:36:46 +0100
Subject: [PATCH] [3.9] gh-103848: Adds checks to ensure that bracketed hosts
found by urlsplit are of IPv6 or IPvFuture format (#103849) (#126976)
Co-authored-by: Gregory P. Smith <greg@krypto.org>
(cherry picked from commit 29f348e232e82938ba2165843c448c2b291504c5)
Co-authored-by: JohnJamesUtley <81572567+JohnJamesUtley@users.noreply.github.com>
---
Lib/test/test_urlparse.py | 26 +++++++++++++++++++
Lib/urllib/parse.py | 16 +++++++++++-
...-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
diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py
index b862711e414..6f7d40c2125 100644
--- 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')
diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py
index 4a24f7eb5e4..9d37dcaa904 100644
--- 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_fragments=True):
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:
diff --git a/Misc/NEWS.d/next/Library/2023-04-26-09-54-25.gh-issue-103848.aDSnpR.rst b/Misc/NEWS.d/next/Library/2023-04-26-09-54-25.gh-issue-103848.aDSnpR.rst
new file mode 100644
index 00000000000..81e5904aa6c
--- /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.
--
2.33.0

View File

@ -0,0 +1,297 @@
From 633555735a023d3e4d92ba31da35b1205f9ecbd7 Mon Sep 17 00:00:00 2001
From: Victor Stinner <vstinner@python.org>
Date: Mon, 4 Nov 2024 16:16:35 +0100
Subject: [PATCH] [3.9] gh-124651: Quote template strings in `venv` activation
scripts (GH-124712) (GH-126185) (GH-126269) (GH-126301)
(cherry picked from commit ae961ae94bf19c8f8c7fbea3d1c25cc55ce8ae97)
---
Lib/test/test_venv.py | 81 +++++++++++++++++++
Lib/venv/__init__.py | 42 ++++++++--
Lib/venv/scripts/common/activate | 6 +-
Lib/venv/scripts/nt/activate.bat | 4 +-
Lib/venv/scripts/posix/activate.csh | 6 +-
Lib/venv/scripts/posix/activate.fish | 6 +-
...-09-28-02-03-04.gh-issue-124651.bLBGtH.rst | 1 +
7 files changed, 130 insertions(+), 16 deletions(-)
create mode 100644 Misc/NEWS.d/next/Library/2024-09-28-02-03-04.gh-issue-124651.bLBGtH.rst
diff --git a/Lib/test/test_venv.py b/Lib/test/test_venv.py
index 480cb29f35a6a4..871b8314b90b05 100644
--- a/Lib/test/test_venv.py
+++ b/Lib/test/test_venv.py
@@ -14,6 +14,7 @@
import subprocess
import sys
import tempfile
+import shlex
from test.support import (captured_stdout, captured_stderr, requires_zlib,
can_symlink, EnvironmentVarGuard, rmtree,
import_module,
@@ -85,6 +86,10 @@ def get_text_file_contents(self, *args, encoding='utf-8'):
result = f.read()
return result
+ def assertEndsWith(self, string, tail):
+ if not string.endswith(tail):
+ self.fail(f"String {string!r} does not end with {tail!r}")
+
class BasicTest(BaseTest):
"""Test venv module functionality."""
@@ -342,6 +347,82 @@ def test_executable_symlinks(self):
'import sys; print(sys.executable)'])
self.assertEqual(out.strip(), envpy.encode())
+ # gh-124651: test quoted strings
+ @unittest.skipIf(os.name == 'nt', 'contains invalid characters on Windows')
+ def test_special_chars_bash(self):
+ """
+ Test that the template strings are quoted properly (bash)
+ """
+ rmtree(self.env_dir)
+ bash = shutil.which('bash')
+ if bash is None:
+ self.skipTest('bash required for this test')
+ env_name = '"\';&&$e|\'"'
+ env_dir = os.path.join(os.path.realpath(self.env_dir), env_name)
+ builder = venv.EnvBuilder(clear=True)
+ builder.create(env_dir)
+ activate = os.path.join(env_dir, self.bindir, 'activate')
+ test_script = os.path.join(self.env_dir, 'test_special_chars.sh')
+ with open(test_script, "w") as f:
+ f.write(f'source {shlex.quote(activate)}\n'
+ 'python -c \'import sys; print(sys.executable)\'\n'
+ 'python -c \'import os; print(os.environ["VIRTUAL_ENV"])\'\n'
+ 'deactivate\n')
+ out, err = check_output([bash, test_script])
+ lines = out.splitlines()
+ self.assertTrue(env_name.encode() in lines[0])
+ self.assertEndsWith(lines[1], env_name.encode())
+
+ # gh-124651: test quoted strings
+ @unittest.skipIf(os.name == 'nt', 'contains invalid characters on Windows')
+ def test_special_chars_csh(self):
+ """
+ Test that the template strings are quoted properly (csh)
+ """
+ rmtree(self.env_dir)
+ csh = shutil.which('tcsh') or shutil.which('csh')
+ if csh is None:
+ self.skipTest('csh required for this test')
+ env_name = '"\';&&$e|\'"'
+ env_dir = os.path.join(os.path.realpath(self.env_dir), env_name)
+ builder = venv.EnvBuilder(clear=True)
+ builder.create(env_dir)
+ activate = os.path.join(env_dir, self.bindir, 'activate.csh')
+ test_script = os.path.join(self.env_dir, 'test_special_chars.csh')
+ with open(test_script, "w") as f:
+ f.write(f'source {shlex.quote(activate)}\n'
+ 'python -c \'import sys; print(sys.executable)\'\n'
+ 'python -c \'import os; print(os.environ["VIRTUAL_ENV"])\'\n'
+ 'deactivate\n')
+ out, err = check_output([csh, test_script])
+ lines = out.splitlines()
+ self.assertTrue(env_name.encode() in lines[0])
+ self.assertEndsWith(lines[1], env_name.encode())
+
+ # gh-124651: test quoted strings on Windows
+ @unittest.skipUnless(os.name == 'nt', 'only relevant on Windows')
+ def test_special_chars_windows(self):
+ """
+ Test that the template strings are quoted properly on Windows
+ """
+ rmtree(self.env_dir)
+ env_name = "'&&^$e"
+ env_dir = os.path.join(os.path.realpath(self.env_dir), env_name)
+ builder = venv.EnvBuilder(clear=True)
+ builder.create(env_dir)
+ activate = os.path.join(env_dir, self.bindir, 'activate.bat')
+ test_batch = os.path.join(self.env_dir, 'test_special_chars.bat')
+ with open(test_batch, "w") as f:
+ f.write('@echo off\n'
+ f'"{activate}" & '
+ f'{self.exe} -c "import sys; print(sys.executable)" & '
+ f'{self.exe} -c "import os; print(os.environ[\'VIRTUAL_ENV\'])" & '
+ 'deactivate')
+ out, err = check_output([test_batch])
+ lines = out.splitlines()
+ self.assertTrue(env_name.encode() in lines[0])
+ self.assertEndsWith(lines[1], env_name.encode())
+
@unittest.skipUnless(os.name == 'nt', 'only relevant on Windows')
def test_unicode_in_batch_file(self):
"""
diff --git a/Lib/venv/__init__.py b/Lib/venv/__init__.py
index 6f1af294ae63e3..299633117e6fbe 100644
--- a/Lib/venv/__init__.py
+++ b/Lib/venv/__init__.py
@@ -11,6 +11,7 @@
import sys
import sysconfig
import types
+import shlex
CORE_VENV_DEPS = ('pip', 'setuptools')
@@ -348,11 +349,41 @@ def replace_variables(self, text, context):
:param context: The information for the environment creation request
being processed.
"""
- text = text.replace('__VENV_DIR__', context.env_dir)
- text = text.replace('__VENV_NAME__', context.env_name)
- text = text.replace('__VENV_PROMPT__', context.prompt)
- text = text.replace('__VENV_BIN_NAME__', context.bin_name)
- text = text.replace('__VENV_PYTHON__', context.env_exe)
+ replacements = {
+ '__VENV_DIR__': context.env_dir,
+ '__VENV_NAME__': context.env_name,
+ '__VENV_PROMPT__': context.prompt,
+ '__VENV_BIN_NAME__': context.bin_name,
+ '__VENV_PYTHON__': context.env_exe,
+ }
+
+ def quote_ps1(s):
+ """
+ This should satisfy PowerShell quoting rules [1], unless the quoted
+ string is passed directly to Windows native commands [2].
+ [1]: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_quoting_rules
+ [2]: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_parsing#passing-arguments-that-contain-quote-characters
+ """
+ s = s.replace("'", "''")
+ return f"'{s}'"
+
+ def quote_bat(s):
+ return s
+
+ # gh-124651: need to quote the template strings properly
+ quote = shlex.quote
+ script_path = context.script_path
+ if script_path.endswith('.ps1'):
+ quote = quote_ps1
+ elif script_path.endswith('.bat'):
+ quote = quote_bat
+ else:
+ # fallbacks to POSIX shell compliant quote
+ quote = shlex.quote
+
+ replacements = {key: quote(s) for key, s in replacements.items()}
+ for key, quoted in replacements.items():
+ text = text.replace(key, quoted)
return text
def install_scripts(self, context, path):
@@ -392,6 +423,7 @@ def install_scripts(self, context, path):
with open(srcfile, 'rb') as f:
data = f.read()
if not srcfile.endswith(('.exe', '.pdb')):
+ context.script_path = srcfile
try:
data = data.decode('utf-8')
data = self.replace_variables(data, context)
diff --git a/Lib/venv/scripts/common/activate b/Lib/venv/scripts/common/activate
index 45af3536aa191d..1d116ca6eda4ed 100644
--- a/Lib/venv/scripts/common/activate
+++ b/Lib/venv/scripts/common/activate
@@ -37,11 +37,11 @@ deactivate () {
# unset irrelevant variables
deactivate nondestructive
-VIRTUAL_ENV="__VENV_DIR__"
+VIRTUAL_ENV=__VENV_DIR__
export VIRTUAL_ENV
_OLD_VIRTUAL_PATH="$PATH"
-PATH="$VIRTUAL_ENV/__VENV_BIN_NAME__:$PATH"
+PATH="$VIRTUAL_ENV/"__VENV_BIN_NAME__":$PATH"
export PATH
# unset PYTHONHOME if set
@@ -54,7 +54,7 @@ fi
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
_OLD_VIRTUAL_PS1="${PS1:-}"
- PS1="__VENV_PROMPT__${PS1:-}"
+ PS1=__VENV_PROMPT__"${PS1:-}"
export PS1
fi
diff --git a/Lib/venv/scripts/nt/activate.bat b/Lib/venv/scripts/nt/activate.bat
index af4c7e0abacb1c..5ca475a6e81879 100644
--- a/Lib/venv/scripts/nt/activate.bat
+++ b/Lib/venv/scripts/nt/activate.bat
@@ -8,7 +8,7 @@
"%SystemRoot%\System32\chcp.com" 65001 > nul
)
-set VIRTUAL_ENV=__VENV_DIR__
+set "VIRTUAL_ENV=__VENV_DIR__"
if not defined PROMPT set PROMPT=$P$G
@@ -24,7 +24,7 @@
if defined _OLD_VIRTUAL_PATH set PATH=%_OLD_VIRTUAL_PATH%
if not defined _OLD_VIRTUAL_PATH set _OLD_VIRTUAL_PATH=%PATH%
-set PATH=%VIRTUAL_ENV%\__VENV_BIN_NAME__;%PATH%
+set "PATH=%VIRTUAL_ENV%\__VENV_BIN_NAME__;%PATH%"
:END
if defined _OLD_CODEPAGE (
diff --git a/Lib/venv/scripts/posix/activate.csh b/Lib/venv/scripts/posix/activate.csh
index 68a0dc74e1a3c7..51301139517f10 100644
--- a/Lib/venv/scripts/posix/activate.csh
+++ b/Lib/venv/scripts/posix/activate.csh
@@ -8,16 +8,16 @@ alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PA
# Unset irrelevant variables.
deactivate nondestructive
-setenv VIRTUAL_ENV "__VENV_DIR__"
+setenv VIRTUAL_ENV __VENV_DIR__
set _OLD_VIRTUAL_PATH="$PATH"
-setenv PATH "$VIRTUAL_ENV/__VENV_BIN_NAME__:$PATH"
+setenv PATH "$VIRTUAL_ENV/"__VENV_BIN_NAME__":$PATH"
set _OLD_VIRTUAL_PROMPT="$prompt"
if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
- set prompt = "__VENV_PROMPT__$prompt"
+ set prompt = __VENV_PROMPT__"$prompt"
endif
alias pydoc python -m pydoc
diff --git a/Lib/venv/scripts/posix/activate.fish b/Lib/venv/scripts/posix/activate.fish
index 54b9ea5676b66b..62ab5312d6121b 100644
--- a/Lib/venv/scripts/posix/activate.fish
+++ b/Lib/venv/scripts/posix/activate.fish
@@ -29,10 +29,10 @@ end
# Unset irrelevant variables.
deactivate nondestructive
-set -gx VIRTUAL_ENV "__VENV_DIR__"
+set -gx VIRTUAL_ENV __VENV_DIR__
set -gx _OLD_VIRTUAL_PATH $PATH
-set -gx PATH "$VIRTUAL_ENV/__VENV_BIN_NAME__" $PATH
+set -gx PATH "$VIRTUAL_ENV/"__VENV_BIN_NAME__ $PATH
# Unset PYTHONHOME if set.
if set -q PYTHONHOME
@@ -52,7 +52,7 @@ if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
set -l old_status $status
# Output the venv prompt; color taken from the blue of the Python logo.
- printf "%s%s%s" (set_color 4B8BBE) "__VENV_PROMPT__" (set_color normal)
+ printf "%s%s%s" (set_color 4B8BBE) __VENV_PROMPT__ (set_color normal)
# Restore the return status of the previous command.
echo "exit $old_status" | .
diff --git a/Misc/NEWS.d/next/Library/2024-09-28-02-03-04.gh-issue-124651.bLBGtH.rst b/Misc/NEWS.d/next/Library/2024-09-28-02-03-04.gh-issue-124651.bLBGtH.rst
new file mode 100644
index 00000000000000..17fc9171390dd9
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-09-28-02-03-04.gh-issue-124651.bLBGtH.rst
@@ -0,0 +1 @@
+Properly quote template strings in :mod:`venv` activation scripts.

View File

@ -0,0 +1,137 @@
From a7084f6075c9595ba60119ce8c62f1496f50c568 Mon Sep 17 00:00:00 2001
From: "Miss Islington (bot)"
<31488909+miss-islington@users.noreply.github.com>
Date: Sun, 2 Feb 2025 09:30:28 +0100
Subject: [PATCH] [3.12] gh-105704: Disallow square brackets (`[` and `]`) in
domain names for parsed URLs (GH-129418) (GH-129527)
gh-105704: Disallow square brackets (`[` and `]`) in domain names for parsed URLs (GH-129418)
* gh-105704: Disallow square brackets ( and ) in domain names for parsed URLs
* Use Sphinx references
* Add mismatched bracket test cases, fix news format
* Add more test coverage for ports
---------
(cherry picked from commit d89a5f6a6e65511a5f6e0618c4c30a7aa5aba56a)
Co-authored-by: Seth Michael Larson <seth@python.org>
Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
---
Lib/test/test_urlparse.py | 37 ++++++++++++++++++-
Lib/urllib/parse.py | 20 +++++++++-
...-01-28-14-08-03.gh-issue-105704.EnhHxu.rst | 4 ++
3 files changed, 58 insertions(+), 3 deletions(-)
create mode 100644 Misc/NEWS.d/next/Security/2025-01-28-14-08-03.gh-issue-105704.EnhHxu.rst
diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py
index 818e7e93dbbe11..5e429b9259fee7 100644
--- a/Lib/test/test_urlparse.py
+++ b/Lib/test/test_urlparse.py
@@ -1273,16 +1273,51 @@ def test_invalid_bracketed_hosts(self):
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')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[v6a.ip]')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[v6a.ip].suffix')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[v6a.ip]/')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[v6a.ip].suffix/')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[v6a.ip]?')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[v6a.ip].suffix?')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]/')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix/')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]?')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix?')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:a')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix:a')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:a1')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix:a1')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:1a')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix:1a')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix:/')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:?')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://user@prefix.[v6a.ip]')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://user@[v6a.ip].suffix')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[v6a.ip')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://v6a.ip]')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://]v6a.ip[')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://]v6a.ip')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://v6a.ip[')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[v6a.ip')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://v6a.ip].suffix')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix]v6a.ip[suffix')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix]v6a.ip')
+ self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://v6a.ip[suffix')
def test_splitting_bracketed_hosts(self):
- p1 = urllib.parse.urlsplit('scheme://user@[v6a.ip]/path?query')
+ p1 = urllib.parse.urlsplit('scheme://user@[v6a.ip]:1234/path?query')
self.assertEqual(p1.hostname, 'v6a.ip')
self.assertEqual(p1.username, 'user')
self.assertEqual(p1.path, '/path')
+ self.assertEqual(p1.port, 1234)
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')
+ self.assertIs(p2.port, None)
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')
diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py
index 24815952037fef..c72138a33ca6d4 100644
--- a/Lib/urllib/parse.py
+++ b/Lib/urllib/parse.py
@@ -436,6 +436,23 @@ def _checknetloc(netloc):
raise ValueError("netloc '" + netloc + "' contains invalid " +
"characters under NFKC normalization")
+def _check_bracketed_netloc(netloc):
+ # Note that this function must mirror the splitting
+ # done in NetlocResultMixins._hostinfo().
+ hostname_and_port = netloc.rpartition('@')[2]
+ before_bracket, have_open_br, bracketed = hostname_and_port.partition('[')
+ if have_open_br:
+ # No data is allowed before a bracket.
+ if before_bracket:
+ raise ValueError("Invalid IPv6 URL")
+ hostname, _, port = bracketed.partition(']')
+ # No data is allowed after the bracket but before the port delimiter.
+ if port and not port.startswith(":"):
+ raise ValueError("Invalid IPv6 URL")
+ else:
+ hostname, _, port = hostname_and_port.partition(':')
+ _check_bracketed_host(hostname)
+
# 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):
@@ -496,8 +513,7 @@ def urlsplit(url, scheme='', allow_fragments=True):
(']' 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)
+ _check_bracketed_netloc(netloc)
if allow_fragments and '#' in url:
url, fragment = url.split('#', 1)
if '?' in url:
diff --git a/Misc/NEWS.d/next/Security/2025-01-28-14-08-03.gh-issue-105704.EnhHxu.rst b/Misc/NEWS.d/next/Security/2025-01-28-14-08-03.gh-issue-105704.EnhHxu.rst
new file mode 100644
index 00000000000000..bff1bc6b0d609c
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2025-01-28-14-08-03.gh-issue-105704.EnhHxu.rst
@@ -0,0 +1,4 @@
+When using :func:`urllib.parse.urlsplit` and :func:`urllib.parse.urlparse` host
+parsing would not reject domain names containing square brackets (``[`` and
+``]``). Square brackets are only valid for IPv6 and IPvFuture hosts according to
+`RFC 3986 Section 3.2.2 <https://www.rfc-editor.org/rfc/rfc3986#section-3.2.2>`__.

View File

@ -3,7 +3,7 @@ Summary: Interpreter of the Python3 programming language
URL: https://www.python.org/
Version: 3.9.9
Release: 36
Release: 41
License: Python-2.0
%global branchversion 3.9
@ -130,12 +130,17 @@ Patch6032: backport-CVE-2024-3219-1-gh-122133-Authenticate-socket-connection-for
Patch6033: backport-CVE-2024-3219-2-gh-122133-Rework-pure-Python-socketpair-tests-to.patch
Patch6034: backport-CVE-2023-6597-gh-91133-tempfile.TemporaryDirectory-fix-symlink.patch
Patch6035: backport-CVE-2024-0450-gh-109858-Protect-zipfile-from-quoted-overlap-zi.patch
Patch6036: backport-3.9-gh-107845-Fix-symlink-handling-for-tarfile.data_.patch
Patch6037: backport-CVE-2024-9287.patch
Patch6038: backport-CVE-2024-11168-3.9-gh-103848-Adds-checks-to-ensure-that-bracketed-h.patch
Patch6039: backport-CVE-2025-0938.patch
Patch9000: add-the-sm3-method-for-obtaining-the-salt-value.patch
Patch9001: python3-Add-sw64-architecture.patch
Patch9002: Add-loongarch-support.patch
Patch9003: avoid-usage-of-md5-in-multiprocessing.patch
Patch9004: update-openssl-version-for-test-case.patch
Patch9005: 0001-expected_algs-list-to-include-TLS_SM4.patch
Provides: python%{branchversion} = %{version}-%{release}
Provides: python(abi) = %{branchversion}
@ -216,51 +221,56 @@ extension modules.
find -name '*.exe' -print -delete
rm -r Modules/expat
%patch1 -p1
%patch111 -p1
%patch251 -p1
%patch6000 -p1
%patch6001 -p1
%patch6002 -p1
%patch6003 -p1
%patch6004 -p1
%patch6005 -p1
%patch6006 -p1
%patch6007 -p1
%patch6008 -p1
%patch6009 -p1
%patch6010 -p1
%patch6011 -p1
%patch6012 -p1
%patch6013 -p1
%patch6014 -p1
%patch6015 -p1
%patch6016 -p1
%patch6017 -p1
%patch6018 -p1
%patch6019 -p1
%patch6020 -p1
%patch6021 -p1
%patch6022 -p1
%patch6023 -p1
%patch6024 -p1
%patch6025 -p1
%patch6026 -p1
%patch6027 -p1
%patch6028 -p1
%patch6029 -p1
%patch6030 -p1
%patch6031 -p1
%patch6032 -p1
%patch6033 -p1
%patch6034 -p1
%patch6035 -p1
%patch -P1 -p1
%patch -P111 -p1
%patch -P251 -p1
%patch -P6000 -p1
%patch -P6001 -p1
%patch -P6002 -p1
%patch -P6003 -p1
%patch -P6004 -p1
%patch -P6005 -p1
%patch -P6006 -p1
%patch -P6007 -p1
%patch -P6008 -p1
%patch -P6009 -p1
%patch -P6010 -p1
%patch -P6011 -p1
%patch -P6012 -p1
%patch -P6013 -p1
%patch -P6014 -p1
%patch -P6015 -p1
%patch -P6016 -p1
%patch -P6017 -p1
%patch -P6018 -p1
%patch -P6019 -p1
%patch -P6020 -p1
%patch -P6021 -p1
%patch -P6022 -p1
%patch -P6023 -p1
%patch -P6024 -p1
%patch -P6025 -p1
%patch -P6026 -p1
%patch -P6027 -p1
%patch -P6028 -p1
%patch -P6029 -p1
%patch -P6030 -p1
%patch -P6031 -p1
%patch -P6032 -p1
%patch -P6033 -p1
%patch -P6034 -p1
%patch -P6035 -p1
%patch -P6036 -p1
%patch -P6037 -p1
%patch -P6038 -p1
%patch9000 -p1
%patch9001 -p1
%patch9002 -p1
%patch9003 -p1
%patch9004 -p1
%patch -P9000 -p1
%patch -P9001 -p1
%patch -P9002 -p1
%patch -P9003 -p1
%patch -P9004 -p1
%patch -P9005 -p1
%patch -P6039 -p1
rm Lib/ensurepip/_bundled/*.whl
rm configure pyconfig.h.in
@ -883,6 +893,39 @@ export BEP_GTDLIST="$BEP_GTDLIST_TMP"
%{_mandir}/*/*
%changelog
* Tue Feb 11 2025 Funda Wang <fundawang@yeah.net> - 3.9.9-41
- Type:CVE
- CVE:CVE-2025-0938
- SUG:NA
- DESC:fix CVE-2025-0938
* Wed Dec 25 2024 xinsheng <xinsheng3@huawei.com> - 3.9.9-40
- Type:CVE
- CVE:CVE-2024-11168
- SUG:NA
- DESC:fix CVE-2024-11168
- Adds checks to ensure that bracketed hosts found by urlsplit are of IPv6 or IPvFuture format
* Wed Dec 11 2024 wangshuo <wangshuo@kylinos.cn> - 3.9.9-39
- Type:update
- CVE:NA
- SUG:NA
- DESC:support TLS_SM4
* Tue Nov 12 2024 Funda Wang <fundawang@yeah.net> - 3.9.9-38
- Type:CVE
- CVE:CVE-2024-9287
- SUG:NA
- DESC:fix CVE-2024-9287
- Quote template strings in venv activation scripts
* Tue Oct 29 2024 wangshuo <wangshuo@kylinos.cn> - 3.9.9-37
- Type:bugfix
- ID:NA
- SUG:NA
- DESC:backport upstream patch, fix the bug introduced by the fix for CVE-2007-4559
- gh-107845: Fix symlink handling for tarfile.data_filter
* Tue Sep 24 2024 xinsheng <xinsheng3@huawei.com> - 3.9.9-36
- Type:CVE
- CVE:CVE-2024-6232,CVE-2024-3219,CVE-2024-0450,CVE-2023-6597,CVE-2024-4032