forked from pool/python314
Compare commits
1 Commits
| Author | SHA256 | Date | |
|---|---|---|---|
| 990b2813e1 |
@@ -1,104 +0,0 @@
|
||||
From 5a8bfd878f086e28f0849bbc3970ad92f6ba37dc Mon Sep 17 00:00:00 2001
|
||||
From: Seth Michael Larson <seth@python.org>
|
||||
Date: Fri, 23 Jan 2026 08:59:35 -0600
|
||||
Subject: [PATCH] gh-144125: email: verify headers are sound in BytesGenerator
|
||||
(cherry picked from commit 052e55e7d44718fe46cbba0ca995cb8fcc359413)
|
||||
|
||||
Co-authored-by: Seth Michael Larson <seth@python.org>
|
||||
Co-authored-by: Denis Ledoux <dle@odoo.com>
|
||||
Co-authored-by: Denis Ledoux <5822488+beledouxdenis@users.noreply.github.com>
|
||||
Co-authored-by: Petr Viktorin <302922+encukou@users.noreply.github.com>
|
||||
Co-authored-by: Bas Bloemsaat <1586868+basbloemsaat@users.noreply.github.com>
|
||||
---
|
||||
Lib/email/generator.py | 12 +++++++++-
|
||||
Lib/test/test_email/test_generator.py | 4 ++-
|
||||
Lib/test/test_email/test_policy.py | 6 ++++-
|
||||
Misc/NEWS.d/next/Security/2026-01-21-12-34-05.gh-issue-144125.TAz5uo.rst | 4 +++
|
||||
4 files changed, 23 insertions(+), 3 deletions(-)
|
||||
create mode 100644 Misc/NEWS.d/next/Security/2026-01-21-12-34-05.gh-issue-144125.TAz5uo.rst
|
||||
|
||||
Index: Python-3.14.2/Lib/email/generator.py
|
||||
===================================================================
|
||||
--- Python-3.14.2.orig/Lib/email/generator.py 2026-01-28 22:15:51.075267925 +0100
|
||||
+++ Python-3.14.2/Lib/email/generator.py 2026-01-28 22:15:56.251194626 +0100
|
||||
@@ -22,6 +22,7 @@
|
||||
NLCRE = re.compile(r'\r\n|\r|\n')
|
||||
fcre = re.compile(r'^From ', re.MULTILINE)
|
||||
NEWLINE_WITHOUT_FWSP = re.compile(r'\r\n[^ \t]|\r[^ \n\t]|\n[^ \t]')
|
||||
+NEWLINE_WITHOUT_FWSP_BYTES = re.compile(br'\r\n[^ \t]|\r[^ \n\t]|\n[^ \t]')
|
||||
|
||||
|
||||
class Generator:
|
||||
@@ -429,7 +430,16 @@
|
||||
# This is almost the same as the string version, except for handling
|
||||
# strings with 8bit bytes.
|
||||
for h, v in msg.raw_items():
|
||||
- self._fp.write(self.policy.fold_binary(h, v))
|
||||
+ folded = self.policy.fold_binary(h, v)
|
||||
+ if self.policy.verify_generated_headers:
|
||||
+ linesep = self.policy.linesep.encode()
|
||||
+ if not folded.endswith(linesep):
|
||||
+ raise HeaderWriteError(
|
||||
+ f'folded header does not end with {linesep!r}: {folded!r}')
|
||||
+ if NEWLINE_WITHOUT_FWSP_BYTES.search(folded.removesuffix(linesep)):
|
||||
+ raise HeaderWriteError(
|
||||
+ f'folded header contains newline: {folded!r}')
|
||||
+ self._fp.write(folded)
|
||||
# A blank line always separates headers from body
|
||||
self.write(self._NL)
|
||||
|
||||
Index: Python-3.14.2/Lib/test/test_email/test_generator.py
|
||||
===================================================================
|
||||
--- Python-3.14.2.orig/Lib/test/test_email/test_generator.py 2026-01-28 22:15:52.693627763 +0100
|
||||
+++ Python-3.14.2/Lib/test/test_email/test_generator.py 2026-01-28 22:15:56.251344799 +0100
|
||||
@@ -313,7 +313,7 @@
|
||||
self.assertEqual(s.getvalue(), self.typ(expected))
|
||||
|
||||
def test_verify_generated_headers(self):
|
||||
- """gh-121650: by default the generator prevents header injection"""
|
||||
+ # gh-121650: by default the generator prevents header injection
|
||||
class LiteralHeader(str):
|
||||
name = 'Header'
|
||||
def fold(self, **kwargs):
|
||||
@@ -334,6 +334,8 @@
|
||||
|
||||
with self.assertRaises(email.errors.HeaderWriteError):
|
||||
message.as_string()
|
||||
+ with self.assertRaises(email.errors.HeaderWriteError):
|
||||
+ message.as_bytes()
|
||||
|
||||
|
||||
class TestBytesGenerator(TestGeneratorBase, TestEmailBase):
|
||||
Index: Python-3.14.2/Lib/test/test_email/test_policy.py
|
||||
===================================================================
|
||||
--- Python-3.14.2.orig/Lib/test/test_email/test_policy.py 2026-01-28 22:15:52.703671956 +0100
|
||||
+++ Python-3.14.2/Lib/test/test_email/test_policy.py 2026-01-28 22:15:56.251499922 +0100
|
||||
@@ -296,7 +296,7 @@
|
||||
policy.fold("Subject", subject)
|
||||
|
||||
def test_verify_generated_headers(self):
|
||||
- """Turning protection off allows header injection"""
|
||||
+ # Turning protection off allows header injection
|
||||
policy = email.policy.default.clone(verify_generated_headers=False)
|
||||
for text in (
|
||||
'Header: Value\r\nBad: Injection\r\n',
|
||||
@@ -319,6 +319,10 @@
|
||||
message.as_string(),
|
||||
f"{text}\nBody",
|
||||
)
|
||||
+ self.assertEqual(
|
||||
+ message.as_bytes(),
|
||||
+ f"{text}\nBody".encode(),
|
||||
+ )
|
||||
|
||||
# XXX: Need subclassing tests.
|
||||
# For adding subclassed objects, make sure the usual rules apply (subclass
|
||||
Index: Python-3.14.2/Misc/NEWS.d/next/Security/2026-01-21-12-34-05.gh-issue-144125.TAz5uo.rst
|
||||
===================================================================
|
||||
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ Python-3.14.2/Misc/NEWS.d/next/Security/2026-01-21-12-34-05.gh-issue-144125.TAz5uo.rst 2026-01-28 22:15:56.251667056 +0100
|
||||
@@ -0,0 +1,4 @@
|
||||
+:mod:`~email.generator.BytesGenerator` will now refuse to serialize (write) headers
|
||||
+that are unsafely folded or delimited; see
|
||||
+:attr:`~email.policy.Policy.verify_generated_headers`. (Contributed by Bas
|
||||
+Bloemsaat and Petr Viktorin in :gh:`121650`).
|
||||
@@ -1,109 +0,0 @@
|
||||
From df45bd1aafc3b6792d43661207d2b7eb3a14d214 Mon Sep 17 00:00:00 2001
|
||||
From: Seth Michael Larson <seth@python.org>
|
||||
Date: Mon, 19 Jan 2026 06:38:22 -0600
|
||||
Subject: [PATCH] gh-143935: Email preserve parens when folding comments
|
||||
(GH-143936)
|
||||
|
||||
Fix a bug in the folding of comments when flattening an email message
|
||||
using a modern email policy. Comments consisting of a very long sequence of
|
||||
non-foldable characters could trigger a forced line wrap that omitted the
|
||||
required leading space on the continuation line, causing the remainder of
|
||||
the comment to be interpreted as a new header field. This enabled header
|
||||
injection with carefully crafted inputs.
|
||||
(cherry picked from commit 17d1490aa97bd6b98a42b1a9b324ead84e7fd8a2)
|
||||
|
||||
Co-authored-by: Seth Michael Larson <seth@python.org>
|
||||
Co-authored-by: Denis Ledoux <dle@odoo.com>
|
||||
---
|
||||
Lib/email/_header_value_parser.py | 15 +++++++++++-
|
||||
.../test_email/test__header_value_parser.py | 23 +++++++++++++++++++
|
||||
...-01-16-14-40-31.gh-issue-143935.U2YtKl.rst | 6 +++++
|
||||
3 files changed, 43 insertions(+), 1 deletion(-)
|
||||
create mode 100644 Misc/NEWS.d/next/Security/2026-01-16-14-40-31.gh-issue-143935.U2YtKl.rst
|
||||
|
||||
diff --git a/Lib/email/_header_value_parser.py b/Lib/email/_header_value_parser.py
|
||||
index 68c2cf9585c5b4..51727688c059ed 100644
|
||||
--- a/Lib/email/_header_value_parser.py
|
||||
+++ b/Lib/email/_header_value_parser.py
|
||||
@@ -101,6 +101,12 @@ def make_quoted_pairs(value):
|
||||
return str(value).replace('\\', '\\\\').replace('"', '\\"')
|
||||
|
||||
|
||||
+def make_parenthesis_pairs(value):
|
||||
+ """Escape parenthesis and backslash for use within a comment."""
|
||||
+ return str(value).replace('\\', '\\\\') \
|
||||
+ .replace('(', '\\(').replace(')', '\\)')
|
||||
+
|
||||
+
|
||||
def quote_string(value):
|
||||
escaped = make_quoted_pairs(value)
|
||||
return f'"{escaped}"'
|
||||
@@ -939,7 +945,7 @@ def value(self):
|
||||
return ' '
|
||||
|
||||
def startswith_fws(self):
|
||||
- return True
|
||||
+ return self and self[0] in WSP
|
||||
|
||||
|
||||
class ValueTerminal(Terminal):
|
||||
@@ -2959,6 +2965,13 @@ def _refold_parse_tree(parse_tree, *, policy):
|
||||
[ValueTerminal(make_quoted_pairs(p), 'ptext')
|
||||
for p in newparts] +
|
||||
[ValueTerminal('"', 'ptext')])
|
||||
+ if part.token_type == 'comment':
|
||||
+ newparts = (
|
||||
+ [ValueTerminal('(', 'ptext')] +
|
||||
+ [ValueTerminal(make_parenthesis_pairs(p), 'ptext')
|
||||
+ if p.token_type == 'ptext' else p
|
||||
+ for p in newparts] +
|
||||
+ [ValueTerminal(')', 'ptext')])
|
||||
if not part.as_ew_allowed:
|
||||
wrap_as_ew_blocked += 1
|
||||
newparts.append(end_ew_not_allowed)
|
||||
diff --git a/Lib/test/test_email/test__header_value_parser.py b/Lib/test/test_email/test__header_value_parser.py
|
||||
index 426ec4644e3096..e28fe3892015b9 100644
|
||||
--- a/Lib/test/test_email/test__header_value_parser.py
|
||||
+++ b/Lib/test/test_email/test__header_value_parser.py
|
||||
@@ -3294,6 +3294,29 @@ def test_address_list_with_specials_in_long_quoted_string(self):
|
||||
with self.subTest(to=to):
|
||||
self._test(parser.get_address_list(to)[0], folded, policy=policy)
|
||||
|
||||
+ def test_address_list_with_long_unwrapable_comment(self):
|
||||
+ policy = self.policy.clone(max_line_length=40)
|
||||
+ cases = [
|
||||
+ # (to, folded)
|
||||
+ ('(loremipsumdolorsitametconsecteturadipi)<spy@example.org>',
|
||||
+ '(loremipsumdolorsitametconsecteturadipi)<spy@example.org>\n'),
|
||||
+ ('<spy@example.org>(loremipsumdolorsitametconsecteturadipi)',
|
||||
+ '<spy@example.org>(loremipsumdolorsitametconsecteturadipi)\n'),
|
||||
+ ('(loremipsum dolorsitametconsecteturadipi)<spy@example.org>',
|
||||
+ '(loremipsum dolorsitametconsecteturadipi)<spy@example.org>\n'),
|
||||
+ ('<spy@example.org>(loremipsum dolorsitametconsecteturadipi)',
|
||||
+ '<spy@example.org>(loremipsum\n dolorsitametconsecteturadipi)\n'),
|
||||
+ ('(Escaped \\( \\) chars \\\\ in comments stay escaped)<spy@example.org>',
|
||||
+ '(Escaped \\( \\) chars \\\\ in comments stay\n escaped)<spy@example.org>\n'),
|
||||
+ ('((loremipsum)(loremipsum)(loremipsum)(loremipsum))<spy@example.org>',
|
||||
+ '((loremipsum)(loremipsum)(loremipsum)(loremipsum))<spy@example.org>\n'),
|
||||
+ ('((loremipsum)(loremipsum)(loremipsum) (loremipsum))<spy@example.org>',
|
||||
+ '((loremipsum)(loremipsum)(loremipsum)\n (loremipsum))<spy@example.org>\n'),
|
||||
+ ]
|
||||
+ for (to, folded) in cases:
|
||||
+ with self.subTest(to=to):
|
||||
+ self._test(parser.get_address_list(to)[0], folded, policy=policy)
|
||||
+
|
||||
# XXX Need tests with comments on various sides of a unicode token,
|
||||
# and with unicode tokens in the comments. Spaces inside the quotes
|
||||
# currently don't do the right thing.
|
||||
diff --git a/Misc/NEWS.d/next/Security/2026-01-16-14-40-31.gh-issue-143935.U2YtKl.rst b/Misc/NEWS.d/next/Security/2026-01-16-14-40-31.gh-issue-143935.U2YtKl.rst
|
||||
new file mode 100644
|
||||
index 00000000000000..c3d864936884ac
|
||||
--- /dev/null
|
||||
+++ b/Misc/NEWS.d/next/Security/2026-01-16-14-40-31.gh-issue-143935.U2YtKl.rst
|
||||
@@ -0,0 +1,6 @@
|
||||
+Fixed a bug in the folding of comments when flattening an email message
|
||||
+using a modern email policy. Comments consisting of a very long sequence of
|
||||
+non-foldable characters could trigger a forced line wrap that omitted the
|
||||
+required leading space on the continuation line, causing the remainder of
|
||||
+the comment to be interpreted as a new header field. This enabled header
|
||||
+injection with carefully crafted inputs.
|
||||
212
gh138498-llvm-version-config.patch
Normal file
212
gh138498-llvm-version-config.patch
Normal file
@@ -0,0 +1,212 @@
|
||||
Index: Python-3.14.0/Tools/jit/README.md
|
||||
===================================================================
|
||||
--- Python-3.14.0.orig/Tools/jit/README.md
|
||||
+++ Python-3.14.0/Tools/jit/README.md
|
||||
@@ -9,7 +9,7 @@ Python 3.11 or newer is required to buil
|
||||
|
||||
The JIT compiler does not require end users to install any third-party dependencies, but part of it must be *built* using LLVM[^why-llvm]. You are *not* required to build the rest of CPython using LLVM, or even the same version of LLVM (in fact, this is uncommon).
|
||||
|
||||
-LLVM version 19 is required. Both `clang` and `llvm-readobj` need to be installed and discoverable (version suffixes, like `clang-19`, are okay). It's highly recommended that you also have `llvm-objdump` available, since this allows the build script to dump human-readable assembly for the generated code.
|
||||
+LLVM version 19 is the officially supported version. You can modify if needed using the `LLVM_VERSION` env var during configure. Both `clang` and `llvm-readobj` need to be installed and discoverable (version suffixes, like `clang-19`, are okay). It's highly recommended that you also have `llvm-objdump` available, since this allows the build script to dump human-readable assembly for the generated code.
|
||||
|
||||
It's easy to install all of the required tools:
|
||||
|
||||
Index: Python-3.14.0/Tools/jit/_llvm.py
|
||||
===================================================================
|
||||
--- Python-3.14.0.orig/Tools/jit/_llvm.py
|
||||
+++ Python-3.14.0/Tools/jit/_llvm.py
|
||||
@@ -10,8 +10,8 @@ import typing
|
||||
|
||||
import _targets
|
||||
|
||||
-_LLVM_VERSION = 19
|
||||
-_LLVM_VERSION_PATTERN = re.compile(rf"version\s+{_LLVM_VERSION}\.\d+\.\d+\S*\s+")
|
||||
+
|
||||
+_LLVM_VERSION = "19"
|
||||
_EXTERNALS_LLVM_TAG = "llvm-19.1.7.0"
|
||||
|
||||
_P = typing.ParamSpec("_P")
|
||||
@@ -56,53 +56,66 @@ async def _run(tool: str, args: typing.I
|
||||
|
||||
|
||||
@_async_cache
|
||||
-async def _check_tool_version(name: str, *, echo: bool = False) -> bool:
|
||||
+async def _check_tool_version(
|
||||
+ name: str, llvm_version: str, *, echo: bool = False
|
||||
+) -> bool:
|
||||
output = await _run(name, ["--version"], echo=echo)
|
||||
- return bool(output and _LLVM_VERSION_PATTERN.search(output))
|
||||
+ _llvm_version_pattern = re.compile(rf"version\s+{llvm_version}\.\d+\.\d+\S*\s+")
|
||||
+ return bool(output and _llvm_version_pattern.search(output))
|
||||
|
||||
|
||||
@_async_cache
|
||||
-async def _get_brew_llvm_prefix(*, echo: bool = False) -> str | None:
|
||||
- output = await _run("brew", ["--prefix", f"llvm@{_LLVM_VERSION}"], echo=echo)
|
||||
+async def _get_brew_llvm_prefix(llvm_version: str, *, echo: bool = False) -> str | None:
|
||||
+ output = await _run("brew", ["--prefix", f"llvm@{llvm_version}"], echo=echo)
|
||||
return output and output.removesuffix("\n")
|
||||
|
||||
|
||||
@_async_cache
|
||||
-async def _find_tool(tool: str, *, echo: bool = False) -> str | None:
|
||||
+async def _find_tool(tool: str, llvm_version: str, *, echo: bool = False) -> str | None:
|
||||
# Unversioned executables:
|
||||
path = tool
|
||||
- if await _check_tool_version(path, echo=echo):
|
||||
+ if await _check_tool_version(path, llvm_version, echo=echo):
|
||||
return path
|
||||
# Versioned executables:
|
||||
- path = f"{tool}-{_LLVM_VERSION}"
|
||||
- if await _check_tool_version(path, echo=echo):
|
||||
+ path = f"{tool}-{llvm_version}"
|
||||
+ if await _check_tool_version(path, llvm_version, echo=echo):
|
||||
return path
|
||||
# PCbuild externals:
|
||||
externals = os.environ.get("EXTERNALS_DIR", _targets.EXTERNALS)
|
||||
path = os.path.join(externals, _EXTERNALS_LLVM_TAG, "bin", tool)
|
||||
- if await _check_tool_version(path, echo=echo):
|
||||
+ if await _check_tool_version(path, llvm_version, echo=echo):
|
||||
return path
|
||||
# Homebrew-installed executables:
|
||||
- prefix = await _get_brew_llvm_prefix(echo=echo)
|
||||
+ prefix = await _get_brew_llvm_prefix(llvm_version, echo=echo)
|
||||
if prefix is not None:
|
||||
path = os.path.join(prefix, "bin", tool)
|
||||
- if await _check_tool_version(path, echo=echo):
|
||||
+ if await _check_tool_version(path, llvm_version, echo=echo):
|
||||
return path
|
||||
# Nothing found:
|
||||
return None
|
||||
|
||||
|
||||
async def maybe_run(
|
||||
- tool: str, args: typing.Iterable[str], echo: bool = False
|
||||
+ tool: str,
|
||||
+ args: typing.Iterable[str],
|
||||
+ echo: bool = False,
|
||||
+ llvm_version: str = _LLVM_VERSION,
|
||||
) -> str | None:
|
||||
"""Run an LLVM tool if it can be found. Otherwise, return None."""
|
||||
- path = await _find_tool(tool, echo=echo)
|
||||
+
|
||||
+ path = await _find_tool(tool, llvm_version, echo=echo)
|
||||
return path and await _run(path, args, echo=echo)
|
||||
|
||||
|
||||
-async def run(tool: str, args: typing.Iterable[str], echo: bool = False) -> str:
|
||||
+async def run(
|
||||
+ tool: str,
|
||||
+ args: typing.Iterable[str],
|
||||
+ echo: bool = False,
|
||||
+ llvm_version: str = _LLVM_VERSION,
|
||||
+) -> str:
|
||||
"""Run an LLVM tool if it can be found. Otherwise, raise RuntimeError."""
|
||||
- output = await maybe_run(tool, args, echo=echo)
|
||||
+
|
||||
+ output = await maybe_run(tool, args, echo=echo, llvm_version=llvm_version)
|
||||
if output is None:
|
||||
- raise RuntimeError(f"Can't find {tool}-{_LLVM_VERSION}!")
|
||||
+ raise RuntimeError(f"Can't find {tool}-{llvm_version}!")
|
||||
return output
|
||||
Index: Python-3.14.0/Tools/jit/_targets.py
|
||||
===================================================================
|
||||
--- Python-3.14.0.orig/Tools/jit/_targets.py
|
||||
+++ Python-3.14.0/Tools/jit/_targets.py
|
||||
@@ -48,6 +48,7 @@ class _Target(typing.Generic[_S, _R]):
|
||||
debug: bool = False
|
||||
verbose: bool = False
|
||||
cflags: str = ""
|
||||
+ llvm_version: str = _llvm._LLVM_VERSION
|
||||
known_symbols: dict[str, int] = dataclasses.field(default_factory=dict)
|
||||
pyconfig_dir: pathlib.Path = pathlib.Path.cwd().resolve()
|
||||
|
||||
@@ -79,7 +80,9 @@ class _Target(typing.Generic[_S, _R]):
|
||||
async def _parse(self, path: pathlib.Path) -> _stencils.StencilGroup:
|
||||
group = _stencils.StencilGroup()
|
||||
args = ["--disassemble", "--reloc", f"{path}"]
|
||||
- output = await _llvm.maybe_run("llvm-objdump", args, echo=self.verbose)
|
||||
+ output = await _llvm.maybe_run(
|
||||
+ "llvm-objdump", args, echo=self.verbose, llvm_version=self.llvm_version
|
||||
+ )
|
||||
if output is not None:
|
||||
# Make sure that full paths don't leak out (for reproducibility):
|
||||
long, short = str(path), str(path.name)
|
||||
@@ -97,7 +100,9 @@ class _Target(typing.Generic[_S, _R]):
|
||||
"--sections",
|
||||
f"{path}",
|
||||
]
|
||||
- output = await _llvm.run("llvm-readobj", args, echo=self.verbose)
|
||||
+ output = await _llvm.run(
|
||||
+ "llvm-readobj", args, echo=self.verbose, llvm_version=self.llvm_version
|
||||
+ )
|
||||
# --elf-output-style=JSON is only *slightly* broken on Mach-O...
|
||||
output = output.replace("PrivateExtern\n", "\n")
|
||||
output = output.replace("Extern\n", "\n")
|
||||
@@ -164,7 +169,9 @@ class _Target(typing.Generic[_S, _R]):
|
||||
# Allow user-provided CFLAGS to override any defaults
|
||||
*shlex.split(self.cflags),
|
||||
]
|
||||
- await _llvm.run("clang", args, echo=self.verbose)
|
||||
+ await _llvm.run(
|
||||
+ "clang", args, echo=self.verbose, llvm_version=self.llvm_version
|
||||
+ )
|
||||
return await self._parse(o)
|
||||
|
||||
async def _build_stencils(self) -> dict[str, _stencils.StencilGroup]:
|
||||
@@ -212,6 +219,8 @@ class _Target(typing.Generic[_S, _R]):
|
||||
if not self.stable:
|
||||
warning = f"JIT support for {self.triple} is still experimental!"
|
||||
request = "Please report any issues you encounter.".center(len(warning))
|
||||
+ if self.llvm_version != _llvm._LLVM_VERSION:
|
||||
+ request = f"Warning! Building with an LLVM version other than {_llvm._LLVM_VERSION} is not supported."
|
||||
outline = "=" * len(warning)
|
||||
print("\n".join(["", outline, warning, request, outline, ""]))
|
||||
digest = f"// {self._compute_digest()}\n"
|
||||
Index: Python-3.14.0/Tools/jit/build.py
|
||||
===================================================================
|
||||
--- Python-3.14.0.orig/Tools/jit/build.py
|
||||
+++ Python-3.14.0/Tools/jit/build.py
|
||||
@@ -42,6 +42,7 @@ if __name__ == "__main__":
|
||||
parser.add_argument(
|
||||
"--cflags", help="additional flags to pass to the compiler", default=""
|
||||
)
|
||||
+ parser.add_argument("--llvm-version", help="LLVM version to use")
|
||||
args = parser.parse_args()
|
||||
for target in args.target:
|
||||
target.debug = args.debug
|
||||
@@ -49,6 +50,8 @@ if __name__ == "__main__":
|
||||
target.verbose = args.verbose
|
||||
target.cflags = args.cflags
|
||||
target.pyconfig_dir = args.pyconfig_dir
|
||||
+ if args.llvm_version:
|
||||
+ target.llvm_version = args.llvm_version
|
||||
target.build(
|
||||
comment=comment,
|
||||
force=args.force,
|
||||
Index: Python-3.14.0/configure
|
||||
===================================================================
|
||||
--- Python-3.14.0.orig/configure
|
||||
+++ Python-3.14.0/configure
|
||||
@@ -10866,7 +10866,7 @@ then :
|
||||
|
||||
else case e in #(
|
||||
e) as_fn_append CFLAGS_NODIST " $jit_flags"
|
||||
- REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir . --cflags=\"$CFLAGS_JIT\""
|
||||
+ REGEN_JIT_COMMAND="\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir . --cflags=\"$CFLAGS_JIT\" --llvm-version=\"$LLVM_VERSION\""
|
||||
JIT_STENCILS_H="jit_stencils.h"
|
||||
if test "x$Py_DEBUG" = xtrue
|
||||
then :
|
||||
Index: Python-3.14.0/configure.ac
|
||||
===================================================================
|
||||
--- Python-3.14.0.orig/configure.ac
|
||||
+++ Python-3.14.0/configure.ac
|
||||
@@ -2779,7 +2779,7 @@ AS_VAR_IF([jit_flags],
|
||||
[],
|
||||
[AS_VAR_APPEND([CFLAGS_NODIST], [" $jit_flags"])
|
||||
AS_VAR_SET([REGEN_JIT_COMMAND],
|
||||
- ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir . --cflags=\"$CFLAGS_JIT\""])
|
||||
+ ["\$(PYTHON_FOR_REGEN) \$(srcdir)/Tools/jit/build.py ${ARCH_TRIPLES:-$host} --output-dir . --pyconfig-dir . --cflags=\"$CFLAGS_JIT\" --llvm-version=\"$LLVM_VERSION\""])
|
||||
AS_VAR_SET([JIT_STENCILS_H], ["jit_stencils.h"])
|
||||
AS_VAR_IF([Py_DEBUG],
|
||||
[true],
|
||||
4
python314-base.rpmlintrc
Normal file
4
python314-base.rpmlintrc
Normal file
@@ -0,0 +1,4 @@
|
||||
addFilter("pem-certificate.*/usr/lib.*/python.*/test/*.pem")
|
||||
addFilter("devel-file-in-non-devel-package.*/usr/lib.*/python.*/tests/*.c")
|
||||
addFilter("devel-file-in-non-devel-package.*/usr/lib.*/python.*/test/*.cpp")
|
||||
addFilter("python-bytecode-inconsistent-mtime.*/usr/lib.*/python.*/*.pyc")
|
||||
@@ -1,4 +1,3 @@
|
||||
addFilter("pem-certificate.*/usr/lib.*/python.*/test/*.pem")
|
||||
addFilter("devel-file-in-non-devel-package.*/usr/lib.*/python.*/tests/*.c")
|
||||
addFilter("devel-file-in-non-devel-package.*/usr/lib.*/python.*/test/*.cpp")
|
||||
addFilter("python-bytecode-inconsistent-mtime.*/usr/lib.*/python.*/*.pyc")
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
-------------------------------------------------------------------
|
||||
Thu Jan 29 12:58:15 UTC 2026 - Matej Cepl <mcepl@cepl.eu>
|
||||
Thu Dec 12 07:00:00 UTC 2025 - Daniel Garcia <daniel.garcia@suse.com>
|
||||
|
||||
- Add CVE-2024-6923-follow-up-EOL-email-headers.patch which is
|
||||
a follow-up to the previous fix of CVE-2024-6923 further
|
||||
encoding EOL possibly hidden in email headers (bsc#1257181).
|
||||
- Add CVE-2025-11468-email-hdr-fold-comment.patch preserving
|
||||
parens when folding comments in email headers (bsc#1257029,
|
||||
CVE-2025-11468).
|
||||
- Use LLVM21 to build python314, add patch
|
||||
gh138498-llvm-version-config.patch
|
||||
bsc#1254826, gh#python/cpython#138498
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Thu Dec 11 17:37:09 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
|
||||
@@ -14,7 +11,7 @@ Thu Dec 11 17:37:09 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
|
||||
* Update to 3.14.2:
|
||||
- Security
|
||||
- gh-142145: Remove quadratic behavior in xml.minidom node ID
|
||||
cache clearing (CVE-2025-12084, bsc#1254997).
|
||||
cache clearing.
|
||||
- gh-119452: Fix a potential memory denial of service in the
|
||||
http.server module. When a malicious user is connected to the
|
||||
CGI server on Windows, it could cause an arbitrary amount of
|
||||
@@ -76,10 +73,10 @@ Thu Dec 11 17:37:09 UTC 2025 - Matej Cepl <mcepl@cepl.eu>
|
||||
- gh-139700: Check consistency of the zip64 end of central
|
||||
directory record. Support records with “zip64 extensible
|
||||
data” if there are no bytes prepended to the ZIP file.
|
||||
(CVE-2025-8291, bsc#1251305)
|
||||
- gh-139283: sqlite3: correctly handle maximum number of rows
|
||||
to fetch in Cursor.fetchmany and reject negative values for
|
||||
Cursor.arraysize. Patch by Bénédikt Tran.
|
||||
Cursor.arraysize. Patch by Bénédikt Tran. (CVE-2025-8291,
|
||||
bsc#1251305)
|
||||
- gh-137836: Add support of the “plaintext” element, RAWTEXT
|
||||
elements “xmp”, “iframe”, “noembed” and “noframes”, and
|
||||
optionally RAWTEXT element “noscript” in
|
||||
@@ -4682,8 +4679,7 @@ Sat Sep 7 15:36:03 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
|
||||
now refuse to serialize (write) headers
|
||||
that are unsafely folded or delimited; see
|
||||
verify_generated_headers. (Contributed by Bas Bloemsaat and
|
||||
Petr Viktorin in gh-121650.; CVE-2024-6923, bsc#1228780,
|
||||
bsc#1257181)
|
||||
Petr Viktorin in gh-121650.; CVE-2024-6923, bsc#1228780)
|
||||
- gh-121723: Make logging.config.dictConfig() accept any
|
||||
object implementing the Queue public API. See the queue
|
||||
configuration section for details. Patch by Bénédikt Tran.
|
||||
|
||||
4
python314.rpmlintrc
Normal file
4
python314.rpmlintrc
Normal file
@@ -0,0 +1,4 @@
|
||||
addFilter("pem-certificate.*/usr/lib.*/python.*/test/*.pem")
|
||||
addFilter("devel-file-in-non-devel-package.*/usr/lib.*/python.*/tests/*.c")
|
||||
addFilter("devel-file-in-non-devel-package.*/usr/lib.*/python.*/test/*.cpp")
|
||||
addFilter("python-bytecode-inconsistent-mtime.*/usr/lib.*/python.*/*.pyc")
|
||||
@@ -54,6 +54,8 @@
|
||||
%bcond_with GIL
|
||||
%endif
|
||||
|
||||
%define llvm_version 21
|
||||
|
||||
%if 0%{?do_profiling} && !0%{?want_reproducible_builds}
|
||||
%bcond_without profileopt
|
||||
%else
|
||||
@@ -209,6 +211,8 @@ Patch07: bpo-31046_ensurepip_honours_prefix.patch
|
||||
# PATCH-FIX-SLE skip-test_pyobject_freed_is_freed.patch mcepl@suse.com
|
||||
# skip a test failing on SLE-15
|
||||
Patch09: skip-test_pyobject_freed_is_freed.patch
|
||||
# PATCH-FIX-UPSTREAM gh138498-llvm-version-config gh#python/cpython#138498 daniel.garcia@suse.com
|
||||
Patch10: gh138498-llvm-version-config.patch
|
||||
# PATCH-FIX-OPENSUSE CVE-2023-52425-libexpat-2.6.0-backport-15.6.patch
|
||||
# This problem on libexpat is patched on 15.6 without version
|
||||
# update, this patch changes the tests to match the libexpat provided
|
||||
@@ -224,14 +228,7 @@ Patch41: bsc1243155-sphinx-non-determinism.patch
|
||||
Patch44: gh138131-exclude-pycache-from-digest.patch
|
||||
# PATCH-FIX-OPENSUSE gh139257-Support-docutils-0.22.patch gh#python/cpython#139257 daniel.garcia@suse.com
|
||||
Patch45: gh139257-Support-docutils-0.22.patch
|
||||
# PATCH-FIX-UPSTREAM CVE-2024-6923-follow-up-EOL-email-headers.patch bsc#1257181 mcepl@suse.com
|
||||
# Encode newlines in headers when using ByteGenerator
|
||||
# patch from gh#python/cpython#144125
|
||||
Patch46: CVE-2024-6923-follow-up-EOL-email-headers.patch
|
||||
# PATCH-FIX-UPSTREAM CVE-2025-11468-email-hdr-fold-comment.patch bsc#1257029 mcepl@suse.com
|
||||
# Email preserve parens when folding comments
|
||||
Patch47: CVE-2025-11468-email-hdr-fold-comment.patch
|
||||
#### Python 3.14 END OF PATCHES
|
||||
#### Python 3.14 DEVELOPMENT PATCHES
|
||||
BuildRequires: autoconf-archive
|
||||
BuildRequires: automake
|
||||
BuildRequires: fdupes
|
||||
@@ -276,7 +273,7 @@ BuildRequires: python3-python-docs-theme >= 2022.1
|
||||
|
||||
%if %{with experimental_jit}
|
||||
# needed for experimental_jit
|
||||
BuildRequires: clang19 llvm19
|
||||
BuildRequires: clang%{llvm_version} llvm%{llvm_version}
|
||||
BuildRequires: llvm
|
||||
%endif
|
||||
|
||||
@@ -582,6 +579,7 @@ sed -e 's/-fprofile-correction//' -i Makefile.pre.in
|
||||
%endif
|
||||
|
||||
export CFLAGS="%{optflags} -IVendor/"
|
||||
export LLVM_VERSION=%{llvm_version}
|
||||
|
||||
%configure \
|
||||
--with-platlibdir=%{_lib} \
|
||||
|
||||
Reference in New Issue
Block a user