diff --git a/SPECS/python3/CVE-2023-27043.patch b/SPECS/python3/CVE-2023-27043.patch new file mode 100644 index 00000000000..63484b1c420 --- /dev/null +++ b/SPECS/python3/CVE-2023-27043.patch @@ -0,0 +1,220 @@ +From 76b1e32b1d730355bd976dbe18c9dd43fafb0ea0 Mon Sep 17 00:00:00 2001 +From: Bala +Date: Thu, 30 Jan 2025 08:38:50 +0000 +Subject: [PATCH] Return empty tuple to indicate the email parsing error. + +Cut short version of original patch taken from below commit +Taking the changes only for Lib/email/utils.py + +From ee953f2b8fc12ee9b8209ab60a2f06c603e5a624 Mon Sep 17 00:00:00 2001 +From: Petr Viktorin +Date: Fri, 6 Sep 2024 13:13:54 +0200 +Subject: [PATCH] [3.9] [CVE-2023-27043] gh-102988: Reject malformed addresses + in email.parseaddr() (GH-111116) (#123769) + +Detect email address parsing errors and return empty tuple to +indicate the parsing error (old API). Add an optional 'strict' +parameter to getaddresses() and parseaddr() functions. Patch by +Thomas Dwyer. + +(cherry picked from commit 4a153a1d3b18803a684cd1bcc2cdf3ede3dbae19) + +Co-authored-by: Victor Stinner +Co-Authored-By: Thomas Dwyer + + Doc/library/email.utils.rst | 19 +- + Doc/whatsnew/3.9.rst | 10 + + Lib/email/utils.py | 151 ++++++++++++- + Lib/test/test_email/test_email.py | 204 +++++++++++++++++- + ...-10-20-15-28-08.gh-issue-102988.dStNO7.rst | 8 + + 5 files changed, 371 insertions(+), 21 deletions(-) +--- + Lib/email/utils.py | 151 ++++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 142 insertions(+), 9 deletions(-) + +diff --git a/Lib/email/utils.py b/Lib/email/utils.py +index aa949aa..af2fb14 100644 +--- a/Lib/email/utils.py ++++ b/Lib/email/utils.py +@@ -48,6 +48,7 @@ TICK = "'" + specialsre = re.compile(r'[][\\()<>@,:;".]') + escapesre = re.compile(r'[\\"]') + ++ + def _has_surrogates(s): + """Return True if s may contain surrogate-escaped binary data.""" + # This check is based on the fact that unless there are surrogates, utf8 +@@ -106,12 +107,127 @@ def formataddr(pair, charset='utf-8'): + return address + + ++def _iter_escaped_chars(addr): ++ pos = 0 ++ escape = False ++ for pos, ch in enumerate(addr): ++ if escape: ++ yield (pos, '\\' + ch) ++ escape = False ++ elif ch == '\\': ++ escape = True ++ else: ++ yield (pos, ch) ++ if escape: ++ yield (pos, '\\') ++ ++ ++def _strip_quoted_realnames(addr): ++ """Strip real names between quotes.""" ++ if '"' not in addr: ++ # Fast path ++ return addr ++ ++ start = 0 ++ open_pos = None ++ result = [] ++ for pos, ch in _iter_escaped_chars(addr): ++ if ch == '"': ++ if open_pos is None: ++ open_pos = pos ++ else: ++ if start != open_pos: ++ result.append(addr[start:open_pos]) ++ start = pos + 1 ++ open_pos = None ++ ++ if start < len(addr): ++ result.append(addr[start:]) ++ ++ return ''.join(result) + +-def getaddresses(fieldvalues): +- """Return a list of (REALNAME, EMAIL) for each fieldvalue.""" +- all = COMMASPACE.join(str(v) for v in fieldvalues) +- a = _AddressList(all) +- return a.addresslist ++ ++supports_strict_parsing = True ++ ++def getaddresses(fieldvalues, *, strict=True): ++ """Return a list of (REALNAME, EMAIL) or ('','') for each fieldvalue. ++ ++ When parsing fails for a fieldvalue, a 2-tuple of ('', '') is returned in ++ its place. ++ ++ If strict is true, use a strict parser which rejects malformed inputs. ++ """ ++ ++ # If strict is true, if the resulting list of parsed addresses is greater ++ # than the number of fieldvalues in the input list, a parsing error has ++ # occurred and consequently a list containing a single empty 2-tuple [('', ++ # '')] is returned in its place. This is done to avoid invalid output. ++ # ++ # Malformed input: getaddresses(['alice@example.com ']) ++ # Invalid output: [('', 'alice@example.com'), ('', 'bob@example.com')] ++ # Safe output: [('', '')] ++ ++ if not strict: ++ all = COMMASPACE.join(str(v) for v in fieldvalues) ++ a = _AddressList(all) ++ return a.addresslist ++ ++ fieldvalues = [str(v) for v in fieldvalues] ++ fieldvalues = _pre_parse_validation(fieldvalues) ++ addr = COMMASPACE.join(fieldvalues) ++ a = _AddressList(addr) ++ result = _post_parse_validation(a.addresslist) ++ ++ # Treat output as invalid if the number of addresses is not equal to the ++ # expected number of addresses. ++ n = 0 ++ for v in fieldvalues: ++ # When a comma is used in the Real Name part it is not a deliminator. ++ # So strip those out before counting the commas. ++ v = _strip_quoted_realnames(v) ++ # Expected number of addresses: 1 + number of commas ++ n += 1 + v.count(',') ++ if len(result) != n: ++ return [('', '')] ++ ++ return result ++ ++ ++def _check_parenthesis(addr): ++ # Ignore parenthesis in quoted real names. ++ addr = _strip_quoted_realnames(addr) ++ ++ opens = 0 ++ for pos, ch in _iter_escaped_chars(addr): ++ if ch == '(': ++ opens += 1 ++ elif ch == ')': ++ opens -= 1 ++ if opens < 0: ++ return False ++ return (opens == 0) ++ ++ ++def _pre_parse_validation(email_header_fields): ++ accepted_values = [] ++ for v in email_header_fields: ++ if not _check_parenthesis(v): ++ v = "('', '')" ++ accepted_values.append(v) ++ ++ return accepted_values ++ ++ ++def _post_parse_validation(parsed_email_header_tuples): ++ accepted_values = [] ++ # The parser would have parsed a correctly formatted domain-literal ++ # The existence of an [ after parsing indicates a parsing failure ++ for v in parsed_email_header_tuples: ++ if '[' in v[1]: ++ v = ('', '') ++ accepted_values.append(v) ++ ++ return accepted_values + + + def _format_timetuple_and_zone(timetuple, zone): +@@ -205,16 +321,33 @@ def parsedate_to_datetime(data): + tzinfo=datetime.timezone(datetime.timedelta(seconds=tz))) + + +-def parseaddr(addr): ++def parseaddr(addr, *, strict=True): + """ + Parse addr into its constituent realname and email address parts. + + Return a tuple of realname and email address, unless the parse fails, in + which case return a 2-tuple of ('', ''). ++ ++ If strict is True, use a strict parser which rejects malformed inputs. + """ +- addrs = _AddressList(addr).addresslist +- if not addrs: +- return '', '' ++ if not strict: ++ addrs = _AddressList(addr).addresslist ++ if not addrs: ++ return ('', '') ++ return addrs[0] ++ ++ if isinstance(addr, list): ++ addr = addr[0] ++ ++ if not isinstance(addr, str): ++ return ('', '') ++ ++ addr = _pre_parse_validation([addr])[0] ++ addrs = _post_parse_validation(_AddressList(addr).addresslist) ++ ++ if not addrs or len(addrs) > 1: ++ return ('', '') ++ + return addrs[0] + + +-- +2.40.4 + diff --git a/SPECS/python3/python3.spec b/SPECS/python3/python3.spec index 21e9ec6b808..28223ac0ac8 100644 --- a/SPECS/python3/python3.spec +++ b/SPECS/python3/python3.spec @@ -6,7 +6,7 @@ Summary: A high-level scripting language Name: python3 Version: 3.12.3 -Release: 5%{?dist} +Release: 6%{?dist} License: PSF Vendor: Microsoft Corporation Distribution: Azure Linux @@ -22,6 +22,7 @@ Patch2: CVE-2024-6923.patch Patch3: CVE-2024-6232.patch Patch4: CVE-2024-8088.patch Patch5: CVE-2024-12254.patch +Patch6: CVE-2023-27043.patch BuildRequires: bzip2-devel BuildRequires: expat-devel >= 2.1.0 @@ -243,6 +244,9 @@ rm -rf %{buildroot}%{_bindir}/__pycache__ %{_libdir}/python%{majmin}/test/* %changelog +* Thu Jan 30 2025 Bala - 3.12.3-6 +- Patch CVE-2023-27043 + * Mon Dec 10 2024 Ankita Pareek - 3.12.3-5 - Patch CVE-2024-12254 diff --git a/toolkit/resources/manifests/package/pkggen_core_aarch64.txt b/toolkit/resources/manifests/package/pkggen_core_aarch64.txt index fde8bbe49eb..03e3bb02eee 100644 --- a/toolkit/resources/manifests/package/pkggen_core_aarch64.txt +++ b/toolkit/resources/manifests/package/pkggen_core_aarch64.txt @@ -240,9 +240,9 @@ ca-certificates-base-3.0.0-8.azl3.noarch.rpm ca-certificates-3.0.0-8.azl3.noarch.rpm dwz-0.14-2.azl3.aarch64.rpm unzip-6.0-21.azl3.aarch64.rpm -python3-3.12.3-5.azl3.aarch64.rpm -python3-devel-3.12.3-5.azl3.aarch64.rpm -python3-libs-3.12.3-5.azl3.aarch64.rpm +python3-3.12.3-6.azl3.aarch64.rpm +python3-devel-3.12.3-6.azl3.aarch64.rpm +python3-libs-3.12.3-6.azl3.aarch64.rpm python3-setuptools-69.0.3-4.azl3.noarch.rpm python3-pygments-2.7.4-2.azl3.noarch.rpm which-2.21-8.azl3.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 a0ebff76e7b..06b70e7a90b 100644 --- a/toolkit/resources/manifests/package/pkggen_core_x86_64.txt +++ b/toolkit/resources/manifests/package/pkggen_core_x86_64.txt @@ -240,9 +240,9 @@ ca-certificates-base-3.0.0-8.azl3.noarch.rpm ca-certificates-3.0.0-8.azl3.noarch.rpm dwz-0.14-2.azl3.x86_64.rpm unzip-6.0-21.azl3.x86_64.rpm -python3-3.12.3-5.azl3.x86_64.rpm -python3-devel-3.12.3-5.azl3.x86_64.rpm -python3-libs-3.12.3-5.azl3.x86_64.rpm +python3-3.12.3-6.azl3.x86_64.rpm +python3-devel-3.12.3-6.azl3.x86_64.rpm +python3-libs-3.12.3-6.azl3.x86_64.rpm python3-setuptools-69.0.3-4.azl3.noarch.rpm python3-pygments-2.7.4-2.azl3.noarch.rpm which-2.21-8.azl3.x86_64.rpm diff --git a/toolkit/resources/manifests/package/toolchain_aarch64.txt b/toolkit/resources/manifests/package/toolchain_aarch64.txt index 6843fd6ac0a..c4a5e53a7e1 100644 --- a/toolkit/resources/manifests/package/toolchain_aarch64.txt +++ b/toolkit/resources/manifests/package/toolchain_aarch64.txt @@ -529,18 +529,18 @@ pyproject-rpm-macros-1.12.0-2.azl3.noarch.rpm pyproject-srpm-macros-1.12.0-2.azl3.noarch.rpm python-markupsafe-debuginfo-2.1.3-1.azl3.aarch64.rpm python-wheel-wheel-0.43.0-1.azl3.noarch.rpm -python3-3.12.3-5.azl3.aarch64.rpm +python3-3.12.3-6.azl3.aarch64.rpm python3-audit-3.1.2-1.azl3.aarch64.rpm python3-cracklib-2.9.11-1.azl3.aarch64.rpm -python3-curses-3.12.3-5.azl3.aarch64.rpm +python3-curses-3.12.3-6.azl3.aarch64.rpm python3-Cython-3.0.5-2.azl3.aarch64.rpm -python3-debuginfo-3.12.3-5.azl3.aarch64.rpm -python3-devel-3.12.3-5.azl3.aarch64.rpm +python3-debuginfo-3.12.3-6.azl3.aarch64.rpm +python3-devel-3.12.3-6.azl3.aarch64.rpm python3-flit-core-3.9.0-1.azl3.noarch.rpm python3-gpg-1.23.2-2.azl3.aarch64.rpm python3-jinja2-3.1.2-2.azl3.noarch.rpm python3-libcap-ng-0.8.4-1.azl3.aarch64.rpm -python3-libs-3.12.3-5.azl3.aarch64.rpm +python3-libs-3.12.3-6.azl3.aarch64.rpm python3-libxml2-2.11.5-3.azl3.aarch64.rpm python3-lxml-4.9.3-1.azl3.aarch64.rpm python3-magic-5.45-1.azl3.noarch.rpm @@ -552,8 +552,8 @@ python3-pygments-2.7.4-2.azl3.noarch.rpm python3-rpm-4.18.2-1.azl3.aarch64.rpm python3-rpm-generators-14-11.azl3.noarch.rpm python3-setuptools-69.0.3-4.azl3.noarch.rpm -python3-test-3.12.3-5.azl3.aarch64.rpm -python3-tools-3.12.3-5.azl3.aarch64.rpm +python3-test-3.12.3-6.azl3.aarch64.rpm +python3-tools-3.12.3-6.azl3.aarch64.rpm python3-wheel-0.43.0-1.azl3.noarch.rpm readline-8.2-1.azl3.aarch64.rpm readline-debuginfo-8.2-1.azl3.aarch64.rpm diff --git a/toolkit/resources/manifests/package/toolchain_x86_64.txt b/toolkit/resources/manifests/package/toolchain_x86_64.txt index 425ec0eb9e3..93ce93fe78e 100644 --- a/toolkit/resources/manifests/package/toolchain_x86_64.txt +++ b/toolkit/resources/manifests/package/toolchain_x86_64.txt @@ -537,18 +537,18 @@ pyproject-rpm-macros-1.12.0-2.azl3.noarch.rpm pyproject-srpm-macros-1.12.0-2.azl3.noarch.rpm python-markupsafe-debuginfo-2.1.3-1.azl3.x86_64.rpm python-wheel-wheel-0.43.0-1.azl3.noarch.rpm -python3-3.12.3-5.azl3.x86_64.rpm +python3-3.12.3-6.azl3.x86_64.rpm python3-audit-3.1.2-1.azl3.x86_64.rpm python3-cracklib-2.9.11-1.azl3.x86_64.rpm -python3-curses-3.12.3-5.azl3.x86_64.rpm +python3-curses-3.12.3-6.azl3.x86_64.rpm python3-Cython-3.0.5-2.azl3.x86_64.rpm -python3-debuginfo-3.12.3-5.azl3.x86_64.rpm -python3-devel-3.12.3-5.azl3.x86_64.rpm +python3-debuginfo-3.12.3-6.azl3.x86_64.rpm +python3-devel-3.12.3-6.azl3.x86_64.rpm python3-flit-core-3.9.0-1.azl3.noarch.rpm python3-gpg-1.23.2-2.azl3.x86_64.rpm python3-jinja2-3.1.2-2.azl3.noarch.rpm python3-libcap-ng-0.8.4-1.azl3.x86_64.rpm -python3-libs-3.12.3-5.azl3.x86_64.rpm +python3-libs-3.12.3-6.azl3.x86_64.rpm python3-libxml2-2.11.5-3.azl3.x86_64.rpm python3-lxml-4.9.3-1.azl3.x86_64.rpm python3-magic-5.45-1.azl3.noarch.rpm @@ -560,8 +560,8 @@ python3-pygments-2.7.4-2.azl3.noarch.rpm python3-rpm-4.18.2-1.azl3.x86_64.rpm python3-rpm-generators-14-11.azl3.noarch.rpm python3-setuptools-69.0.3-4.azl3.noarch.rpm -python3-test-3.12.3-5.azl3.x86_64.rpm -python3-tools-3.12.3-5.azl3.x86_64.rpm +python3-test-3.12.3-6.azl3.x86_64.rpm +python3-tools-3.12.3-6.azl3.x86_64.rpm python3-wheel-0.43.0-1.azl3.noarch.rpm readline-8.2-1.azl3.x86_64.rpm readline-debuginfo-8.2-1.azl3.x86_64.rpm