-
-
Notifications
You must be signed in to change notification settings - Fork 35.7k
_testcapi mishandles Py_fopen() failures #155905
Copy link
Copy link
Closed
Labels
3.14bugs and security fixesbugs and security fixes3.15pre-release feature fixes, bugs and security fixespre-release feature fixes, bugs and security fixes3.16new features, bugs and security fixesnew features, bugs and security fixestestsTests in the Lib/test dirTests in the Lib/test dirtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or errortype-crashA hard crash of the interpreter, possibly with a core dumpA hard crash of the interpreter, possibly with a core dump
Description
Activity
Metadata
Metadata
Assignees
Labels
3.14bugs and security fixesbugs and security fixes3.15pre-release feature fixes, bugs and security fixespre-release feature fixes, bugs and security fixes3.16new features, bugs and security fixesnew features, bugs and security fixestestsTests in the Lib/test dirTests in the Lib/test dirtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or errortype-crashA hard crash of the interpreter, possibly with a core dumpA hard crash of the interpreter, possibly with a core dump
Bug report
Py_fopen()sets an exception and returnsNULLon error, but several_testcapihelpers ignore both halves of that contract.Modules/_testcapi/object.cdoes not check the result at all. All four helpers pass it straight toPyObject_Print():so a
NULLfile pointer reachesfprintf()and the interpreter crashes:The same happens with
pyobject_print_null(),pyobject_print_noref_object()andpyobject_print_os_error().Modules/_testcapimodule.csets a second exception. The sixpymarshal_*helpers do:so
OSErroris instantiated whilePy_fopen()'s exception is still pending:>>> _testcapi.pymarshal_read_object_from_file('nonexistent') SystemError: <class 'OSError'> returned a result with an exception setOn a debug build it aborts instead:
Objects/call.c:342: _PyObject_Call: Assertion `!_PyErr_Occurred(tstate)' failed.Both date from f89e5e2 (gh-127350), which converted these helpers from
fopen()toPy_fopen(). They affect 3.14 and later.Related cleanup: these helpers also close the file with
fclose()rather thanPy_fclose(), which the documentation requires -- 8 sites inobject.c, 6 in_testcapimodule.cand 14 inrun.c. It is harmless today, sincePy_fclose()is just a wrapper.All other
Py_fopen()call sites in the tree check the result correctly.Linked PRs