Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions SPECS/python3/CVE-2026-0864.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
From db4a157c790479710a1a840d7937c5c815a6f8b6 Mon Sep 17 00:00:00 2001
From: "Miss Islington (bot)"
<31488909+miss-islington@users.noreply.github.com>
Date: Tue, 4 Aug 2026 11:27:20 +0200
Subject: [PATCH] [3.12] gh-143927: Normalize all line endings (CR, CRLF, and
LF) in configparser (GH-143929) (#152005)

gh-143927: Normalize all line endings (CR, CRLF, and LF) in configparser (GH-143929)
(cherry picked from commit 5858e42c539dac8394636a6e9b30472b8994851f)

Co-authored-by: Seth Larson <seth@python.org>

Upstream Patch Reference: https://github.com/python/cpython/commit/db4a157c790479710a1a840d7937c5c815a6f8b6.patch
---
Lib/configparser.py | 4 +++-
Lib/test/test_configparser.py | 11 +++++++++++
.../2026-01-16-11-58-19.gh-issue-143927.aviFeG.rst | 2 ++
3 files changed, 16 insertions(+), 1 deletion(-)
create mode 100644 Misc/NEWS.d/next/Security/2026-01-16-11-58-19.gh-issue-143927.aviFeG.rst

diff --git a/Lib/configparser.py b/Lib/configparser.py
index f96704e..8ae35a0 100644
--- a/Lib/configparser.py
+++ b/Lib/configparser.py
@@ -907,7 +907,9 @@ class RawConfigParser(MutableMapping):
value = self._interpolation.before_write(self, section_name, key,
value)
if value is not None or not self._allow_no_value:
- value = delimiter + str(value).replace('\n', '\n\t')
+ # Convert all possible line-endings into '\n\t'
+ value = (delimiter + str(value).replace('\r\n', '\n')
+ .replace('\r', '\n').replace('\n', '\n\t'))
else:
value = ""
fp.write("{}{}\n".format(key, value))
diff --git a/Lib/test/test_configparser.py b/Lib/test/test_configparser.py
index b7e68d7..389aa15 100644
--- a/Lib/test/test_configparser.py
+++ b/Lib/test/test_configparser.py
@@ -527,6 +527,17 @@ boolean {0[0]} NO
cf.get(self.default_section, "Foo"), "Bar",
"could not locate option, expecting case-insensitive defaults")

+ def test_crlf_normalization(self):
+ cf = self.newconfig({"key1": "a\nb","key2": "a\rb", "key3": "a\r\nb", "key4": "a\r\nb"})
+ buf = io.StringIO()
+ cf.write(buf)
+ cf_str = buf.getvalue()
+ self.assertNotIn("\r", cf_str)
+ self.assertNotIn("\r\n", cf_str)
+ self.assertEqual(cf_str.count("\n"), 10)
+ self.assertEqual(cf_str.count("\n\t"), 4)
+ self.assertTrue(cf_str.endswith("\n\n"))
+
def test_parse_errors(self):
cf = self.newconfig()
self.parse_error(cf, configparser.ParsingError,
diff --git a/Misc/NEWS.d/next/Security/2026-01-16-11-58-19.gh-issue-143927.aviFeG.rst b/Misc/NEWS.d/next/Security/2026-01-16-11-58-19.gh-issue-143927.aviFeG.rst
new file mode 100644
index 0000000..ca55499
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2026-01-16-11-58-19.gh-issue-143927.aviFeG.rst
@@ -0,0 +1,2 @@
+Normalize all line endings (CR, CRLF, and LF) to LF+TAB when writing
+multi-line configparser values.
--
2.45.4

111 changes: 111 additions & 0 deletions SPECS/python3/CVE-2026-11972.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
From 26ce07f59a656b5da92114392a2dc27267de9274 Mon Sep 17 00:00:00 2001
From: "Miss Islington (bot)"
<31488909+miss-islington@users.noreply.github.com>
Date: Tue, 4 Aug 2026 11:26:39 +0200
Subject: [PATCH] gh-151981: Make tarfile._Stream.seek break at EOF (GH-151982)
(#151994)

gh-151981: Make tarfile._Stream.seek break at EOF (GH-151982)
(cherry picked from commit f50bf13566189c8d0ce5a814f33eff3d89951896)

Co-authored-by: Petr Viktorin <encukou@gmail.com>
Co-authored-by: Stan Ulbrych <stan@python.org>
Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
Upstream-reference: https://github.com/python/cpython/commit/f5e2776ff0383a902c12acf2b703e7e951fc8438.patch
---
Lib/tarfile.py | 4 ++-
Lib/test/support/__init__.py | 25 +++++++++++++++++++
Lib/test/test_tarfile.py | 16 ++++++++++++
...-06-23-13-28-16.gh-issue-151981.xBHEcU.rst | 2 ++
4 files changed, 46 insertions(+), 1 deletion(-)
create mode 100644 Misc/NEWS.d/next/Security/2026-06-23-13-28-16.gh-issue-151981.xBHEcU.rst

diff --git a/Lib/tarfile.py b/Lib/tarfile.py
index 461ec16..28c3edf 100755
--- a/Lib/tarfile.py
+++ b/Lib/tarfile.py
@@ -516,7 +516,9 @@ class _Stream:
if pos - self.pos >= 0:
blocks, remainder = divmod(pos - self.pos, self.bufsize)
for i in range(blocks):
- self.read(self.bufsize)
+ data = self.read(self.bufsize)
+ if not data:
+ break
self.read(remainder)
else:
raise StreamError("seeking backwards is not allowed")
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index abd2fea..4ccce74 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -863,6 +863,31 @@ def check_sizeof(test, o, size):
% (type(o), result, size)
test.assertEqual(result, size, msg)

+def subTests(arg_names, arg_values, /, *, _do_cleanups=False):
+ """Run multiple subtests with different parameters.
+ """
+ single_param = False
+ if isinstance(arg_names, str):
+ arg_names = arg_names.replace(',',' ').split()
+ if len(arg_names) == 1:
+ single_param = True
+ arg_values = tuple(arg_values)
+ def decorator(func):
+ if isinstance(func, type):
+ raise TypeError('subTests() can only decorate methods, not classes')
+ @functools.wraps(func)
+ def wrapper(self, /, *args, **kwargs):
+ for values in arg_values:
+ if single_param:
+ values = (values,)
+ subtest_kwargs = dict(zip(arg_names, values))
+ with self.subTest(**subtest_kwargs):
+ func(self, *args, **kwargs, **subtest_kwargs)
+ if _do_cleanups:
+ self.doCleanups()
+ return wrapper
+ return decorator
+
#=======================================================================
# Decorator/context manager for running a code in a different locale,
# correctly resetting it afterwards.
diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py
index 717d1c1..8388dc4 100644
--- a/Lib/test/test_tarfile.py
+++ b/Lib/test/test_tarfile.py
@@ -4555,6 +4555,22 @@ class TestExtractionFilters(unittest.TestCase):
with self.check_context(arc.open(errorlevel='boo!'), filtererror_filter):
self.expect_exception(TypeError) # errorlevel is not int

+ @support.subTests('format', [tarfile.GNU_FORMAT, tarfile.PAX_FORMAT])
+ def test_getmembers_big_size(self, format):
+ # gh-151981: A loop in seek() for streaming files tried to read the
+ # declared number of blocks even at EOF
+ tinfo = tarfile.TarInfo("huge-file")
+ tinfo.size = 1 << 64
+ bio = io.BytesIO()
+ # Write header without data
+ bio.write(tinfo.tobuf(format))
+
+ # Reset & try to get contents
+ bio.seek(0)
+ with tarfile.open(fileobj=bio, mode="r|") as tar:
+ with self.assertRaises(tarfile.ReadError):
+ tar.getmembers()
+

class OverwriteTests(archiver_tests.OverwriteTests, unittest.TestCase):
testdir = os.path.join(TEMPDIR, "testoverwrite")
diff --git a/Misc/NEWS.d/next/Security/2026-06-23-13-28-16.gh-issue-151981.xBHEcU.rst b/Misc/NEWS.d/next/Security/2026-06-23-13-28-16.gh-issue-151981.xBHEcU.rst
new file mode 100644
index 0000000..2123ab8
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2026-06-23-13-28-16.gh-issue-151981.xBHEcU.rst
@@ -0,0 +1,2 @@
+In :mod:`tarfile`, seeking a stream now stops when end of the stream is
+reached.
--
2.45.4

94 changes: 94 additions & 0 deletions SPECS/python3/CVE-2026-12003.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
From d5ee580a170b7afe7dda8d5a89102ed5cc1ac683 Mon Sep 17 00:00:00 2001
From: "Miss Islington (bot)"
<31488909+miss-islington@users.noreply.github.com>
Date: Tue, 4 Aug 2026 11:24:46 +0200
Subject: [PATCH] gh-151544: Fixes CVE-2026-12003 by removing the fallback to
%VPATH%/Modules/Setup.local for discovering sources in getpath.py (GH-151545)
(#151567)

gh-151544: Fixes CVE-2026-12003 by removing the fallback to %VPATH%/Modules/Setup.local for discovering sources in getpath.py (GH-151545)
(cherry picked from commit 9e863fab283eddca9c2a8f9d1ee30f4dc243e314)

Co-authored-by: Steve Dower <steve.dower@python.org>
Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
Upstream-reference: https://github.com/python/cpython/commit/03ab7b44788bfd6b8927e16bcdbd025aa08dce06.patch
---
Makefile.pre.in | 2 ++
...2026-06-16-14-58-02.gh-issue-151544._bexVy.rst | 4 ++++
Modules/getpath.py | 15 ++++-----------
3 files changed, 10 insertions(+), 11 deletions(-)
create mode 100644 Misc/NEWS.d/next/Security/2026-06-16-14-58-02.gh-issue-151544._bexVy.rst

diff --git a/Makefile.pre.in b/Makefile.pre.in
index 689f33d..8d13d20 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -1074,6 +1074,8 @@ Programs/_bootstrap_python.o: Programs/_bootstrap_python.c $(BOOTSTRAP_HEADERS)
_bootstrap_python: $(LIBRARY_OBJS_OMIT_FROZEN) Programs/_bootstrap_python.o Modules/getpath.o Modules/Setup.local
$(LINKCC) $(PY_LDFLAGS_NOLTO) -o $@ $(LIBRARY_OBJS_OMIT_FROZEN) \
Programs/_bootstrap_python.o Modules/getpath.o $(LIBS) $(MODLIBS) $(SYSLIBS)
+ # Dummy pybuilddir.txt is needed for _bootstrap_python to be runnable
+ @echo "none" > ./pybuilddir.txt


############################################################################
diff --git a/Misc/NEWS.d/next/Security/2026-06-16-14-58-02.gh-issue-151544._bexVy.rst b/Misc/NEWS.d/next/Security/2026-06-16-14-58-02.gh-issue-151544._bexVy.rst
new file mode 100644
index 0000000..418e3b4
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2026-06-16-14-58-02.gh-issue-151544._bexVy.rst
@@ -0,0 +1,4 @@
+:file:`Modules/Setup.local` is no longer used as a landmark to discover
+whether Python is running in a source tree, as it could potentially affect
+actual installs. The :file:`pybuilddir.txt` file is now the sole indicator
+of running in a source tree.
diff --git a/Modules/getpath.py b/Modules/getpath.py
index 9913fcb..29a6b30 100644
--- a/Modules/getpath.py
+++ b/Modules/getpath.py
@@ -128,8 +128,7 @@
# checked by looking for the BUILDDIR_TXT file, which contains the
# relative path to the platlib dir. The executable_dir value is
# derived from joining the VPATH preprocessor variable to the
-# directory containing pybuilddir.txt. If it is not found, the
-# BUILD_LANDMARK file is found, which is part of the source tree.
+# directory containing pybuilddir.txt.
# prefix is then found by searching up for a file that should only
# exist in the source tree, and the stdlib dir is set to prefix/Lib.

@@ -175,7 +174,6 @@ platlibdir = config.get('platlibdir') or PLATLIBDIR

if os_name == 'posix' or os_name == 'darwin':
BUILDDIR_TXT = 'pybuilddir.txt'
- BUILD_LANDMARK = 'Modules/Setup.local'
DEFAULT_PROGRAM_NAME = f'python{VERSION_MAJOR}'
STDLIB_SUBDIR = f'{platlibdir}/python{VERSION_MAJOR}.{VERSION_MINOR}'
STDLIB_LANDMARKS = [f'{STDLIB_SUBDIR}/os.py', f'{STDLIB_SUBDIR}/os.pyc']
@@ -188,7 +186,6 @@ if os_name == 'posix' or os_name == 'darwin':

elif os_name == 'nt':
BUILDDIR_TXT = 'pybuilddir.txt'
- BUILD_LANDMARK = f'{VPATH}\\Modules\\Setup.local'
DEFAULT_PROGRAM_NAME = f'python'
STDLIB_SUBDIR = 'Lib'
STDLIB_LANDMARKS = [f'{STDLIB_SUBDIR}\\os.py', f'{STDLIB_SUBDIR}\\os.pyc']
@@ -495,13 +492,9 @@ if ((not home_was_set and real_executable_dir and not py_setpath)
platstdlib_dir = real_executable_dir
build_prefix = joinpath(real_executable_dir, VPATH)
except (FileNotFoundError, PermissionError):
- if isfile(joinpath(real_executable_dir, BUILD_LANDMARK)):
- build_prefix = joinpath(real_executable_dir, VPATH)
- if os_name == 'nt':
- # QUIRK: Windows builds need platstdlib_dir to be the executable
- # dir. Normally the builddir marker handles this, but in this
- # case we need to correct manually.
- platstdlib_dir = real_executable_dir
+ # We used to check for an alternate landmark here, but now we require
+ # BUILDDIR_TXT to exist. (gh-151544; CVE-2026-12003)
+ pass

if build_prefix:
if os_name == 'nt':
--
2.45.4

43 changes: 43 additions & 0 deletions SPECS/python3/CVE-2026-2297.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
From d3a9b6792366a8386be7278540b6e3e7037413ae Mon Sep 17 00:00:00 2001
From: "Miss Islington (bot)"
<31488909+miss-islington@users.noreply.github.com>
Date: Tue, 4 Aug 2026 11:14:48 +0200
Subject: [PATCH] gh-145506: Fixes CVE-2026-2297 by ensuring
SourcelessFileLoader uses io.open_code (GH-145507) (#145514)

gh-145506: Fixes CVE-2026-2297 by ensuring SourcelessFileLoader uses io.open_code (GH-145507)
(cherry picked from commit a51b1b512de1d56b3714b65628a2eae2b07e535e)

Co-authored-by: Steve Dower <steve.dower@python.org>
Signed-off-by: Azure Linux Security Servicing Account <azurelinux-security@microsoft.com>
Upstream-reference: https://github.com/python/cpython/commit/c70adad78caeeea33f92f560ecb93331ca11bf66.patch
---
Lib/importlib/_bootstrap_external.py | 2 +-
.../Security/2026-03-04-18-59-17.gh-issue-145506.6hwvEh.rst | 2 ++
2 files changed, 3 insertions(+), 1 deletion(-)
create mode 100644 Misc/NEWS.d/next/Security/2026-03-04-18-59-17.gh-issue-145506.6hwvEh.rst

diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py
index 9b8a8df..6e4a087 100644
--- a/Lib/importlib/_bootstrap_external.py
+++ b/Lib/importlib/_bootstrap_external.py
@@ -1186,7 +1186,7 @@ class FileLoader:

def get_data(self, path):
"""Return the data from path as raw bytes."""
- if isinstance(self, (SourceLoader, ExtensionFileLoader)):
+ if isinstance(self, (SourceLoader, SourcelessFileLoader, ExtensionFileLoader)):
with _io.open_code(str(path)) as file:
return file.read()
else:
diff --git a/Misc/NEWS.d/next/Security/2026-03-04-18-59-17.gh-issue-145506.6hwvEh.rst b/Misc/NEWS.d/next/Security/2026-03-04-18-59-17.gh-issue-145506.6hwvEh.rst
new file mode 100644
index 0000000..dcdb44d
--- /dev/null
+++ b/Misc/NEWS.d/next/Security/2026-03-04-18-59-17.gh-issue-145506.6hwvEh.rst
@@ -0,0 +1,2 @@
+Fixes :cve:`2026-2297` by ensuring that ``SourcelessFileLoader`` uses
+:func:`io.open_code` when opening ``.pyc`` files.
--
2.45.4

Loading
Loading