[3.12] gh-130163: Fix crashes related to PySys_GetObject() (GH-130503) (GH-130556) (GH-130576)

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().

(cherry picked from commit 0ef4ffeefd)
(cherry picked from commit 7c1b76fce8)
(cherry picked from commit 2ab7e1135a)
This commit is contained in:
Serhiy Storchaka 2025-02-26 17:20:47 +02:00 committed by GitHub
parent 6a268a046f
commit 89a79fc919
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 506 additions and 162 deletions

View file

@ -109,6 +109,7 @@ static const char PyCursesVersion[] = "2.2";
#include "Python.h"
#include "pycore_long.h" // _PyLong_GetZero()
#include "pycore_structseq.h" // _PyStructSequence_NewType()
#include "pycore_sysmodule.h" // _PySys_GetOptionalAttrString()
#ifdef __hpux
#define STRICT_SYSV_CURSES
@ -3375,17 +3376,20 @@ _curses_setupterm_impl(PyObject *module, const char *term, int fd)
if (fd == -1) {
PyObject* sys_stdout;
sys_stdout = PySys_GetObject("stdout");
if (_PySys_GetOptionalAttrString("stdout", &sys_stdout) < 0) {
return NULL;
}
if (sys_stdout == NULL || sys_stdout == Py_None) {
PyErr_SetString(
PyCursesError,
"lost sys.stdout");
Py_XDECREF(sys_stdout);
return NULL;
}
fd = PyObject_AsFileDescriptor(sys_stdout);
Py_DECREF(sys_stdout);
if (fd == -1) {
return NULL;
}

View file

@ -13,6 +13,7 @@
#include "pycore_moduleobject.h" // _PyModule_GetState()
#include "pycore_runtime.h" // _Py_ID()
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_sysmodule.h" // _PySys_GetRequiredAttr()
#include "structmember.h" // PyMemberDef
#include <stdlib.h> // strtol()
@ -1984,19 +1985,19 @@ whichmodule(PyObject *global, PyObject *dotted_path)
assert(module_name == NULL);
/* Fallback on walking sys.modules */
PyThreadState *tstate = _PyThreadState_GET();
modules = _PySys_GetAttr(tstate, &_Py_ID(modules));
modules = _PySys_GetRequiredAttr(&_Py_ID(modules));
if (modules == NULL) {
PyErr_SetString(PyExc_RuntimeError, "unable to get sys.modules");
return NULL;
}
if (PyDict_CheckExact(modules)) {
i = 0;
while (PyDict_Next(modules, &i, &module_name, &module)) {
if (_checkmodule(module_name, module, global, dotted_path) == 0) {
Py_DECREF(modules);
return Py_NewRef(module_name);
}
if (PyErr_Occurred()) {
Py_DECREF(modules);
return NULL;
}
}
@ -2004,6 +2005,7 @@ whichmodule(PyObject *global, PyObject *dotted_path)
else {
PyObject *iterator = PyObject_GetIter(modules);
if (iterator == NULL) {
Py_DECREF(modules);
return NULL;
}
while ((module_name = PyIter_Next(iterator))) {
@ -2011,22 +2013,26 @@ whichmodule(PyObject *global, PyObject *dotted_path)
if (module == NULL) {
Py_DECREF(module_name);
Py_DECREF(iterator);
Py_DECREF(modules);
return NULL;
}
if (_checkmodule(module_name, module, global, dotted_path) == 0) {
Py_DECREF(module);
Py_DECREF(iterator);
Py_DECREF(modules);
return module_name;
}
Py_DECREF(module);
Py_DECREF(module_name);
if (PyErr_Occurred()) {
Py_DECREF(iterator);
Py_DECREF(modules);
return NULL;
}
}
Py_DECREF(iterator);
}
Py_DECREF(modules);
/* If no module is found, use __main__. */
module_name = &_Py_ID(__main__);

View file

@ -7,6 +7,8 @@
#include "pycore_moduleobject.h" // _PyModule_GetState()
#include "pycore_pylifecycle.h"
#include "pycore_pystate.h" // _PyThreadState_SetCurrent()
#include "pycore_sysmodule.h" // _PySys_GetOptionalAttr()
#include <stddef.h> // offsetof()
#include "structmember.h" // PyMemberDef
@ -1567,9 +1569,12 @@ thread_excepthook(PyObject *module, PyObject *args)
PyObject *exc_tb = PyStructSequence_GET_ITEM(args, 2);
PyObject *thread = PyStructSequence_GET_ITEM(args, 3);
PyThreadState *tstate = _PyThreadState_GET();
PyObject *file = _PySys_GetAttr(tstate, &_Py_ID(stderr));
PyObject *file;
if (_PySys_GetOptionalAttr( &_Py_ID(stderr), &file) < 0) {
return NULL;
}
if (file == NULL || file == Py_None) {
Py_XDECREF(file);
if (thread == Py_None) {
/* do nothing if sys.stderr is None and thread is None */
Py_RETURN_NONE;
@ -1586,9 +1591,6 @@ thread_excepthook(PyObject *module, PyObject *args)
Py_RETURN_NONE;
}
}
else {
Py_INCREF(file);
}
int res = thread_excepthook_file(file, exc_type, exc_value, exc_tb,
thread);

View file

@ -33,6 +33,7 @@ Copyright (C) 1994 Steen Lumholt.
#endif
#include "pycore_long.h"
#include "pycore_sysmodule.h" // _PySys_GetOptionalAttrString()
#ifdef MS_WINDOWS
#include <windows.h>
@ -154,9 +155,11 @@ _get_tcl_lib_path(void)
/* Check expected location for an installed Python first */
tcl_library_path = PyUnicode_FromString("\\tcl\\tcl" TCL_VERSION);
if (tcl_library_path == NULL) {
Py_DECREF(prefix);
return NULL;
}
tcl_library_path = PyUnicode_Concat(prefix, tcl_library_path);
Py_DECREF(prefix);
if (tcl_library_path == NULL) {
return NULL;
}
@ -3509,6 +3512,7 @@ PyInit__tkinter(void)
uexe = PyUnicode_FromWideChar(Py_GetProgramName(), -1);
if (uexe) {
cexe = PyUnicode_EncodeFSDefault(uexe);
Py_DECREF(uexe);
if (cexe) {
#ifdef MS_WINDOWS
int set_var = 0;
@ -3521,12 +3525,14 @@ PyInit__tkinter(void)
if (!ret && GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
str_path = _get_tcl_lib_path();
if (str_path == NULL && PyErr_Occurred()) {
Py_DECREF(cexe);
Py_DECREF(m);
return NULL;
}
if (str_path != NULL) {
wcs_path = PyUnicode_AsWideCharString(str_path, NULL);
if (wcs_path == NULL) {
Py_DECREF(cexe);
Py_DECREF(m);
return NULL;
}
@ -3546,7 +3552,6 @@ PyInit__tkinter(void)
#endif /* MS_WINDOWS */
}
Py_XDECREF(cexe);
Py_DECREF(uexe);
}
if (PyErr_Occurred()) {

View file

@ -3,6 +3,7 @@
#include "pycore_pyerrors.h" // _Py_DumpExtensionModules
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_signal.h" // Py_NSIG
#include "pycore_sysmodule.h" // _PySys_GetRequiredAttr()
#include "pycore_traceback.h" // _Py_DumpTracebackThreads
#include <object.h>
@ -104,14 +105,13 @@ faulthandler_get_fileno(PyObject **file_ptr)
PyObject *file = *file_ptr;
if (file == NULL || file == Py_None) {
PyThreadState *tstate = _PyThreadState_GET();
file = _PySys_GetAttr(tstate, &_Py_ID(stderr));
file = _PySys_GetRequiredAttr(&_Py_ID(stderr));
if (file == NULL) {
PyErr_SetString(PyExc_RuntimeError, "unable to get sys.stderr");
return -1;
}
if (file == Py_None) {
PyErr_SetString(PyExc_RuntimeError, "sys.stderr is None");
Py_DECREF(file);
return -1;
}
}
@ -127,10 +127,15 @@ faulthandler_get_fileno(PyObject **file_ptr)
*file_ptr = NULL;
return fd;
}
else {
Py_INCREF(file);
}
result = PyObject_CallMethodNoArgs(file, &_Py_ID(fileno));
if (result == NULL)
if (result == NULL) {
Py_DECREF(file);
return -1;
}
fd = -1;
if (PyLong_Check(result)) {
@ -143,6 +148,7 @@ faulthandler_get_fileno(PyObject **file_ptr)
if (fd == -1) {
PyErr_SetString(PyExc_RuntimeError,
"file.fileno() is not a valid file descriptor");
Py_DECREF(file);
return -1;
}
@ -225,19 +231,23 @@ faulthandler_dump_traceback_py(PyObject *self,
return NULL;
tstate = get_thread_state();
if (tstate == NULL)
if (tstate == NULL) {
Py_XDECREF(file);
return NULL;
}
if (all_threads) {
errmsg = _Py_DumpTracebackThreads(fd, NULL, tstate);
if (errmsg != NULL) {
PyErr_SetString(PyExc_RuntimeError, errmsg);
Py_XDECREF(file);
return NULL;
}
}
else {
_Py_DumpTraceback(fd, tstate);
}
Py_XDECREF(file);
if (PyErr_CheckSignals())
return NULL;
@ -499,10 +509,11 @@ faulthandler_py_enable(PyObject *self, PyObject *args, PyObject *kwargs)
return NULL;
tstate = get_thread_state();
if (tstate == NULL)
if (tstate == NULL) {
Py_XDECREF(file);
return NULL;
}
Py_XINCREF(file);
Py_XSETREF(fatal_error.file, file);
fatal_error.fd = fd;
fatal_error.all_threads = all_threads;
@ -692,12 +703,14 @@ faulthandler_dump_traceback_later(PyObject *self,
if (!thread.running) {
thread.running = PyThread_allocate_lock();
if (!thread.running) {
Py_XDECREF(file);
return PyErr_NoMemory();
}
}
if (!thread.cancel_event) {
thread.cancel_event = PyThread_allocate_lock();
if (!thread.cancel_event || !thread.running) {
Py_XDECREF(file);
return PyErr_NoMemory();
}
@ -709,6 +722,7 @@ faulthandler_dump_traceback_later(PyObject *self,
/* format the timeout */
header = format_timeout(timeout_us);
if (header == NULL) {
Py_XDECREF(file);
return PyErr_NoMemory();
}
header_len = strlen(header);
@ -716,7 +730,6 @@ faulthandler_dump_traceback_later(PyObject *self,
/* Cancel previous thread, if running */
cancel_dump_traceback_later();
Py_XINCREF(file);
Py_XSETREF(thread.file, file);
thread.fd = fd;
/* the downcast is safe: we check that 0 < timeout_us < PY_TIMEOUT_MAX */
@ -878,14 +891,17 @@ faulthandler_register_py(PyObject *self,
if (user_signals == NULL) {
user_signals = PyMem_Calloc(Py_NSIG, sizeof(user_signal_t));
if (user_signals == NULL)
if (user_signals == NULL) {
Py_XDECREF(file);
return PyErr_NoMemory();
}
}
user = &user_signals[signum];
if (!user->enabled) {
#ifdef FAULTHANDLER_USE_ALT_STACK
if (faulthandler_allocate_stack() < 0) {
Py_XDECREF(file);
return NULL;
}
#endif
@ -893,13 +909,13 @@ faulthandler_register_py(PyObject *self,
err = faulthandler_register(signum, chain, &previous);
if (err) {
PyErr_SetFromErrno(PyExc_OSError);
Py_XDECREF(file);
return NULL;
}
user->previous = previous;
}
Py_XINCREF(file);
Py_XSETREF(user->file, file);
user->fd = fd;
user->all_threads = all_threads;

View file

@ -49,8 +49,13 @@ Revision history:
/* syslog module */
#ifndef Py_BUILD_CORE_BUILTIN
# define Py_BUILD_CORE_MODULE 1
#endif
#include "Python.h"
#include "osdefs.h" // SEP
#include "pycore_sysmodule.h" // _PySys_GetOptionalAttrString()
#include <syslog.h>
@ -84,45 +89,50 @@ syslog_get_argv(void)
Py_ssize_t argv_len, scriptlen;
PyObject *scriptobj;
Py_ssize_t slash;
PyObject *argv = PySys_GetObject("argv");
PyObject *argv;
if (argv == NULL) {
return(NULL);
if (_PySys_GetOptionalAttrString("argv", &argv) <= 0) {
return NULL;
}
argv_len = PyList_Size(argv);
if (argv_len == -1) {
PyErr_Clear();
return(NULL);
Py_DECREF(argv);
return NULL;
}
if (argv_len == 0) {
return(NULL);
Py_DECREF(argv);
return NULL;
}
scriptobj = PyList_GetItem(argv, 0);
Py_XINCREF(scriptobj);
Py_DECREF(argv);
if (scriptobj == NULL) {
PyErr_Clear();
return NULL;
}
if (!PyUnicode_Check(scriptobj)) {
return(NULL);
Py_DECREF(scriptobj);
return NULL;
}
scriptlen = PyUnicode_GET_LENGTH(scriptobj);
if (scriptlen == 0) {
return(NULL);
Py_DECREF(scriptobj);
return NULL;
}
slash = PyUnicode_FindChar(scriptobj, SEP, 0, scriptlen, -1);
if (slash == -2) {
PyErr_Clear();
Py_DECREF(scriptobj);
return NULL;
}
if (slash != -1) {
return PyUnicode_Substring(scriptobj, slash + 1, scriptlen);
} else {
Py_INCREF(scriptobj);
return(scriptobj);
Py_SETREF(scriptobj, PyUnicode_Substring(scriptobj, slash + 1, scriptlen));
}
return scriptobj;
}
@ -156,6 +166,9 @@ syslog_openlog_impl(PyObject *module, PyObject *ident, long logopt,
else {
/* get sys.argv[0] or NULL if we can't for some reason */
ident = syslog_get_argv();
if (ident == NULL && PyErr_Occurred()) {
return NULL;
}
}
/* At this point, ident should be INCREF()ed. openlog(3) does not