diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2025-02-25 23:04:27 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-02-25 23:04:27 +0200 |
commit | 0ef4ffeefd1737c18dc9326133c7894d58108c2e (patch) | |
tree | dc3614077d06e68df192e57505951b80012a2e31 /Python/pylifecycle.c | |
parent | 2dad1e08ec9d5ddc798a313900613b3d1eeaff6b (diff) | |
download | cpython-0ef4ffeefd1737c18dc9326133c7894d58108c2e.tar.gz cpython-0ef4ffeefd1737c18dc9326133c7894d58108c2e.zip |
gh-130163: Fix crashes related to PySys_GetObject() (GH-130503)
The use of PySys_GetObject() and _PySys_GetAttr(), which return a borrowed
reference, has been replaced by using one of the following functions, which
return a strong reference and distinguish a missing attribute from an error:
_PySys_GetOptionalAttr(), _PySys_GetOptionalAttrString(),
_PySys_GetRequiredAttr(), and _PySys_GetRequiredAttrString().
Diffstat (limited to 'Python/pylifecycle.c')
-rw-r--r-- | Python/pylifecycle.c | 43 |
1 files changed, 31 insertions, 12 deletions
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 300a871d2cc..1a7f312a604 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -27,7 +27,7 @@ #include "pycore_runtime_init.h" // _PyRuntimeState_INIT #include "pycore_setobject.h" // _PySet_NextEntry() #include "pycore_sliceobject.h" // _PySlice_Fini() -#include "pycore_sysmodule.h" // _PySys_GetAttr() +#include "pycore_sysmodule.h" // _PySys_ClearAttrString() #include "pycore_traceback.h" // _Py_DumpTracebackThreads() #include "pycore_uniqueid.h" // _PyObject_FinalizeUniqueIdPool() #include "pycore_typeobject.h" // _PyTypes_InitTypes() @@ -1254,8 +1254,12 @@ init_interp_main(PyThreadState *tstate) if (is_main_interp) { /* Initialize warnings. */ - PyObject *warnoptions = PySys_GetObject("warnoptions"); - if (warnoptions != NULL && PyList_Size(warnoptions) > 0) + PyObject *warnoptions; + if (_PySys_GetOptionalAttrString("warnoptions", &warnoptions) < 0) { + return _PyStatus_ERR("can't initialize warnings"); + } + if (warnoptions != NULL && PyList_Check(warnoptions) && + PyList_Size(warnoptions) > 0) { PyObject *warnings_module = PyImport_ImportModule("warnings"); if (warnings_module == NULL) { @@ -1264,6 +1268,7 @@ init_interp_main(PyThreadState *tstate) } Py_XDECREF(warnings_module); } + Py_XDECREF(warnoptions); interp->runtime->initialized = 1; } @@ -1770,24 +1775,33 @@ file_is_closed(PyObject *fobj) static int flush_std_files(void) { - PyThreadState *tstate = _PyThreadState_GET(); - PyObject *fout = _PySys_GetAttr(tstate, &_Py_ID(stdout)); - PyObject *ferr = _PySys_GetAttr(tstate, &_Py_ID(stderr)); + PyObject *file; int status = 0; - if (fout != NULL && fout != Py_None && !file_is_closed(fout)) { - if (_PyFile_Flush(fout) < 0) { - PyErr_FormatUnraisable("Exception ignored while flushing sys.stdout"); + if (_PySys_GetOptionalAttr(&_Py_ID(stdout), &file) < 0) { + status = -1; + } + else if (file != NULL && file != Py_None && !file_is_closed(file)) { + if (_PyFile_Flush(file) < 0) { status = -1; } } + if (status < 0) { + PyErr_FormatUnraisable("Exception ignored while flushing sys.stdout"); + } + Py_XDECREF(file); - if (ferr != NULL && ferr != Py_None && !file_is_closed(ferr)) { - if (_PyFile_Flush(ferr) < 0) { + if (_PySys_GetOptionalAttr(&_Py_ID(stderr), &file) < 0) { + PyErr_Clear(); + status = -1; + } + else if (file != NULL && file != Py_None && !file_is_closed(file)) { + if (_PyFile_Flush(file) < 0) { PyErr_Clear(); status = -1; } } + Py_XDECREF(file); return status; } @@ -2998,10 +3012,14 @@ _Py_FatalError_PrintExc(PyThreadState *tstate) return 0; } - PyObject *ferr = _PySys_GetAttr(tstate, &_Py_ID(stderr)); + PyObject *ferr; + if (_PySys_GetOptionalAttr(&_Py_ID(stderr), &ferr) < 0) { + _PyErr_Clear(tstate); + } if (ferr == NULL || ferr == Py_None) { /* sys.stderr is not set yet or set to None, no need to try to display the exception */ + Py_XDECREF(ferr); Py_DECREF(exc); return 0; } @@ -3017,6 +3035,7 @@ _Py_FatalError_PrintExc(PyThreadState *tstate) if (_PyFile_Flush(ferr) < 0) { _PyErr_Clear(tstate); } + Py_DECREF(ferr); return has_tb; } |