https://github.com/python/cpython/commit/f277781bba684322dffffe45cd878f4652ccf7e4
commit: f277781bba684322dffffe45cd878f4652ccf7e4
branch: main
author: Bartosz Sławecki <[email protected]>
committer: ZeroIntensity <[email protected]>
date: 2025-12-15T22:58:50Z
summary:
gh-142737: Handle lost `io.open` in `_Py_FindSourceFile` (GH-142747)
files:
A
Misc/NEWS.d/next/Core_and_Builtins/2025-12-15-15-01-21.gh-issue-142737.xYXzeB.rst
M Lib/test/test_traceback.py
M Objects/call.c
M Python/traceback.c
diff --git a/Lib/test/test_traceback.py b/Lib/test/test_traceback.py
index 259f70f1ea0dbc..96510eeec54640 100644
--- a/Lib/test/test_traceback.py
+++ b/Lib/test/test_traceback.py
@@ -18,7 +18,7 @@
from test.support import (Error, captured_output, cpython_only, ALWAYS_EQ,
requires_debug_ranges, has_no_debug_ranges,
requires_subprocess)
-from test.support.os_helper import TESTFN, unlink
+from test.support.os_helper import TESTFN, temp_dir, unlink
from test.support.script_helper import assert_python_ok,
assert_python_failure, make_script
from test.support.import_helper import forget
from test.support import force_not_colorized, force_not_colorized_test_class
@@ -524,6 +524,33 @@ def __del__(self):
b'ZeroDivisionError: division by zero']
self.assertEqual(stderr.splitlines(), expected)
+ @cpython_only
+ def test_lost_io_open(self):
+ # GH-142737: Display the traceback even if io.open is lost
+ crasher = textwrap.dedent("""\
+ import io
+ import traceback
+ # Trigger fallback mode
+ traceback._print_exception_bltin = None
+ del io.open
+ raise RuntimeError("should not crash")
+ """)
+
+ # Create a temporary script to exercise _Py_FindSourceFile
+ with temp_dir() as script_dir:
+ script = make_script(
+ script_dir=script_dir,
+ script_basename='tb_test_no_io_open',
+ source=crasher)
+ rc, stdout, stderr = assert_python_failure(script)
+
+ self.assertEqual(rc, 1) # Make sure it's not a crash
+
+ expected = [b'Traceback (most recent call last):',
+ f' File "{script}", line 6, in <module>'.encode(),
+ b'RuntimeError: should not crash']
+ self.assertEqual(stderr.splitlines(), expected)
+
def test_print_exception(self):
output = StringIO()
traceback.print_exception(
diff --git
a/Misc/NEWS.d/next/Core_and_Builtins/2025-12-15-15-01-21.gh-issue-142737.xYXzeB.rst
b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-15-15-01-21.gh-issue-142737.xYXzeB.rst
new file mode 100644
index 00000000000000..8b743d1e49de21
--- /dev/null
+++
b/Misc/NEWS.d/next/Core_and_Builtins/2025-12-15-15-01-21.gh-issue-142737.xYXzeB.rst
@@ -0,0 +1,3 @@
+Tracebacks will be displayed in fallback mode even if :func:`io.open` is lost.
+Previously, this would crash the interpreter.
+Patch by Bartosz Sławecki.
diff --git a/Objects/call.c b/Objects/call.c
index 41d075caf11ce6..af42fc8f7f2dbf 100644
--- a/Objects/call.c
+++ b/Objects/call.c
@@ -729,6 +729,7 @@ _Py_COMP_DIAG_POP
PyObject * _PyObject_CallMethodFormat(PyThreadState *tstate, PyObject
*callable,
const char *format, ...)
{
+ assert(callable != NULL);
va_list va;
va_start(va, format);
PyObject *retval = callmethod(tstate, callable, format, va);
diff --git a/Python/traceback.c b/Python/traceback.c
index 8af63c22a9f84e..264f034dea7fa5 100644
--- a/Python/traceback.c
+++ b/Python/traceback.c
@@ -415,6 +415,9 @@ _Py_FindSourceFile(PyObject *filename, char* namebuf,
size_t namelen, PyObject *
npath = PyList_Size(syspath);
open = PyObject_GetAttr(io, &_Py_ID(open));
+ if (open == NULL) {
+ goto error;
+ }
for (i = 0; i < npath; i++) {
v = PyList_GetItem(syspath, i);
if (v == NULL) {
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]