diff --git a/SPECS/python3/CVE-2025-13837.patch b/SPECS/python3/CVE-2025-13837.patch new file mode 100644 index 00000000000..92619d4854b --- /dev/null +++ b/SPECS/python3/CVE-2025-13837.patch @@ -0,0 +1,165 @@ +From b6c0cfd97917cf3ef6831f60a7830136fc508b09 Mon Sep 17 00:00:00 2001 +From: Serhiy Storchaka +Date: Mon, 1 Dec 2025 17:28:15 +0200 +Subject: [PATCH] gh-119342: Fix a potential denial of service in plistlib + (GH-119343) + +Reading a specially prepared small Plist file could cause OOM because file's +read(n) preallocates a bytes object for reading the specified amount of +data. Now plistlib reads large data by chunks, therefore the upper limit of +consumed memory is proportional to the size of the input file. +(cherry picked from commit 694922cf40aa3a28f898b5f5ee08b71b4922df70) + +Co-authored-by: Serhiy Storchaka +Signed-off-by: Azure Linux Security Servicing Account +Upstream-reference: https://github.com/python/cpython/pull/142151.patch +--- + Lib/plistlib.py | 31 ++++++++++------ + Lib/test/test_plistlib.py | 37 +++++++++++++++++-- + ...-05-21-22-11-31.gh-issue-119342.BTFj4Z.rst | 5 +++ + 3 files changed, 59 insertions(+), 14 deletions(-) + create mode 100644 Misc/NEWS.d/next/Security/2024-05-21-22-11-31.gh-issue-119342.BTFj4Z.rst + +diff --git a/Lib/plistlib.py b/Lib/plistlib.py +index 2eeebe4..9125f3a 100644 +--- a/Lib/plistlib.py ++++ b/Lib/plistlib.py +@@ -64,6 +64,9 @@ from xml.parsers.expat import ParserCreate + PlistFormat = enum.Enum('PlistFormat', 'FMT_XML FMT_BINARY', module=__name__) + globals().update(PlistFormat.__members__) + ++# Data larger than this will be read in chunks, to prevent extreme ++# overallocation. ++_MIN_READ_BUF_SIZE = 1 << 20 + + class UID: + def __init__(self, data): +@@ -490,12 +493,24 @@ class _BinaryPlistParser: + + return tokenL + ++ def _read(self, size): ++ cursize = min(size, _MIN_READ_BUF_SIZE) ++ data = self._fp.read(cursize) ++ while True: ++ if len(data) != cursize: ++ raise InvalidFileException ++ if cursize == size: ++ return data ++ delta = min(cursize, size - cursize) ++ data += self._fp.read(delta) ++ cursize += delta ++ + def _read_ints(self, n, size): +- data = self._fp.read(size * n) ++ data = self._read(size * n) + if size in _BINARY_FORMAT: + return struct.unpack(f'>{n}{_BINARY_FORMAT[size]}', data) + else: +- if not size or len(data) != size * n: ++ if not size: + raise InvalidFileException() + return tuple(int.from_bytes(data[i: i + size], 'big') + for i in range(0, size * n, size)) +@@ -552,22 +567,16 @@ class _BinaryPlistParser: + + elif tokenH == 0x40: # data + s = self._get_size(tokenL) +- result = self._fp.read(s) +- if len(result) != s: +- raise InvalidFileException() ++ result = self._read(s) + + elif tokenH == 0x50: # ascii string + s = self._get_size(tokenL) +- data = self._fp.read(s) +- if len(data) != s: +- raise InvalidFileException() ++ data = self._read(s) + result = data.decode('ascii') + + elif tokenH == 0x60: # unicode string + s = self._get_size(tokenL) * 2 +- data = self._fp.read(s) +- if len(data) != s: +- raise InvalidFileException() ++ data = self._read(s) + result = data.decode('utf-16be') + + elif tokenH == 0x80: # UID +diff --git a/Lib/test/test_plistlib.py b/Lib/test/test_plistlib.py +index 9e53305..1a716b0 100644 +--- a/Lib/test/test_plistlib.py ++++ b/Lib/test/test_plistlib.py +@@ -837,8 +837,7 @@ class TestPlistlib(unittest.TestCase): + + class TestBinaryPlistlib(unittest.TestCase): + +- @staticmethod +- def decode(*objects, offset_size=1, ref_size=1): ++ def build(self, *objects, offset_size=1, ref_size=1): + data = [b'bplist00'] + offset = 8 + offsets = [] +@@ -850,7 +849,11 @@ class TestBinaryPlistlib(unittest.TestCase): + len(objects), 0, offset) + data.extend(offsets) + data.append(tail) +- return plistlib.loads(b''.join(data), fmt=plistlib.FMT_BINARY) ++ return b''.join(data) ++ ++ def decode(self, *objects, offset_size=1, ref_size=1): ++ data = self.build(*objects, offset_size=offset_size, ref_size=ref_size) ++ return plistlib.loads(data, fmt=plistlib.FMT_BINARY) + + def test_nonstandard_refs_size(self): + # Issue #21538: Refs and offsets are 24-bit integers +@@ -958,6 +961,34 @@ class TestBinaryPlistlib(unittest.TestCase): + with self.assertRaises(plistlib.InvalidFileException): + plistlib.loads(b'bplist00' + data, fmt=plistlib.FMT_BINARY) + ++ def test_truncated_large_data(self): ++ self.addCleanup(os_helper.unlink, os_helper.TESTFN) ++ def check(data): ++ with open(os_helper.TESTFN, 'wb') as f: ++ f.write(data) ++ # buffered file ++ with open(os_helper.TESTFN, 'rb') as f: ++ with self.assertRaises(plistlib.InvalidFileException): ++ plistlib.load(f, fmt=plistlib.FMT_BINARY) ++ # unbuffered file ++ with open(os_helper.TESTFN, 'rb', buffering=0) as f: ++ with self.assertRaises(plistlib.InvalidFileException): ++ plistlib.load(f, fmt=plistlib.FMT_BINARY) ++ for w in range(20, 64): ++ s = 1 << w ++ # data ++ check(self.build(b'\x4f\x13' + s.to_bytes(8, 'big'))) ++ # ascii string ++ check(self.build(b'\x5f\x13' + s.to_bytes(8, 'big'))) ++ # unicode string ++ check(self.build(b'\x6f\x13' + s.to_bytes(8, 'big'))) ++ # array ++ check(self.build(b'\xaf\x13' + s.to_bytes(8, 'big'))) ++ # dict ++ check(self.build(b'\xdf\x13' + s.to_bytes(8, 'big'))) ++ # number of objects ++ check(b'bplist00' + struct.pack('>6xBBQQQ', 1, 1, s, 0, 8)) ++ + + class TestKeyedArchive(unittest.TestCase): + def test_keyed_archive_data(self): +diff --git a/Misc/NEWS.d/next/Security/2024-05-21-22-11-31.gh-issue-119342.BTFj4Z.rst b/Misc/NEWS.d/next/Security/2024-05-21-22-11-31.gh-issue-119342.BTFj4Z.rst +new file mode 100644 +index 0000000..04fd8fa +--- /dev/null ++++ b/Misc/NEWS.d/next/Security/2024-05-21-22-11-31.gh-issue-119342.BTFj4Z.rst +@@ -0,0 +1,5 @@ ++Fix a potential memory denial of service in the :mod:`plistlib` module. ++When reading a Plist file received from untrusted source, it could cause ++an arbitrary amount of memory to be allocated. ++This could have led to symptoms including a :exc:`MemoryError`, swapping, out ++of memory (OOM) killed processes or containers, or even system crashes. +-- +2.45.4 + diff --git a/SPECS/python3/python3.spec b/SPECS/python3/python3.spec index 7805accec48..087411bcfd8 100644 --- a/SPECS/python3/python3.spec +++ b/SPECS/python3/python3.spec @@ -12,7 +12,7 @@ Summary: A high-level scripting language Name: python3 Version: 3.9.19 -Release: 17%{?dist} +Release: 18%{?dist} License: PSF Vendor: Microsoft Corporation Distribution: Mariner @@ -50,6 +50,7 @@ Patch1004: CVE-2024-37891.patch Patch1005: CVE-2025-50181.patch Patch1006: CVE-2023-5752.patch Patch1007: CVE-2023-45803.patch +Patch1008: CVE-2025-13837.patch BuildRequires: bzip2-devel BuildRequires: expat-devel >= 2.1.0 @@ -379,6 +380,9 @@ make test TESTOPTS="-x test_multiprocessing_spawn -x test_socket -x test_email" %{_libdir}/python%{majmin}/test/* %changelog +* Thu Dec 25 2025 Azure Linux Security Servicing Account - 3.9.19-18 +- Patch for CVE-2025-13837 + * Tue Nov 04 2025 Azure Linux Security Servicing Account - 3.9.19-17 - Patch for CVE-2025-6075 diff --git a/toolkit/resources/manifests/package/pkggen_core_aarch64.txt b/toolkit/resources/manifests/package/pkggen_core_aarch64.txt index 6a340f1c05f..574e7d6c726 100644 --- a/toolkit/resources/manifests/package/pkggen_core_aarch64.txt +++ b/toolkit/resources/manifests/package/pkggen_core_aarch64.txt @@ -237,10 +237,10 @@ ca-certificates-base-2.0.0-25.cm2.noarch.rpm ca-certificates-2.0.0-25.cm2.noarch.rpm dwz-0.14-2.cm2.aarch64.rpm unzip-6.0-22.cm2.aarch64.rpm -python3-3.9.19-17.cm2.aarch64.rpm -python3-devel-3.9.19-17.cm2.aarch64.rpm -python3-libs-3.9.19-17.cm2.aarch64.rpm -python3-setuptools-3.9.19-17.cm2.noarch.rpm +python3-3.9.19-18.cm2.aarch64.rpm +python3-devel-3.9.19-18.cm2.aarch64.rpm +python3-libs-3.9.19-18.cm2.aarch64.rpm +python3-setuptools-3.9.19-18.cm2.noarch.rpm python3-pygments-2.4.2-7.cm2.noarch.rpm which-2.21-8.cm2.aarch64.rpm libselinux-3.2-1.cm2.aarch64.rpm diff --git a/toolkit/resources/manifests/package/pkggen_core_x86_64.txt b/toolkit/resources/manifests/package/pkggen_core_x86_64.txt index a8e215242cd..b3f8d1d7719 100644 --- a/toolkit/resources/manifests/package/pkggen_core_x86_64.txt +++ b/toolkit/resources/manifests/package/pkggen_core_x86_64.txt @@ -237,10 +237,10 @@ ca-certificates-base-2.0.0-25.cm2.noarch.rpm ca-certificates-2.0.0-25.cm2.noarch.rpm dwz-0.14-2.cm2.x86_64.rpm unzip-6.0-22.cm2.x86_64.rpm -python3-3.9.19-17.cm2.x86_64.rpm -python3-devel-3.9.19-17.cm2.x86_64.rpm -python3-libs-3.9.19-17.cm2.x86_64.rpm -python3-setuptools-3.9.19-17.cm2.noarch.rpm +python3-3.9.19-18.cm2.x86_64.rpm +python3-devel-3.9.19-18.cm2.x86_64.rpm +python3-libs-3.9.19-18.cm2.x86_64.rpm +python3-setuptools-3.9.19-18.cm2.noarch.rpm python3-pygments-2.4.2-7.cm2.noarch.rpm which-2.21-8.cm2.x86_64.rpm libselinux-3.2-1.cm2.x86_64.rpm diff --git a/toolkit/resources/manifests/package/toolchain_aarch64.txt b/toolkit/resources/manifests/package/toolchain_aarch64.txt index 2508bd75571..6c0f138748c 100644 --- a/toolkit/resources/manifests/package/toolchain_aarch64.txt +++ b/toolkit/resources/manifests/package/toolchain_aarch64.txt @@ -510,28 +510,28 @@ procps-ng-devel-3.3.17-2.cm2.aarch64.rpm procps-ng-lang-3.3.17-2.cm2.aarch64.rpm pyproject-rpm-macros-1.0.0~rc1-4.cm2.noarch.rpm python-markupsafe-debuginfo-2.1.0-1.cm2.aarch64.rpm -python3-3.9.19-17.cm2.aarch64.rpm +python3-3.9.19-18.cm2.aarch64.rpm python3-audit-3.0.6-8.cm2.aarch64.rpm python3-cracklib-2.9.7-5.cm2.aarch64.rpm -python3-curses-3.9.19-17.cm2.aarch64.rpm +python3-curses-3.9.19-18.cm2.aarch64.rpm python3-Cython-0.29.33-2.cm2.aarch64.rpm -python3-debuginfo-3.9.19-17.cm2.aarch64.rpm -python3-devel-3.9.19-17.cm2.aarch64.rpm +python3-debuginfo-3.9.19-18.cm2.aarch64.rpm +python3-devel-3.9.19-18.cm2.aarch64.rpm python3-gpg-1.16.0-2.cm2.aarch64.rpm python3-jinja2-3.0.3-7.cm2.noarch.rpm python3-libcap-ng-0.8.2-2.cm2.aarch64.rpm -python3-libs-3.9.19-17.cm2.aarch64.rpm +python3-libs-3.9.19-18.cm2.aarch64.rpm python3-libxml2-2.10.4-9.cm2.aarch64.rpm python3-lxml-4.9.1-1.cm2.aarch64.rpm python3-magic-5.40-3.cm2.noarch.rpm python3-markupsafe-2.1.0-1.cm2.aarch64.rpm python3-newt-0.52.21-5.cm2.aarch64.rpm -python3-pip-3.9.19-17.cm2.noarch.rpm +python3-pip-3.9.19-18.cm2.noarch.rpm python3-pygments-2.4.2-7.cm2.noarch.rpm python3-rpm-4.18.0-4.cm2.aarch64.rpm -python3-setuptools-3.9.19-17.cm2.noarch.rpm -python3-test-3.9.19-17.cm2.aarch64.rpm -python3-tools-3.9.19-17.cm2.aarch64.rpm +python3-setuptools-3.9.19-18.cm2.noarch.rpm +python3-test-3.9.19-18.cm2.aarch64.rpm +python3-tools-3.9.19-18.cm2.aarch64.rpm readline-8.1-1.cm2.aarch64.rpm readline-debuginfo-8.1-1.cm2.aarch64.rpm readline-devel-8.1-1.cm2.aarch64.rpm diff --git a/toolkit/resources/manifests/package/toolchain_x86_64.txt b/toolkit/resources/manifests/package/toolchain_x86_64.txt index e675120046f..695153c38d7 100644 --- a/toolkit/resources/manifests/package/toolchain_x86_64.txt +++ b/toolkit/resources/manifests/package/toolchain_x86_64.txt @@ -516,28 +516,28 @@ procps-ng-devel-3.3.17-2.cm2.x86_64.rpm procps-ng-lang-3.3.17-2.cm2.x86_64.rpm pyproject-rpm-macros-1.0.0~rc1-4.cm2.noarch.rpm python-markupsafe-debuginfo-2.1.0-1.cm2.x86_64.rpm -python3-3.9.19-17.cm2.x86_64.rpm +python3-3.9.19-18.cm2.x86_64.rpm python3-audit-3.0.6-8.cm2.x86_64.rpm python3-cracklib-2.9.7-5.cm2.x86_64.rpm -python3-curses-3.9.19-17.cm2.x86_64.rpm +python3-curses-3.9.19-18.cm2.x86_64.rpm python3-Cython-0.29.33-2.cm2.x86_64.rpm -python3-debuginfo-3.9.19-17.cm2.x86_64.rpm -python3-devel-3.9.19-17.cm2.x86_64.rpm +python3-debuginfo-3.9.19-18.cm2.x86_64.rpm +python3-devel-3.9.19-18.cm2.x86_64.rpm python3-gpg-1.16.0-2.cm2.x86_64.rpm python3-jinja2-3.0.3-7.cm2.noarch.rpm python3-libcap-ng-0.8.2-2.cm2.x86_64.rpm -python3-libs-3.9.19-17.cm2.x86_64.rpm +python3-libs-3.9.19-18.cm2.x86_64.rpm python3-libxml2-2.10.4-9.cm2.x86_64.rpm python3-lxml-4.9.1-1.cm2.x86_64.rpm python3-magic-5.40-3.cm2.noarch.rpm python3-markupsafe-2.1.0-1.cm2.x86_64.rpm python3-newt-0.52.21-5.cm2.x86_64.rpm -python3-pip-3.9.19-17.cm2.noarch.rpm +python3-pip-3.9.19-18.cm2.noarch.rpm python3-pygments-2.4.2-7.cm2.noarch.rpm python3-rpm-4.18.0-4.cm2.x86_64.rpm -python3-setuptools-3.9.19-17.cm2.noarch.rpm -python3-test-3.9.19-17.cm2.x86_64.rpm -python3-tools-3.9.19-17.cm2.x86_64.rpm +python3-setuptools-3.9.19-18.cm2.noarch.rpm +python3-test-3.9.19-18.cm2.x86_64.rpm +python3-tools-3.9.19-18.cm2.x86_64.rpm readline-8.1-1.cm2.x86_64.rpm readline-debuginfo-8.1-1.cm2.x86_64.rpm readline-devel-8.1-1.cm2.x86_64.rpm