From 59c9718c5a9b8ad518a66f3ba219f0a7a2736533 Mon Sep 17 00:00:00 2001 From: Shamil Abdulaev Date: Sun, 23 Aug 2026 23:17:36 +0300 Subject: [PATCH 1/2] Fix crash in perf trampoline with unencodable code names --- Lib/test/test_perf_profiler.py | 9 +++++++++ .../2026-08-23-12-00-00.gh-issue-156114.Kq7fXz.rst | 2 ++ Python/perf_jit_trampoline.c | 6 ++++++ Python/perf_trampoline.c | 8 ++++++++ 4 files changed, 25 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-08-23-12-00-00.gh-issue-156114.Kq7fXz.rst diff --git a/Lib/test/test_perf_profiler.py b/Lib/test/test_perf_profiler.py index 425c76dd01ed7c2..482c209ddc61d85 100644 --- a/Lib/test/test_perf_profiler.py +++ b/Lib/test/test_perf_profiler.py @@ -113,6 +113,15 @@ def baz(): "Address should contain only hex characters", ) + def test_trampoline_with_unencodable_name(self): + code = """if 1: + import sys + + sys.activate_stack_trampoline("perf") + eval(compile("pass", "bad\\ud800file", "exec")) + """ + assert_python_ok("-c", code, PYTHON_JIT="0") + @unittest.skipIf(support.check_bolt_optimized(), "fails on BOLT instrumented binaries") def test_trampoline_works_with_forks(self): code = """if 1: diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-08-23-12-00-00.gh-issue-156114.Kq7fXz.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-08-23-12-00-00.gh-issue-156114.Kq7fXz.rst new file mode 100644 index 000000000000000..096216f7e6c7b3c --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-08-23-12-00-00.gh-issue-156114.Kq7fXz.rst @@ -0,0 +1,2 @@ +Fix a crash in the perf trampoline when a code object has a name or filename +that cannot be encoded to UTF-8. Patched by Shamil Abdulaev. diff --git a/Python/perf_jit_trampoline.c b/Python/perf_jit_trampoline.c index 21beead742a3a25..07aa8e769bf2d7d 100644 --- a/Python/perf_jit_trampoline.c +++ b/Python/perf_jit_trampoline.c @@ -751,9 +751,15 @@ static void perf_map_jit_write_entry(void *state, const void *code_addr, if (co != NULL) { if (co->co_qualname != NULL) { entry = PyUnicode_AsUTF8(co->co_qualname); + if (entry == NULL) { + PyErr_Clear(); + } } if (co->co_filename != NULL) { filename = PyUnicode_AsUTF8(co->co_filename); + if (filename == NULL) { + PyErr_Clear(); + } } } perf_map_jit_write_entry_with_name(state, code_addr, code_size, diff --git a/Python/perf_trampoline.c b/Python/perf_trampoline.c index d90b789c2b57126..431ac2c3a778edb 100644 --- a/Python/perf_trampoline.c +++ b/Python/perf_trampoline.c @@ -254,10 +254,18 @@ perf_map_write_entry(void *state, const void *code_addr, const char *entry = ""; if (co->co_qualname != NULL) { entry = PyUnicode_AsUTF8(co->co_qualname); + if (entry == NULL) { + PyErr_Clear(); + entry = ""; + } } const char *filename = ""; if (co->co_filename != NULL) { filename = PyUnicode_AsUTF8(co->co_filename); + if (filename == NULL) { + PyErr_Clear(); + filename = ""; + } } size_t perf_map_entry_size = snprintf(NULL, 0, "py::%s:%s", entry, filename) + 1; char* perf_map_entry = (char*) PyMem_RawMalloc(perf_map_entry_size); From b3f0c830bbfed085a55c0bab1b572572fc077b53 Mon Sep 17 00:00:00 2001 From: Shamil Abdulaev Date: Mon, 24 Aug 2026 03:04:46 +0300 Subject: [PATCH 2/2] Skip unencodable name trampoline test on BOLT builds --- Lib/test/test_perf_profiler.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/test/test_perf_profiler.py b/Lib/test/test_perf_profiler.py index 482c209ddc61d85..394bcdce69767ce 100644 --- a/Lib/test/test_perf_profiler.py +++ b/Lib/test/test_perf_profiler.py @@ -113,6 +113,7 @@ def baz(): "Address should contain only hex characters", ) + @unittest.skipIf(support.check_bolt_optimized(), "fails on BOLT instrumented binaries") def test_trampoline_with_unencodable_name(self): code = """if 1: import sys