From 6fd57359b76a17dd2cf818ffd5d46823bde4d08d Mon Sep 17 00:00:00 2001 From: Tomasz Pytel Date: Tue, 11 Feb 2025 15:22:39 -0500 Subject: [PATCH 1/7] gh-129983: fix data race in compile_template in sre.c --- Lib/test/libregrtest/tsan.py | 1 + Lib/test/test_re.py | 13 +++++++++++++ Modules/_sre/sre.c | 10 +++++++++- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Lib/test/libregrtest/tsan.py b/Lib/test/libregrtest/tsan.py index 10b12cce165931..1f25c6ba403089 100644 --- a/Lib/test/libregrtest/tsan.py +++ b/Lib/test/libregrtest/tsan.py @@ -34,6 +34,7 @@ TSAN_PARALLEL_TESTS = [ 'test_abc', 'test_hashlib', + 'test_re', ] diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index 5538de60b2a03a..0b0cc61e8f9441 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -1,3 +1,4 @@ +from test import support from test.support import (gc_collect, bigmemtest, _2G, cpython_only, captured_stdout, check_disallow_instantiation, is_emscripten, is_wasi, @@ -33,6 +34,7 @@ class B(bytes): def __getitem__(self, index): return B(super().__getitem__(index)) +@support.skip_if_sanitizer("not everything here is free-threading safe yet", thread=True) class ReTests(unittest.TestCase): def assertTypedEqual(self, actual, expect, msg=None): @@ -2714,6 +2716,7 @@ def get_debug_out(pat): return out.getvalue() +@support.skip_if_sanitizer("not everything here is free-threading safe yet", thread=True) @cpython_only class DebugTests(unittest.TestCase): maxDiff = None @@ -2810,6 +2813,7 @@ def test_possesive_repeat(self): ''') +@support.skip_if_sanitizer("not everything here is free-threading safe yet", thread=True) class PatternReprTests(unittest.TestCase): def check(self, pattern, expected): self.assertEqual(repr(re.compile(pattern)), expected) @@ -2890,6 +2894,7 @@ def test_flags_repr(self): "re.ASCII|re.LOCALE|re.UNICODE|re.MULTILINE|re.DEBUG|0xffe01") +@support.skip_if_sanitizer("not everything here is free-threading safe yet", thread=True) class ImplementationTest(unittest.TestCase): """ Test implementation details of the re module. @@ -3027,6 +3032,7 @@ def test_sre_template_invalid_group_index(self): self.assertIn("an integer is required", str(cm.exception)) +@support.skip_if_sanitizer("not everything here is free-threading safe yet", thread=True) class ExternalTests(unittest.TestCase): def test_re_benchmarks(self): @@ -3140,5 +3146,12 @@ def test_re_tests(self): self.assertTrue(obj.search(s)) +@unittest.skipUnless(support.check_sanitizer(thread=True), 'only has meaning if TSAN enabled') +class FreeThreadingTests(unittest.TestCase): + def test_compile_pattern(self): + # gh-129983: Data race in compile_template in sre.c + re.sub(r"(\d+)", r"\1kg", "Weight: 50") + + if __name__ == "__main__": unittest.main() diff --git a/Modules/_sre/sre.c b/Modules/_sre/sre.c index 0d8d4843d33c1b..64ef6b202e56af 100644 --- a/Modules/_sre/sre.c +++ b/Modules/_sre/sre.c @@ -1167,13 +1167,21 @@ compile_template(_sremodulestate *module_state, PatternObject *pattern, PyObject *template) { /* delegate to Python code */ - PyObject *func = module_state->compile_template; + PyObject *func = FT_ATOMIC_LOAD_PTR_RELAXED(module_state->compile_template); if (func == NULL) { func = PyImport_ImportModuleAttrString("re", "_compile_template"); if (func == NULL) { return NULL; } +#ifdef Py_GIL_DISABLED + PyObject *other_func = NULL; + if (!_Py_atomic_compare_exchange_ptr(&module_state->compile_template, &other_func, func)) { + Py_DECREF(func); + func = other_func; + } +#else Py_XSETREF(module_state->compile_template, func); +#endif } PyObject *args[] = {(PyObject *)pattern, template}; From f929205f0c9da67effc9217b6ad5442e0564a047 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Tue, 11 Feb 2025 20:38:38 +0000 Subject: [PATCH 2/7] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst new file mode 100644 index 00000000000000..223a60751616eb --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst @@ -0,0 +1 @@ +gh-129983: Fix data race in :c:func:`compile_template` in :file:`sre.c`. From b84d19a03e5ee86cea0da440a90ff0eec5ef02c9 Mon Sep 17 00:00:00 2001 From: Tomasz Pytel Date: Tue, 11 Feb 2025 15:40:43 -0500 Subject: [PATCH 3/7] Update 2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst --- .../2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst index 223a60751616eb..f16c99433a4c64 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst @@ -1 +1 @@ -gh-129983: Fix data race in :c:func:`compile_template` in :file:`sre.c`. +gh-129983: Fix data race in "compile_template" in :file:`sre.c`. From db9e13bebb70ee63b2d4f060f8de1ba1d02280ae Mon Sep 17 00:00:00 2001 From: Tomasz Pytel Date: Tue, 11 Feb 2025 15:42:51 -0500 Subject: [PATCH 4/7] Update 2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst --- .../2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst index f16c99433a4c64..c55981f52ad662 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst @@ -1 +1 @@ -gh-129983: Fix data race in "compile_template" in :file:`sre.c`. +gh-129983: Fix data race in "compile_template" in sre.c. From 101364a46624b158531c7473564cf00a3477fb2f Mon Sep 17 00:00:00 2001 From: Tomasz Pytel Date: Tue, 11 Feb 2025 15:45:06 -0500 Subject: [PATCH 5/7] Update 2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst --- .../2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst index c55981f52ad662..9b435703eb734a 100644 --- a/Misc/NEWS.d/next/Core_and_Builtins/2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-02-11-20-38-37.gh-issue-129983._1Fujo.rst @@ -1 +1 @@ -gh-129983: Fix data race in "compile_template" in sre.c. +Fix data race in compile_template in :file:`sre.c`. From da15fb8e3ec7e7aac4125d3a6841b177ba53e598 Mon Sep 17 00:00:00 2001 From: Tomasz Pytel Date: Tue, 11 Feb 2025 16:04:13 -0500 Subject: [PATCH 6/7] change to FT_ATOMIC_LOAD_PTR --- Modules/_sre/sre.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_sre/sre.c b/Modules/_sre/sre.c index 64ef6b202e56af..54f0e64d4819f1 100644 --- a/Modules/_sre/sre.c +++ b/Modules/_sre/sre.c @@ -1167,7 +1167,7 @@ compile_template(_sremodulestate *module_state, PatternObject *pattern, PyObject *template) { /* delegate to Python code */ - PyObject *func = FT_ATOMIC_LOAD_PTR_RELAXED(module_state->compile_template); + PyObject *func = FT_ATOMIC_LOAD_PTR(module_state->compile_template); if (func == NULL) { func = PyImport_ImportModuleAttrString("re", "_compile_template"); if (func == NULL) { From ce1301f2ac02791f83fa2d76fc1c7c4f9626d1b4 Mon Sep 17 00:00:00 2001 From: Tomasz Pytel Date: Tue, 11 Feb 2025 16:42:45 -0500 Subject: [PATCH 7/7] remove flaky test --- Lib/test/libregrtest/tsan.py | 1 - Lib/test/test_re.py | 13 ------------- 2 files changed, 14 deletions(-) diff --git a/Lib/test/libregrtest/tsan.py b/Lib/test/libregrtest/tsan.py index 1f25c6ba403089..10b12cce165931 100644 --- a/Lib/test/libregrtest/tsan.py +++ b/Lib/test/libregrtest/tsan.py @@ -34,7 +34,6 @@ TSAN_PARALLEL_TESTS = [ 'test_abc', 'test_hashlib', - 'test_re', ] diff --git a/Lib/test/test_re.py b/Lib/test/test_re.py index 0b0cc61e8f9441..5538de60b2a03a 100644 --- a/Lib/test/test_re.py +++ b/Lib/test/test_re.py @@ -1,4 +1,3 @@ -from test import support from test.support import (gc_collect, bigmemtest, _2G, cpython_only, captured_stdout, check_disallow_instantiation, is_emscripten, is_wasi, @@ -34,7 +33,6 @@ class B(bytes): def __getitem__(self, index): return B(super().__getitem__(index)) -@support.skip_if_sanitizer("not everything here is free-threading safe yet", thread=True) class ReTests(unittest.TestCase): def assertTypedEqual(self, actual, expect, msg=None): @@ -2716,7 +2714,6 @@ def get_debug_out(pat): return out.getvalue() -@support.skip_if_sanitizer("not everything here is free-threading safe yet", thread=True) @cpython_only class DebugTests(unittest.TestCase): maxDiff = None @@ -2813,7 +2810,6 @@ def test_possesive_repeat(self): ''') -@support.skip_if_sanitizer("not everything here is free-threading safe yet", thread=True) class PatternReprTests(unittest.TestCase): def check(self, pattern, expected): self.assertEqual(repr(re.compile(pattern)), expected) @@ -2894,7 +2890,6 @@ def test_flags_repr(self): "re.ASCII|re.LOCALE|re.UNICODE|re.MULTILINE|re.DEBUG|0xffe01") -@support.skip_if_sanitizer("not everything here is free-threading safe yet", thread=True) class ImplementationTest(unittest.TestCase): """ Test implementation details of the re module. @@ -3032,7 +3027,6 @@ def test_sre_template_invalid_group_index(self): self.assertIn("an integer is required", str(cm.exception)) -@support.skip_if_sanitizer("not everything here is free-threading safe yet", thread=True) class ExternalTests(unittest.TestCase): def test_re_benchmarks(self): @@ -3146,12 +3140,5 @@ def test_re_tests(self): self.assertTrue(obj.search(s)) -@unittest.skipUnless(support.check_sanitizer(thread=True), 'only has meaning if TSAN enabled') -class FreeThreadingTests(unittest.TestCase): - def test_compile_pattern(self): - # gh-129983: Data race in compile_template in sre.c - re.sub(r"(\d+)", r"\1kg", "Weight: 50") - - if __name__ == "__main__": unittest.main()