Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python313 for openSUSE:Factory checked in at 2026-08-17 16:55:28 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python313 (Old) and /work/SRC/openSUSE:Factory/.python313.new.1258 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python313" Mon Aug 17 16:55:28 2026 rev:44 rq:1371267 version:3.13.14 Changes: -------- --- /work/SRC/openSUSE:Factory/python313/python313.changes 2026-07-22 19:01:14.229095898 +0200 +++ /work/SRC/openSUSE:Factory/.python313.new.1258/python313.changes 2026-08-17 16:55:30.414666548 +0200 @@ -1,0 +2,33 @@ +Fri Aug 7 07:23:53 UTC 2026 - Matej Cepl <[email protected]> + +- Add reproducible_stencils.patch from gh#python/cpython!154988 + +------------------------------------------------------------------- +Fri Jul 31 13:35:09 UTC 2026 - Matej Cepl <[email protected]> + +- CVE-2026-0864: Normalize all line endings (CR, CRLF, and LF) in + configparser (bsc#1269066, gh#python/cpython#143927) + CVE-2026-0864-normalize-LFTAB-configparser.patch + +------------------------------------------------------------------- +Fri Jul 31 13:22:45 UTC 2026 - Matej Cepl <[email protected]> + +- CVE-2026-11972: Make tarfile._Stream.seek break at EOF + (bsc#1269788, gh-151981) + CVE-2026-11972-tarfile-Stream-seek-EOF.patch + +------------------------------------------------------------------- +Fri Jul 31 13:07:50 UTC 2026 - Matej Cepl <[email protected]> + +- CVE-2026-4360: Pass filter_function to TarFile._extract_one() + during .extract() (bsc#1269959, gh#python/cpython#151987) + CVE-2026-4360-filter_function-TarFile-extractone.patch + +------------------------------------------------------------------- +Fri Jul 31 12:54:51 UTC 2026 - Matej Cepl <[email protected]> + +- CVE-2026-15308: Fix quadratic complexity in incremental parsing + in HTMLParser (bsc#1271192, gh#python/cpython#153030) + CVE-2026-15308-HTMLParser-CPU-exhaust.patch + +------------------------------------------------------------------- @@ -5 +38,2 @@ - hardlink-extraction fallback (bsc#1268977) + hardlink-extraction fallback (bsc#1268977, + gh#python/cpython#151558) @@ -52 +86 @@ - extraction filter. + extraction filter (bsc#1267821, CVE-2026-7774). @@ -59 +93,2 @@ - a linear-time counting sort for long runs. + a linear-time counting sort for long runs (bsc#1267581, + CVE-2026-3276). @@ -96,0 +132,5 @@ + - gh-149144: Fixes an issue introduced by CVE-2026-6019 + patch. atob() in JavaScript processes bytes as 'latin-1', + switches the encoding algorithm from base64 to percent + encoding and uses the decodeURIComponent() JavaScript API + (bsc#1263083). New: ---- CVE-2026-0864-normalize-LFTAB-configparser.patch CVE-2026-11972-tarfile-Stream-seek-EOF.patch CVE-2026-15308-HTMLParser-CPU-exhaust.patch CVE-2026-4360-filter_function-TarFile-extractone.patch reproducible_stencils.patch ----------(New B)---------- New: configparser (bsc#1269066, gh#python/cpython#143927) CVE-2026-0864-normalize-LFTAB-configparser.patch New: (bsc#1269788, gh-151981) CVE-2026-11972-tarfile-Stream-seek-EOF.patch New: in HTMLParser (bsc#1271192, gh#python/cpython#153030) CVE-2026-15308-HTMLParser-CPU-exhaust.patch New: during .extract() (bsc#1269959, gh#python/cpython#151987) CVE-2026-4360-filter_function-TarFile-extractone.patch New: - Add reproducible_stencils.patch from gh#python/cpython!154988 ----------(New E)---------- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python313.spec ++++++ --- /var/tmp/diff_new_pack.guDIG7/_old 2026-08-17 16:55:33.256766584 +0200 +++ /var/tmp/diff_new_pack.guDIG7/_new 2026-08-17 16:55:33.258766655 +0200 @@ -248,6 +248,21 @@ # PATCH-FIX-UPSTREAM CVE-2026-11940-tarfile-escape.patch bsc#1268977 [email protected] # Fix symlink escape via tarfile hardlink-extraction fallback Patch56: CVE-2026-11940-tarfile-escape.patch +# PATCH-FIX-UPSTREAM reproducible_stencils.patch gh#python/cpython!154988 [email protected] +# make jit_stencils.h reproducible +Patch57: reproducible_stencils.patch +# PATCH-FIX-UPSTREAM CVE-2026-0864-normalize-LFTAB-configparser.patch bsc#1269066 [email protected] +# Normalize all line endings (CR, CRLF, and LF) in configparser +Patch58: CVE-2026-0864-normalize-LFTAB-configparser.patch +# PATCH-FIX-UPSTREAM CVE-2026-11972-tarfile-Stream-seek-EOF.patch bsc#1269788 [email protected] +# Make tarfile._Stream.seek break at EOF +Patch59: CVE-2026-11972-tarfile-Stream-seek-EOF.patch +# PATCH-FIX-UPSTREAM CVE-2026-4360-filter_function-TarFile-extractone.patch bsc#1269959 [email protected] +# Pass filter_function to TarFile._extract_one() during .extract() +Patch60: CVE-2026-4360-filter_function-TarFile-extractone.patch +# PATCH-FIX-UPSTREAM CVE-2026-15308-HTMLParser-CPU-exhaust.patch bsc#1271192 [email protected] +# Fix quadratic complexity in incremental parsing in HTMLParser +Patch61: CVE-2026-15308-HTMLParser-CPU-exhaust.patch #### END OF PATCHES BuildRequires: autoconf-archive BuildRequires: automake ++++++ CVE-2026-0864-normalize-LFTAB-configparser.patch ++++++ >From f6a86b1ac9aeca3b48173ed3f88d8c097ec5131d Mon Sep 17 00:00:00 2001 From: Seth Larson <[email protected]> Date: Tue, 23 Jun 2026 08:33:51 -0500 Subject: [PATCH] gh-143927: Normalize all line endings (CR, CRLF, and LF) in configparser (GH-143929) (cherry picked from commit 5858e42c539dac8394636a6e9b30472b8994851f) Co-authored-by: Seth Larson <[email protected]> --- Lib/configparser.py | 4 ++- Lib/test/test_configparser.py | 11 ++++++++++ Misc/NEWS.d/next/Security/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 Index: Python-3.13.14/Lib/configparser.py =================================================================== --- Python-3.13.14.orig/Lib/configparser.py 2026-06-10 14:24:04.000000000 +0200 +++ Python-3.13.14/Lib/configparser.py 2026-08-09 22:28:22.232886394 +0200 @@ -973,7 +973,9 @@ 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)) Index: Python-3.13.14/Lib/test/test_configparser.py =================================================================== --- Python-3.13.14.orig/Lib/test/test_configparser.py 2026-06-10 14:24:04.000000000 +0200 +++ Python-3.13.14/Lib/test/test_configparser.py 2026-08-09 22:28:22.233186370 +0200 @@ -526,6 +526,17 @@ 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, Index: Python-3.13.14/Misc/NEWS.d/next/Security/2026-01-16-11-58-19.gh-issue-143927.aviFeG.rst =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ Python-3.13.14/Misc/NEWS.d/next/Security/2026-01-16-11-58-19.gh-issue-143927.aviFeG.rst 2026-08-09 22:28:22.233463081 +0200 @@ -0,0 +1,2 @@ +Normalize all line endings (CR, CRLF, and LF) to LF+TAB when writing +multi-line configparser values. ++++++ CVE-2026-11972-tarfile-Stream-seek-EOF.patch ++++++ >From 2fb7c785e2ce6d592b82be2840615611c8d3da4d Mon Sep 17 00:00:00 2001 From: Petr Viktorin <[email protected]> Date: Tue, 23 Jun 2026 15:13:30 +0200 Subject: [PATCH] gh-151981: Make tarfile._Stream.seek break at EOF (GH-151982) (cherry picked from commit f50bf13566189c8d0ce5a814f33eff3d89951896) Co-authored-by: Petr Viktorin <[email protected]> Co-authored-by: Stan Ulbrych <[email protected]> --- Lib/tarfile.py | 4 +- Lib/test/test_tarfile.py | 16 ++++++++++ Misc/NEWS.d/next/Security/2026-06-23-13-28-16.gh-issue-151981.xBHEcU.rst | 2 + 3 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Security/2026-06-23-13-28-16.gh-issue-151981.xBHEcU.rst Index: Python-3.13.14/Lib/tarfile.py =================================================================== --- Python-3.13.14.orig/Lib/tarfile.py 2026-08-09 23:17:17.509878117 +0200 +++ Python-3.13.14/Lib/tarfile.py 2026-08-09 23:17:17.554905835 +0200 @@ -515,7 +515,9 @@ 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") Index: Python-3.13.14/Lib/test/test_tarfile.py =================================================================== --- Python-3.13.14.orig/Lib/test/test_tarfile.py 2026-08-09 23:17:17.510736636 +0200 +++ Python-3.13.14/Lib/test/test_tarfile.py 2026-08-09 23:17:17.555562714 +0200 @@ -4762,6 +4762,22 @@ 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") Index: Python-3.13.14/Misc/NEWS.d/next/Security/2026-06-23-13-28-16.gh-issue-151981.xBHEcU.rst =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ Python-3.13.14/Misc/NEWS.d/next/Security/2026-06-23-13-28-16.gh-issue-151981.xBHEcU.rst 2026-08-09 23:17:17.556049943 +0200 @@ -0,0 +1,2 @@ +In :mod:`tarfile`, seeking a stream now stops when end of the stream is +reached. ++++++ CVE-2026-15308-HTMLParser-CPU-exhaust.patch ++++++ >From fc4dca171f6bb07d9f4e73765ffef2ba10ab8b0b Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka <[email protected]> Date: Sat, 4 Jul 2026 20:40:22 +0300 Subject: [PATCH] gh-153030: Fix quadratic complexity in incremental parsing in HTMLParser (GH-153031) When an unterminated construct (e.g. a tag or comment) spanned many feed() calls, rescanning the growing buffer and concatenating new data onto it were both quadratic. New data is now accumulated in a list and only joined and parsed once enough has piled up. (cherry picked from commit bcf98ddbc40ec9b3ee87da0124a5660b19b7e606) Co-authored-by: Serhiy Storchaka <[email protected]> Co-Authored-By: Claude Opus 4.8 <[email protected]> --- Lib/html/parser.py | 32 +++++++++- Lib/test/test_htmlparser.py | 20 ++++++ Misc/NEWS.d/next/Security/2026-07-04-17-00-00.gh-issue-153030.RovkP6.rst | 3 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Security/2026-07-04-17-00-00.gh-issue-153030.RovkP6.rst Index: Python-3.13.14/Lib/html/parser.py =================================================================== --- Python-3.13.14.orig/Lib/html/parser.py 2026-06-10 14:24:04.000000000 +0200 +++ Python-3.13.14/Lib/html/parser.py 2026-08-09 23:36:47.005389358 +0200 @@ -157,6 +157,9 @@ self.cdata_elem = None self._support_cdata = True self._escapable = True + self._pending = [] + self._pending_len = 0 + self._parse_threshold = 1 super().reset() def feed(self, data): @@ -165,11 +168,36 @@ Call this as often as you want, with as little or as much text as you want (may include '\n'). """ - self.rawdata = self.rawdata + data - self.goahead(0) + # Accumulate new data in a list and only join and parse it once + # enough has piled up. Rescanning an unparsed buffer (e.g. an + # unterminated tag) and concatenating onto it on every call would + # both be quadratic in the input size. + self._pending_len += len(data) + if self._pending_len < self._parse_threshold: + self._pending.append(data) + else: + if not self._pending: + self.rawdata += data + else: + self._pending.append(data) + self.rawdata += ''.join(self._pending) + self._pending.clear() + self._pending_len = 0 + n = len(self.rawdata) + self.goahead(0) + if len(self.rawdata) < n: + # Some data was parsed; resume on the next call. + self._parse_threshold = 1 + else: + # Nothing was parsed; wait until the buffer doubles. + self._parse_threshold = len(self.rawdata) def close(self): """Handle any buffered data.""" + if self._pending: + self.rawdata += ''.join(self._pending) + self._pending.clear() + self._pending_len = 0 self.goahead(1) __starttag_text = None Index: Python-3.13.14/Lib/test/test_htmlparser.py =================================================================== --- Python-3.13.14.orig/Lib/test/test_htmlparser.py 2026-06-10 14:24:04.000000000 +0200 +++ Python-3.13.14/Lib/test/test_htmlparser.py 2026-08-09 23:36:47.005672372 +0200 @@ -1031,6 +1031,26 @@ check("<![CDATA[" * 9 * n) check("<!doctype" * 35 * n) + @support.requires_resource('cpu') + def test_incremental_no_quadratic_complexity(self): + # An unterminated construct fed in many small chunks used to take + # quadratic time, both to rescan and to concatenate the buffer. + # Now it takes a fraction of a second. + def check(prefix, chunk, suffix): + parser = html.parser.HTMLParser() + parser.feed(prefix) + for _ in range(200_000): + parser.feed(chunk) + parser.feed(suffix) + parser.close() + chunk = "a" * 64 + check("<!--", chunk, "-->") # comment + check("<?", chunk, ">") # processing instruction + check("<!doctype ", chunk, ">") # doctype + check("<![CDATA[", chunk, "]]>") # CDATA section + check("<a href='", chunk, "'>") # start tag + check("<script>", chunk, "</script>") # RAWTEXT element + class AttributesTestCase(TestCaseBase): Index: Python-3.13.14/Misc/NEWS.d/next/Security/2026-07-04-17-00-00.gh-issue-153030.RovkP6.rst =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ Python-3.13.14/Misc/NEWS.d/next/Security/2026-07-04-17-00-00.gh-issue-153030.RovkP6.rst 2026-08-09 23:36:47.005873451 +0200 @@ -0,0 +1,3 @@ +Fixed quadratic complexity in incremental parsing of long unterminated +constructs (such as tags or comments) in :class:`html.parser.HTMLParser`, +which could be exploited for a denial of service. ++++++ CVE-2026-4360-filter_function-TarFile-extractone.patch ++++++ >From e1e764993cf5817936e50c294dc954b5be201781 Mon Sep 17 00:00:00 2001 From: Petr Viktorin <[email protected]> Date: Mon, 29 Jun 2026 17:41:26 +0200 Subject: [PATCH] gh-151987: Pass filter_function to TarFile._extract_one() during .extract() (GH-151988) (cherry picked from commit 7ccdbaba2c54250a70d7f25632152df7655a5e0a) Co-authored-by: Petr Viktorin <[email protected]> Co-authored-by: Seth Michael Larson <[email protected]> --- Lib/tarfile.py | 3 Lib/test/test_tarfile.py | 92 ++++++++++ Misc/NEWS.d/next/Security/2026-06-23-14-19-30.gh-issue-151987.8mNIMf.rst | 2 3 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Security/2026-06-23-14-19-30.gh-issue-151987.8mNIMf.rst Index: Python-3.13.14/Lib/tarfile.py =================================================================== --- Python-3.13.14.orig/Lib/tarfile.py 2026-08-09 23:33:55.420853456 +0200 +++ Python-3.13.14/Lib/tarfile.py 2026-08-09 23:33:55.436421166 +0200 @@ -2449,7 +2449,8 @@ tarinfo, unfiltered = self._get_extract_tarinfo( member, filter_function, path) if tarinfo is not None: - self._extract_one(tarinfo, path, set_attrs, numeric_owner) + self._extract_one(tarinfo, path, set_attrs, numeric_owner, + filter_function=filter_function) def _get_extract_tarinfo(self, member, filter_function, path): """Get (filtered, unfiltered) TarInfos from *member* Index: Python-3.13.14/Lib/test/test_tarfile.py =================================================================== --- Python-3.13.14.orig/Lib/test/test_tarfile.py 2026-08-09 23:33:55.421831219 +0200 +++ Python-3.13.14/Lib/test/test_tarfile.py 2026-08-09 23:33:55.438126494 +0200 @@ -4390,6 +4390,98 @@ st_mode = cc.outerdir.stat().st_mode self.assertNotEqual(st_mode & 0o777, 0o777) + @symlink_test + @unittest.skipUnless(hasattr(os, 'chown'), "missing os.chown") + @unittest.skipUnless(hasattr(os, 'lchown'), "missing os.lchown") + @unittest.skipUnless(hasattr(os, 'geteuid'), "missing os.geteuid") + @support.subTests('link_type', (tarfile.SYMTYPE, tarfile.LNKTYPE)) + def test_chown_links_on_extract(self, link_type): + with ArchiveMaker() as arc: + arc.add("test.txt", + uid=1337, gid=1337, uname="", gname="", mode='-rwxr-xr-x') + arc.add("link", + type=link_type, + linkname='test.txt', + uid=1337, gid=1337, uname="", gname="", mode='-rwxr-xr-x') + + with ( + os_helper.temp_dir() as tmpdir, + arc.open() as tar, + unittest.mock.patch("os.chown") as mock_chown, + unittest.mock.patch("os.lchown") as mock_lchown, + unittest.mock.patch("os.geteuid") as mock_geteuid, + ): + # Set UID to 0 so chown() is attempted. + mock_geteuid.return_value = 0 + tar.extract("link", path=tmpdir, filter='data') + extract_path = os.path.join(tmpdir, "link") + + if link_type == tarfile.SYMTYPE: + mock_chown.assert_not_called() + mock_lchown.assert_called_once_with(extract_path, -1, -1) + else: + mock_chown.assert_has_calls([ + unittest.mock.call(extract_path, -1, -1), + unittest.mock.call(extract_path, -1, -1) + ]) + mock_lchown.assert_not_called() + + @symlink_test + @unittest.skipUnless(hasattr(os, 'chown'), "missing os.chown") + @unittest.skipUnless(hasattr(os, 'lchown'), "missing os.lchown") + @unittest.skipUnless(hasattr(os, 'geteuid'), "missing os.geteuid") + @support.subTests('link_type', (tarfile.SYMTYPE, tarfile.LNKTYPE)) + def test_chown_links_on_extractall(self, link_type): + with ArchiveMaker() as arc: + arc.add("test.txt", + uid=1337, gid=1337, uname="", gname="", mode='-rwxr-xr-x') + arc.add("link", + type=link_type, + linkname='test.txt', + uid=1337, gid=1337, uname="", gname="", mode='-rwxr-xr-x') + + with ( + os_helper.temp_dir() as tmpdir, + arc.open() as tar, + unittest.mock.patch("os.chown") as mock_chown, + unittest.mock.patch("os.lchown") as mock_lchown, + unittest.mock.patch("os.geteuid") as mock_geteuid, + ): + # Set UID to 0 so chown() is attempted. + mock_geteuid.return_value = 0 + tar.extractall(path=tmpdir, filter='data') + extract_link_path = os.path.join(tmpdir, "link") + extract_file_path = os.path.join(tmpdir, "test.txt") + + if link_type == tarfile.SYMTYPE: + mock_chown.assert_called_once_with(extract_file_path, -1, -1) + mock_lchown.assert_called_once_with(extract_link_path, -1, -1) + else: + mock_chown.assert_has_calls([ + unittest.mock.call(extract_file_path, -1, -1), + unittest.mock.call(extract_link_path, -1, -1) + ]) + mock_lchown.assert_not_called() + + def test_extract_filters_target(self): + # Test that when extract() falls back to extracting (rather than + # linking) a hardlink target, it filters the target. + with ArchiveMaker() as arc: + arc.add("target") + arc.add("link", hardlink_to="target") + def testing_filter(member, path): + if member.name == 'target': + # target: set read-only + return member.replace(mode=stat.S_IRUSR) + # link: don't overwrite the mode + return member.replace(mode=None) + tempdir = pathlib.Path(TEMPDIR) / 'extract' + with os_helper.temp_dir(tempdir), arc.open() as tar: + tar.extract("link", path=tempdir, filter=testing_filter) + path = tempdir / 'link' + if os_helper.can_chmod(): + self.assertFalse(path.stat().st_mode & stat.S_IWUSR) + def test_link_fallback_normalizes(self): # Make sure hardlink fallbacks work for non-normalized paths for all # filters Index: Python-3.13.14/Misc/NEWS.d/next/Security/2026-06-23-14-19-30.gh-issue-151987.8mNIMf.rst =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ Python-3.13.14/Misc/NEWS.d/next/Security/2026-06-23-14-19-30.gh-issue-151987.8mNIMf.rst 2026-08-09 23:33:55.438660200 +0200 @@ -0,0 +1,2 @@ +The :meth:`tarfile.TarFile.extract` method now applies the given filter when +it extracts a link target from the archive as a fallback. ++++++ _scmsync.obsinfo ++++++ --- /var/tmp/diff_new_pack.guDIG7/_old 2026-08-17 16:55:33.460773765 +0200 +++ /var/tmp/diff_new_pack.guDIG7/_new 2026-08-17 16:55:33.466773976 +0200 @@ -1,6 +1,6 @@ -mtime: 1784282806 -commit: 231e2440e2990865abbe4e28761b76d134fc48b59de16e0a1f93c13ed00e4c59 +mtime: 1786748532 +commit: 0c31b87f057215535b70ee18ac6609824e74d568e05b74cdef7d75f0af347233 url: https://src.opensuse.org/python-interpreters/python313 -revision: 231e2440e2990865abbe4e28761b76d134fc48b59de16e0a1f93c13ed00e4c59 +revision: 0c31b87f057215535b70ee18ac6609824e74d568e05b74cdef7d75f0af347233 projectscmsync: https://src.opensuse.org/python-interpreters/_ObsPrj ++++++ build.specials.obscpio ++++++ ++++++ build.specials.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/.gitignore new/.gitignore --- old/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/.gitignore 2026-08-15 01:02:12.000000000 +0200 @@ -0,0 +1,6 @@ +.osc +*.obscpio +*.osc +_build.* +.pbuild +python313-*-build/ ++++++ reproducible_stencils.patch ++++++ >From eb1d1079dcf13fa601bf95b40f65a0b0dee5f5ff Mon Sep 17 00:00:00 2001 From: "Bernhard M. Wiedemann" <[email protected]> Date: Thu, 30 Jul 2026 21:27:28 +0200 Subject: [PATCH] [3.13] GH-115869: Make jit_stencils.h reproducible (GH-127166) Keep the build tmpdir out of jit_stencils.h llvm-objdump prints the path of the object file it disassembles, and the JIT builds every stencil in a fresh tempfile.TemporaryDirectory(). That random path ended up verbatim in the disassembly comments of the generated jit_stencils.h, so two builds of the same source never produced the same header: // /tmp/tmp164olvmi/_BINARY_OP.o: file format elf64-x86-64 +// /tmp/tmpmufvewt2/_BINARY_OP.o: file format elf64-x86-64 Replace the full path with the bare file name. Only the _parse() hunk of that commit is taken here; the rest of it depends on refactorings that are not in 3.13. (cherry picked from commit 17c16aea66b606d66f71ae9af381bc34d0ef3f5f) Co-authored-by: Brandt Bucher <[email protected]> --- .../next/Build/2024-11-22-08-46-46.gh-issue-115869.UVLSKd.rst | 1 + Tools/jit/_targets.py | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Build/2024-11-22-08-46-46.gh-issue-115869.UVLSKd.rst diff --git a/Misc/NEWS.d/next/Build/2024-11-22-08-46-46.gh-issue-115869.UVLSKd.rst b/Misc/NEWS.d/next/Build/2024-11-22-08-46-46.gh-issue-115869.UVLSKd.rst new file mode 100644 index 000000000000000..9e8a078983f20b5 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2024-11-22-08-46-46.gh-issue-115869.UVLSKd.rst @@ -0,0 +1 @@ +Make ``jit_stencils.h`` (which is produced during JIT builds) reproducible. diff --git a/Tools/jit/_targets.py b/Tools/jit/_targets.py index c50bd63545c2fe4..55f2332136cba92 100644 --- a/Tools/jit/_targets.py +++ b/Tools/jit/_targets.py @@ -65,8 +65,10 @@ async def _parse(self, path: pathlib.Path) -> _stencils.StencilGroup: args = ["--disassemble", "--reloc", f"{path}"] output = await _llvm.maybe_run("llvm-objdump", args, echo=self.verbose) if output is not None: + # Make sure that full paths don't leak out (for reproducibility): + long, short = str(path), str(path.name) group.code.disassembly.extend( - line.expandtabs().strip() + line.expandtabs().strip().replace(long, short) for line in output.splitlines() if not line.isspace() )
