https://github.com/python/cpython/commit/89a79fc919419bfe817da13bc2a4437908d7fc07
commit: 89a79fc919419bfe817da13bc2a4437908d7fc07
branch: 3.12
author: Serhiy Storchaka <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2025-02-26T17:20:47+02:00
summary:
[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 0ef4ffeefd1737c18dc9326133c7894d58108c2e)
(cherry picked from commit 7c1b76fce8c8df00da38830f72dbdde6881a33be)
(cherry picked from commit 2ab7e1135a2d5ca45b60881ece27729e4fc0ee8b)
files:
A Misc/NEWS.d/next/Core and
Builtins/2025-02-24-14-25-36.gh-issue-130163.rGpc9v.rst
M Include/internal/pycore_sysmodule.h
M Lib/test/test_builtin.py
M Lib/test/test_print.py
M Lib/test/test_sys.py
M Modules/_cursesmodule.c
M Modules/_pickle.c
M Modules/_threadmodule.c
M Modules/_tkinter.c
M Modules/faulthandler.c
M Modules/syslogmodule.c
M Python/_warnings.c
M Python/bltinmodule.c
M Python/errors.c
M Python/import.c
M Python/initconfig.c
M Python/intrinsics.c
M Python/pylifecycle.c
M Python/pythonrun.c
M Python/sysmodule.c
M Python/traceback.c
diff --git a/Include/internal/pycore_sysmodule.h
b/Include/internal/pycore_sysmodule.h
index b4b1febafa4479..e76c269100201d 100644
--- a/Include/internal/pycore_sysmodule.h
+++ b/Include/internal/pycore_sysmodule.h
@@ -8,6 +8,11 @@ extern "C" {
# error "this header requires Py_BUILD_CORE define"
#endif
+PyAPI_FUNC(int) _PySys_GetOptionalAttr(PyObject *, PyObject **);
+PyAPI_FUNC(int) _PySys_GetOptionalAttrString(const char *, PyObject **);
+PyAPI_FUNC(PyObject *) _PySys_GetRequiredAttr(PyObject *);
+PyAPI_FUNC(PyObject *) _PySys_GetRequiredAttrString(const char *);
+
PyAPI_FUNC(int) _PySys_Audit(
PyThreadState *tstate,
const char *event,
diff --git a/Lib/test/test_builtin.py b/Lib/test/test_builtin.py
index c71c56877f690f..5f2ed5c30fcde0 100644
--- a/Lib/test/test_builtin.py
+++ b/Lib/test/test_builtin.py
@@ -1526,6 +1526,29 @@ def test_input(self):
sys.stdout = savestdout
fp.close()
+ def test_input_gh130163(self):
+ class X(io.StringIO):
+ def __getattribute__(self, name):
+ nonlocal patch
+ if patch:
+ patch = False
+ sys.stdout = X()
+ sys.stderr = X()
+ sys.stdin = X('input\n')
+ support.gc_collect()
+ return io.StringIO.__getattribute__(self, name)
+
+ with (support.swap_attr(sys, 'stdout', None),
+ support.swap_attr(sys, 'stderr', None),
+ support.swap_attr(sys, 'stdin', None)):
+ patch = False
+ # the only references:
+ sys.stdout = X()
+ sys.stderr = X()
+ sys.stdin = X('input\n')
+ patch = True
+ input() # should not crash
+
# test_int(): see test_int.py for tests of built-in function int().
def test_repr(self):
diff --git a/Lib/test/test_print.py b/Lib/test/test_print.py
index 5f1bfd9e30db98..a782225ce99971 100644
--- a/Lib/test/test_print.py
+++ b/Lib/test/test_print.py
@@ -129,6 +129,17 @@ def flush(self):
raise RuntimeError
self.assertRaises(RuntimeError, print, 1, file=noflush(), flush=True)
+ def test_gh130163(self):
+ class X:
+ def __str__(self):
+ sys.stdout = StringIO()
+ support.gc_collect()
+ return 'foo'
+
+ with support.swap_attr(sys, 'stdout', None):
+ sys.stdout = StringIO() # the only reference
+ print(X()) # should not crash
+
class TestPy2MigrationHint(unittest.TestCase):
"""Test that correct hint is produced analogous to Python3 syntax,
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
index 2f06299f6db6a9..51afa29c567cc6 100644
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -1,6 +1,7 @@
import builtins
import codecs
import gc
+import io
import locale
import operator
import os
@@ -79,6 +80,18 @@ def baddisplayhook(obj):
code = compile("42", "<string>", "single")
self.assertRaises(ValueError, eval, code)
+ def test_gh130163(self):
+ class X:
+ def __repr__(self):
+ sys.stdout = io.StringIO()
+ support.gc_collect()
+ return 'foo'
+
+ with support.swap_attr(sys, 'stdout', None):
+ sys.stdout = io.StringIO() # the only reference
+ sys.displayhook(X()) # should not crash
+
+
class ActiveExceptionTests(unittest.TestCase):
def test_exc_info_no_exception(self):
self.assertEqual(sys.exc_info(), (None, None, None))
diff --git a/Misc/NEWS.d/next/Core and
Builtins/2025-02-24-14-25-36.gh-issue-130163.rGpc9v.rst b/Misc/NEWS.d/next/Core
and Builtins/2025-02-24-14-25-36.gh-issue-130163.rGpc9v.rst
new file mode 100644
index 00000000000000..590a3fa437b936
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and
Builtins/2025-02-24-14-25-36.gh-issue-130163.rGpc9v.rst
@@ -0,0 +1,2 @@
+Fix possible crashes related to concurrent
+change and use of the :mod:`sys` module attributes.
diff --git a/Modules/_cursesmodule.c b/Modules/_cursesmodule.c
index 3fc7f88c61ede4..26c515136973a2 100644
--- a/Modules/_cursesmodule.c
+++ b/Modules/_cursesmodule.c
@@ -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;
}
diff --git a/Modules/_pickle.c b/Modules/_pickle.c
index b8f701c2af2e67..c4b59700d3ef98 100644
--- a/Modules/_pickle.c
+++ b/Modules/_pickle.c
@@ -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__);
diff --git a/Modules/_threadmodule.c b/Modules/_threadmodule.c
index 366ee6186de0d5..56a9f3d893650f 100644
--- a/Modules/_threadmodule.c
+++ b/Modules/_threadmodule.c
@@ -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);
diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c
index 6b5fcb8a365b61..60f66a556842eb 100644
--- a/Modules/_tkinter.c
+++ b/Modules/_tkinter.c
@@ -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()) {
diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c
index f3062a71ab83bd..2f2b00787edd76 100644
--- a/Modules/faulthandler.c
+++ b/Modules/faulthandler.c
@@ -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;
diff --git a/Modules/syslogmodule.c b/Modules/syslogmodule.c
index c925a42dc05c53..55ed2426fb4c25 100644
--- a/Modules/syslogmodule.c
+++ b/Modules/syslogmodule.c
@@ -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
diff --git a/Python/_warnings.c b/Python/_warnings.c
index 1f91edbf5cb5dc..bcfd241df2357c 100644
--- a/Python/_warnings.c
+++ b/Python/_warnings.c
@@ -5,6 +5,8 @@
#include "pycore_pyerrors.h"
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_frame.h"
+#include "pycore_sysmodule.h" // _PySys_GetOptionalAttr()
+
#include "clinic/_warnings.c.h"
#define MODULE_NAME "_warnings"
@@ -493,7 +495,7 @@ static void
show_warning(PyThreadState *tstate, PyObject *filename, int lineno,
PyObject *text, PyObject *category, PyObject *sourceline)
{
- PyObject *f_stderr;
+ PyObject *f_stderr = NULL;
PyObject *name;
char lineno_str[128];
@@ -504,8 +506,7 @@ show_warning(PyThreadState *tstate, PyObject *filename, int
lineno,
goto error;
}
- f_stderr = _PySys_GetAttr(tstate, &_Py_ID(stderr));
- if (f_stderr == NULL) {
+ if (_PySys_GetOptionalAttr(&_Py_ID(stderr), &f_stderr) <= 0) {
fprintf(stderr, "lost sys.stderr\n");
goto error;
}
@@ -558,6 +559,7 @@ show_warning(PyThreadState *tstate, PyObject *filename, int
lineno,
}
error:
+ Py_XDECREF(f_stderr);
Py_XDECREF(name);
PyErr_Clear();
}
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 8bbdba7eb91675..ab87ee4fc4dfe9 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -9,6 +9,7 @@
#include "pycore_object.h" // _Py_AddToAllObjects()
#include "pycore_pyerrors.h" // _PyErr_NoMemory()
#include "pycore_pystate.h" // _PyThreadState_GET()
+#include "pycore_sysmodule.h" // _PySys_GetRequiredAttr()
#include "pycore_tuple.h" // _PyTuple_FromArray()
#include "pycore_ceval.h" // _PyEval_Vector()
@@ -455,18 +456,16 @@ builtin_callable(PyObject *module, PyObject *obj)
static PyObject *
builtin_breakpoint(PyObject *self, PyObject *const *args, Py_ssize_t nargs,
PyObject *keywords)
{
- PyObject *hook = PySys_GetObject("breakpointhook");
-
+ PyObject *hook = _PySys_GetRequiredAttrString("breakpointhook");
if (hook == NULL) {
- PyErr_SetString(PyExc_RuntimeError, "lost sys.breakpointhook");
return NULL;
}
if (PySys_Audit("builtins.breakpoint", "O", hook) < 0) {
+ Py_DECREF(hook);
return NULL;
}
- Py_INCREF(hook);
PyObject *retval = PyObject_Vectorcall(hook, args, nargs, keywords);
Py_DECREF(hook);
return retval;
@@ -2003,18 +2002,20 @@ builtin_print_impl(PyObject *module, PyObject *args,
PyObject *sep,
int i, err;
if (file == Py_None) {
- PyThreadState *tstate = _PyThreadState_GET();
- file = _PySys_GetAttr(tstate, &_Py_ID(stdout));
+ file = _PySys_GetRequiredAttr(&_Py_ID(stdout));
if (file == NULL) {
- PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
return NULL;
}
/* sys.stdout may be None when FILE* stdout isn't connected */
if (file == Py_None) {
+ Py_DECREF(file);
Py_RETURN_NONE;
}
}
+ else {
+ Py_INCREF(file);
+ }
if (sep == Py_None) {
sep = NULL;
@@ -2023,6 +2024,7 @@ builtin_print_impl(PyObject *module, PyObject *args,
PyObject *sep,
PyErr_Format(PyExc_TypeError,
"sep must be None or a string, not %.200s",
Py_TYPE(sep)->tp_name);
+ Py_DECREF(file);
return NULL;
}
if (end == Py_None) {
@@ -2032,6 +2034,7 @@ builtin_print_impl(PyObject *module, PyObject *args,
PyObject *sep,
PyErr_Format(PyExc_TypeError,
"end must be None or a string, not %.200s",
Py_TYPE(end)->tp_name);
+ Py_DECREF(file);
return NULL;
}
@@ -2044,11 +2047,13 @@ builtin_print_impl(PyObject *module, PyObject *args,
PyObject *sep,
err = PyFile_WriteObject(sep, file, Py_PRINT_RAW);
}
if (err) {
+ Py_DECREF(file);
return NULL;
}
}
err = PyFile_WriteObject(PyTuple_GET_ITEM(args, i), file,
Py_PRINT_RAW);
if (err) {
+ Py_DECREF(file);
return NULL;
}
}
@@ -2060,16 +2065,19 @@ builtin_print_impl(PyObject *module, PyObject *args,
PyObject *sep,
err = PyFile_WriteObject(end, file, Py_PRINT_RAW);
}
if (err) {
+ Py_DECREF(file);
return NULL;
}
if (flush) {
PyObject *tmp = PyObject_CallMethodNoArgs(file, &_Py_ID(flush));
if (tmp == NULL) {
+ Py_DECREF(file);
return NULL;
}
Py_DECREF(tmp);
}
+ Py_DECREF(file);
Py_RETURN_NONE;
}
@@ -2094,36 +2102,41 @@ static PyObject *
builtin_input_impl(PyObject *module, PyObject *prompt)
/*[clinic end generated code: output=83db5a191e7a0d60 input=159c46d4ae40977e]*/
{
- PyThreadState *tstate = _PyThreadState_GET();
- PyObject *fin = _PySys_GetAttr(
- tstate, &_Py_ID(stdin));
- PyObject *fout = _PySys_GetAttr(
- tstate, &_Py_ID(stdout));
- PyObject *ferr = _PySys_GetAttr(
- tstate, &_Py_ID(stderr));
+ PyObject *fin = NULL;
+ PyObject *fout = NULL;
+ PyObject *ferr = NULL;
PyObject *tmp;
long fd;
int tty;
/* Check that stdin/out/err are intact */
- if (fin == NULL || fin == Py_None) {
- PyErr_SetString(PyExc_RuntimeError,
- "input(): lost sys.stdin");
- return NULL;
+ fin = _PySys_GetRequiredAttr(&_Py_ID(stdin));
+ if (fin == NULL) {
+ goto error;
}
- if (fout == NULL || fout == Py_None) {
- PyErr_SetString(PyExc_RuntimeError,
- "input(): lost sys.stdout");
- return NULL;
+ if (fin == Py_None) {
+ PyErr_SetString(PyExc_RuntimeError, "lost sys.stdin");
+ goto error;
}
- if (ferr == NULL || ferr == Py_None) {
- PyErr_SetString(PyExc_RuntimeError,
- "input(): lost sys.stderr");
- return NULL;
+ fout = _PySys_GetRequiredAttr(&_Py_ID(stdout));
+ if (fout == NULL) {
+ goto error;
+ }
+ if (fout == Py_None) {
+ PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
+ goto error;
+ }
+ ferr = _PySys_GetRequiredAttr(&_Py_ID(stderr));
+ if (ferr == NULL) {
+ goto error;
+ }
+ if (ferr == Py_None) {
+ PyErr_SetString(PyExc_RuntimeError, "lost sys.stderr");
+ goto error;
}
if (PySys_Audit("builtins.input", "O", prompt ? prompt : Py_None) < 0) {
- return NULL;
+ goto error;
}
/* First of all, flush stderr */
@@ -2144,8 +2157,9 @@ builtin_input_impl(PyObject *module, PyObject *prompt)
else {
fd = PyLong_AsLong(tmp);
Py_DECREF(tmp);
- if (fd < 0 && PyErr_Occurred())
- return NULL;
+ if (fd < 0 && PyErr_Occurred()) {
+ goto error;
+ }
tty = fd == fileno(stdin) && isatty(fd);
}
if (tty) {
@@ -2158,7 +2172,7 @@ builtin_input_impl(PyObject *module, PyObject *prompt)
fd = PyLong_AsLong(tmp);
Py_DECREF(tmp);
if (fd < 0 && PyErr_Occurred())
- return NULL;
+ goto error;
tty = fd == fileno(stdout) && isatty(fd);
}
}
@@ -2283,10 +2297,13 @@ builtin_input_impl(PyObject *module, PyObject *prompt)
if (result != NULL) {
if (PySys_Audit("builtins.input/result", "O", result) < 0) {
- return NULL;
+ goto error;
}
}
+ Py_DECREF(fin);
+ Py_DECREF(fout);
+ Py_DECREF(ferr);
return result;
_readline_errors:
@@ -2296,7 +2313,7 @@ builtin_input_impl(PyObject *module, PyObject *prompt)
Py_XDECREF(stdout_errors);
Py_XDECREF(po);
if (tty)
- return NULL;
+ goto error;
PyErr_Clear();
}
@@ -2304,14 +2321,25 @@ builtin_input_impl(PyObject *module, PyObject *prompt)
/* Fallback if we're not interactive */
if (prompt != NULL) {
if (PyFile_WriteObject(prompt, fout, Py_PRINT_RAW) != 0)
- return NULL;
+ goto error;
}
tmp = PyObject_CallMethodNoArgs(fout, &_Py_ID(flush));
if (tmp == NULL)
PyErr_Clear();
else
Py_DECREF(tmp);
- return PyFile_GetLine(fin, -1);
+
+ tmp = PyFile_GetLine(fin, -1);
+ Py_DECREF(fin);
+ Py_DECREF(fout);
+ Py_DECREF(ferr);
+ return tmp;
+
+error:
+ Py_XDECREF(fin);
+ Py_XDECREF(fout);
+ Py_XDECREF(ferr);
+ return NULL;
}
diff --git a/Python/errors.c b/Python/errors.c
index bfc37f3dbb6ff0..79cf4e07f3e010 100644
--- a/Python/errors.c
+++ b/Python/errors.c
@@ -1562,14 +1562,15 @@ write_unraisable_exc(PyThreadState *tstate, PyObject
*exc_type,
PyObject *exc_value, PyObject *exc_tb, PyObject *err_msg,
PyObject *obj)
{
- PyObject *file = _PySys_GetAttr(tstate, &_Py_ID(stderr));
+ PyObject *file;
+ if (_PySys_GetOptionalAttr(&_Py_ID(stderr), &file) < 0) {
+ return -1;
+ }
if (file == NULL || file == Py_None) {
+ Py_XDECREF(file);
return 0;
}
- /* Hold a strong reference to ensure that sys.stderr doesn't go away
- while we use it */
- Py_INCREF(file);
int res = write_unraisable_exc_file(tstate, exc_type, exc_value, exc_tb,
err_msg, obj, file);
Py_DECREF(file);
@@ -1666,13 +1667,20 @@ _PyErr_WriteUnraisableMsg(const char *err_msg_str,
PyObject *obj)
goto error;
}
- PyObject *hook = _PySys_GetAttr(tstate, &_Py_ID(unraisablehook));
+ PyObject *hook;
+ if (_PySys_GetOptionalAttr(&_Py_ID(unraisablehook), &hook) < 0) {
+ Py_DECREF(hook_args);
+ err_msg_str = NULL;
+ obj = NULL;
+ goto error;
+ }
if (hook == NULL) {
Py_DECREF(hook_args);
goto default_hook;
}
if (_PySys_Audit(tstate, "sys.unraisablehook", "OO", hook, hook_args) < 0)
{
+ Py_DECREF(hook);
Py_DECREF(hook_args);
err_msg_str = "Exception ignored in audit hook";
obj = NULL;
@@ -1680,11 +1688,13 @@ _PyErr_WriteUnraisableMsg(const char *err_msg_str,
PyObject *obj)
}
if (hook == Py_None) {
+ Py_DECREF(hook);
Py_DECREF(hook_args);
goto default_hook;
}
PyObject *res = PyObject_CallOneArg(hook, hook_args);
+ Py_DECREF(hook);
Py_DECREF(hook_args);
if (res != NULL) {
Py_DECREF(res);
diff --git a/Python/import.c b/Python/import.c
index 66391c04a0baaa..ac741cb64f6b61 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -2431,19 +2431,15 @@ PyObject *
PyImport_GetImporter(PyObject *path)
{
PyThreadState *tstate = _PyThreadState_GET();
- PyObject *path_importer_cache = PySys_GetObject("path_importer_cache");
+ PyObject *path_importer_cache =
_PySys_GetRequiredAttrString("path_importer_cache");
if (path_importer_cache == NULL) {
- PyErr_SetString(PyExc_RuntimeError, "lost sys.path_importer_cache");
return NULL;
}
- Py_INCREF(path_importer_cache);
- PyObject *path_hooks = PySys_GetObject("path_hooks");
+ PyObject *path_hooks = _PySys_GetRequiredAttrString("path_hooks");
if (path_hooks == NULL) {
- PyErr_SetString(PyExc_RuntimeError, "lost sys.path_hooks");
Py_DECREF(path_importer_cache);
return NULL;
}
- Py_INCREF(path_hooks);
PyObject *importer = get_path_importer(tstate, path_importer_cache,
path_hooks, path);
Py_DECREF(path_hooks);
Py_DECREF(path_importer_cache);
@@ -2745,15 +2741,31 @@ import_find_and_load(PyThreadState *tstate, PyObject
*abs_name)
_PyTime_t t1 = 0, accumulated_copy = accumulated;
- PyObject *sys_path = PySys_GetObject("path");
- PyObject *sys_meta_path = PySys_GetObject("meta_path");
- PyObject *sys_path_hooks = PySys_GetObject("path_hooks");
+ PyObject *sys_path, *sys_meta_path, *sys_path_hooks;
+ if (_PySys_GetOptionalAttrString("path", &sys_path) < 0) {
+ return NULL;
+ }
+ if (_PySys_GetOptionalAttrString("meta_path", &sys_meta_path) < 0) {
+ Py_XDECREF(sys_path);
+ return NULL;
+ }
+ if (_PySys_GetOptionalAttrString("path_hooks", &sys_path_hooks) < 0) {
+ Py_XDECREF(sys_meta_path);
+ Py_XDECREF(sys_path);
+ return NULL;
+ }
if (_PySys_Audit(tstate, "import", "OOOOO",
abs_name, Py_None, sys_path ? sys_path : Py_None,
sys_meta_path ? sys_meta_path : Py_None,
sys_path_hooks ? sys_path_hooks : Py_None) < 0) {
+ Py_XDECREF(sys_path_hooks);
+ Py_XDECREF(sys_meta_path);
+ Py_XDECREF(sys_path);
return NULL;
}
+ Py_XDECREF(sys_path_hooks);
+ Py_XDECREF(sys_meta_path);
+ Py_XDECREF(sys_path);
/* XOptions is initialized after first some imports.
@@ -3207,10 +3219,8 @@ _PyImport_FiniCore(PyInterpreterState *interp)
static int
init_zipimport(PyThreadState *tstate, int verbose)
{
- PyObject *path_hooks = PySys_GetObject("path_hooks");
+ PyObject *path_hooks = _PySys_GetRequiredAttrString("path_hooks");
if (path_hooks == NULL) {
- _PyErr_SetString(tstate, PyExc_RuntimeError,
- "unable to get sys.path_hooks");
return -1;
}
@@ -3230,12 +3240,14 @@ init_zipimport(PyThreadState *tstate, int verbose)
int err = PyList_Insert(path_hooks, 0, zipimporter);
Py_DECREF(zipimporter);
if (err < 0) {
+ Py_DECREF(path_hooks);
return -1;
}
if (verbose) {
PySys_WriteStderr("# installed zipimport hook\n");
}
}
+ Py_DECREF(path_hooks);
return 0;
}
diff --git a/Python/initconfig.c b/Python/initconfig.c
index 192089b5cc3e53..6eb09ab8eec394 100644
--- a/Python/initconfig.c
+++ b/Python/initconfig.c
@@ -9,6 +9,7 @@
#include "pycore_pylifecycle.h" // _Py_PreInitializeFromConfig()
#include "pycore_pymem.h" // _PyMem_SetDefaultAllocator()
#include "pycore_pystate.h" // _PyThreadState_GET()
+#include "pycore_sysmodule.h" // _PySys_GetOptionalAttrString()
#include "osdefs.h" // DELIM
@@ -3144,10 +3145,13 @@ _Py_DumpPathConfig(PyThreadState *tstate)
#define DUMP_SYS(NAME) \
do { \
- obj = PySys_GetObject(#NAME); \
PySys_FormatStderr(" sys.%s = ", #NAME); \
+ if (_PySys_GetOptionalAttrString(#NAME, &obj) < 0) { \
+ PyErr_Clear(); \
+ } \
if (obj != NULL) { \
PySys_FormatStderr("%A", obj); \
+ Py_DECREF(obj); \
} \
else { \
PySys_WriteStderr("(not set)"); \
@@ -3165,7 +3169,8 @@ _Py_DumpPathConfig(PyThreadState *tstate)
DUMP_SYS(exec_prefix);
#undef DUMP_SYS
- PyObject *sys_path = PySys_GetObject("path"); /* borrowed reference */
+ PyObject *sys_path;
+ (void) _PySys_GetOptionalAttrString("path", &sys_path);
if (sys_path != NULL && PyList_Check(sys_path)) {
PySys_WriteStderr(" sys.path = [\n");
Py_ssize_t len = PyList_GET_SIZE(sys_path);
@@ -3175,6 +3180,7 @@ _Py_DumpPathConfig(PyThreadState *tstate)
}
PySys_WriteStderr(" ]\n");
}
+ Py_XDECREF(sys_path);
_PyErr_SetRaisedException(tstate, exc);
}
diff --git a/Python/intrinsics.c b/Python/intrinsics.c
index c6f5ac5402d644..50b279693bf9fa 100644
--- a/Python/intrinsics.c
+++ b/Python/intrinsics.c
@@ -8,6 +8,7 @@
#include "pycore_global_objects.h"
#include "pycore_intrinsics.h"
#include "pycore_pyerrors.h"
+#include "pycore_sysmodule.h" // _PySys_GetRequiredAttr()
#include "pycore_typevarobject.h"
@@ -21,16 +22,16 @@ no_intrinsic(PyThreadState* tstate, PyObject *unused)
}
static PyObject *
-print_expr(PyThreadState* tstate, PyObject *value)
+print_expr(PyThreadState* Py_UNUSED(ignored), PyObject *value)
{
- PyObject *hook = _PySys_GetAttr(tstate, &_Py_ID(displayhook));
+ PyObject *hook = _PySys_GetRequiredAttr(&_Py_ID(displayhook));
// Can't use ERROR_IF here.
if (hook == NULL) {
- _PyErr_SetString(tstate, PyExc_RuntimeError,
- "lost sys.displayhook");
return NULL;
}
- return PyObject_CallOneArg(hook, value);
+ PyObject *res = PyObject_CallOneArg(hook, value);
+ Py_DECREF(hook);
+ return res;
}
static int
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index ef4e60765705b9..f5bea14b16b401 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -1189,8 +1189,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) {
@@ -1199,6 +1203,7 @@ init_interp_main(PyThreadState *tstate)
}
Py_XDECREF(warnings_module);
}
+ Py_XDECREF(warnoptions);
interp->runtime->initialized = 1;
}
@@ -1667,24 +1672,32 @@ 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;
PyObject *tmp;
int status = 0;
- if (fout != NULL && fout != Py_None && !file_is_closed(fout)) {
- tmp = PyObject_CallMethodNoArgs(fout, &_Py_ID(flush));
+ if (_PySys_GetOptionalAttr(&_Py_ID(stdout), &file) < 0) {
+ status = -1;
+ }
+ else if (file != NULL && file != Py_None && !file_is_closed(file)) {
+ tmp = PyObject_CallMethodNoArgs(file, &_Py_ID(flush));
if (tmp == NULL) {
- PyErr_WriteUnraisable(fout);
status = -1;
}
else
Py_DECREF(tmp);
}
+ if (status < 0) {
+ PyErr_WriteUnraisable(file);
+ }
+ Py_XDECREF(file);
- if (ferr != NULL && ferr != Py_None && !file_is_closed(ferr)) {
- tmp = PyObject_CallMethodNoArgs(ferr, &_Py_ID(flush));
+ if (_PySys_GetOptionalAttr(&_Py_ID(stderr), &file) < 0) {
+ PyErr_Clear();
+ status = -1;
+ }
+ else if (file != NULL && file != Py_None && !file_is_closed(file)) {
+ tmp = PyObject_CallMethodNoArgs(file, &_Py_ID(flush));
if (tmp == NULL) {
PyErr_Clear();
status = -1;
@@ -1692,6 +1705,7 @@ flush_std_files(void)
else
Py_DECREF(tmp);
}
+ Py_XDECREF(file);
return status;
}
@@ -2655,10 +2669,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;
}
@@ -2678,6 +2696,7 @@ _Py_FatalError_PrintExc(PyThreadState *tstate)
else {
Py_DECREF(res);
}
+ Py_DECREF(ferr);
return has_tb;
}
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index cf84573a8e6147..ac71e73311f297 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -115,17 +115,35 @@ _PyRun_InteractiveLoopObject(FILE *fp, PyObject
*filename, PyCompilerFlags *flag
flags = &local_flags;
}
- PyThreadState *tstate = _PyThreadState_GET();
- PyObject *v = _PySys_GetAttr(tstate, &_Py_ID(ps1));
+ PyObject *v;
+ if (_PySys_GetOptionalAttr(&_Py_ID(ps1), &v) < 0) {
+ PyErr_Print();
+ return -1;
+ }
if (v == NULL) {
- _PySys_SetAttr(&_Py_ID(ps1), v = PyUnicode_FromString(">>> "));
- Py_XDECREF(v);
+ v = PyUnicode_FromString(">>> ");
+ if (v == NULL) {
+ PyErr_Clear();
+ }
+ if (_PySys_SetAttr(&_Py_ID(ps1), v) < 0) {
+ PyErr_Clear();
+ }
+ }
+ Py_XDECREF(v);
+ if (_PySys_GetOptionalAttr(&_Py_ID(ps2), &v) < 0) {
+ PyErr_Print();
+ return -1;
}
- v = _PySys_GetAttr(tstate, &_Py_ID(ps2));
if (v == NULL) {
- _PySys_SetAttr(&_Py_ID(ps2), v = PyUnicode_FromString("... "));
- Py_XDECREF(v);
+ v = PyUnicode_FromString("... ");
+ if (v == NULL) {
+ PyErr_Clear();
+ }
+ if (_PySys_SetAttr(&_Py_ID(ps2), v) < 0) {
+ PyErr_Clear();
+ }
}
+ Py_XDECREF(v);
#ifdef Py_REF_DEBUG
int show_ref_count = _Py_GetConfig()->show_ref_count;
@@ -190,11 +208,12 @@ PyRun_InteractiveOneObjectEx(FILE *fp, PyObject *filename,
PyArena *arena;
const char *ps1 = "", *ps2 = "", *enc = NULL;
int errcode = 0;
- PyThreadState *tstate = _PyThreadState_GET();
if (fp == stdin) {
/* Fetch encoding from sys.stdin if possible. */
- v = _PySys_GetAttr(tstate, &_Py_ID(stdin));
+ if (_PySys_GetOptionalAttr(&_Py_ID(stdin), &v) < 0) {
+ return -1;
+ }
if (v && v != Py_None) {
oenc = PyObject_GetAttr(v, &_Py_ID(encoding));
if (oenc)
@@ -202,10 +221,14 @@ PyRun_InteractiveOneObjectEx(FILE *fp, PyObject *filename,
if (!enc)
PyErr_Clear();
}
+ Py_XDECREF(v);
+ }
+ if (_PySys_GetOptionalAttr(&_Py_ID(ps1), &v) < 0) {
+ Py_XDECREF(oenc);
+ return -1;
}
- v = _PySys_GetAttr(tstate, &_Py_ID(ps1));
if (v != NULL) {
- v = PyObject_Str(v);
+ Py_SETREF(v, PyObject_Str(v));
if (v == NULL)
PyErr_Clear();
else if (PyUnicode_Check(v)) {
@@ -216,9 +239,12 @@ PyRun_InteractiveOneObjectEx(FILE *fp, PyObject *filename,
}
}
}
- w = _PySys_GetAttr(tstate, &_Py_ID(ps2));
+ if (_PySys_GetOptionalAttr(&_Py_ID(ps2), &w) < 0) {
+ Py_XDECREF(oenc);
+ return -1;
+ }
if (w != NULL) {
- w = PyObject_Str(w);
+ Py_SETREF(w, PyObject_Str(w));
if (w == NULL)
PyErr_Clear();
else if (PyUnicode_Check(w)) {
@@ -718,8 +744,8 @@ _Py_HandleSystemExit(int *exitcode_p)
exitcode = (int)PyLong_AsLong(exc);
}
else {
- PyThreadState *tstate = _PyThreadState_GET();
- PyObject *sys_stderr = _PySys_GetAttr(tstate, &_Py_ID(stderr));
+ PyObject *sys_stderr;
+ (void) _PySys_GetOptionalAttr(&_Py_ID(stderr), &sys_stderr);
/* We clear the exception here to avoid triggering the assertion
* in PyObject_Str that ensures it won't silently lose exception
* details.
@@ -731,6 +757,7 @@ _Py_HandleSystemExit(int *exitcode_p)
PyObject_Print(exc, stderr, Py_PRINT_RAW);
fflush(stderr);
}
+ Py_XDECREF(sys_stderr);
PySys_WriteStderr("\n");
exitcode = 1;
}
@@ -755,7 +782,7 @@ handle_system_exit(void)
static void
_PyErr_PrintEx(PyThreadState *tstate, int set_sys_last_vars)
{
- PyObject *typ = NULL, *tb = NULL;
+ PyObject *typ = NULL, *tb = NULL, *hook = NULL;
handle_system_exit();
PyObject *exc = _PyErr_GetRaisedException(tstate);
@@ -784,7 +811,9 @@ _PyErr_PrintEx(PyThreadState *tstate, int set_sys_last_vars)
_PyErr_Clear(tstate);
}
}
- PyObject *hook = _PySys_GetAttr(tstate, &_Py_ID(excepthook));
+ if (_PySys_GetOptionalAttr(&_Py_ID(excepthook), &hook) < 0) {
+ PyErr_Clear();
+ }
if (_PySys_Audit(tstate, "sys.excepthook", "OOOO", hook ? hook : Py_None,
typ, exc, tb) < 0) {
if (PyErr_ExceptionMatches(PyExc_RuntimeError)) {
@@ -821,6 +850,7 @@ _PyErr_PrintEx(PyThreadState *tstate, int set_sys_last_vars)
}
done:
+ Py_XDECREF(hook);
Py_XDECREF(typ);
Py_XDECREF(exc);
Py_XDECREF(tb);
@@ -1567,17 +1597,24 @@ _PyErr_Display(PyObject *file, PyObject *unused,
PyObject *value, PyObject *tb)
void
PyErr_Display(PyObject *unused, PyObject *value, PyObject *tb)
{
- PyThreadState *tstate = _PyThreadState_GET();
- PyObject *file = _PySys_GetAttr(tstate, &_Py_ID(stderr));
+ PyObject *file;
+ if (_PySys_GetOptionalAttr(&_Py_ID(stderr), &file) < 0) {
+ PyObject *exc = PyErr_GetRaisedException();
+ _PyObject_Dump(value);
+ fprintf(stderr, "lost sys.stderr\n");
+ _PyObject_Dump(exc);
+ Py_DECREF(exc);
+ return;
+ }
if (file == NULL) {
_PyObject_Dump(value);
fprintf(stderr, "lost sys.stderr\n");
return;
}
if (file == Py_None) {
+ Py_DECREF(file);
return;
}
- Py_INCREF(file);
_PyErr_Display(file, NULL, value, tb);
Py_DECREF(file);
}
@@ -1664,7 +1701,10 @@ PyRun_FileExFlags(FILE *fp, const char *filename, int
start, PyObject *globals,
static void
flush_io_stream(PyThreadState *tstate, PyObject *name)
{
- PyObject *f = _PySys_GetAttr(tstate, name);
+ PyObject *f;
+ if (_PySys_GetOptionalAttr(name, &f) < 0) {
+ PyErr_Clear();
+ }
if (f != NULL) {
PyObject *r = _PyObject_CallMethodNoArgs(f, &_Py_ID(flush));
if (r) {
@@ -1673,6 +1713,7 @@ flush_io_stream(PyThreadState *tstate, PyObject *name)
else {
PyErr_Clear();
}
+ Py_DECREF(f);
}
}
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index 1f7cc655c45ed0..e3bdff15a856bf 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -29,6 +29,7 @@ Data members:
#include "pycore_pymem.h" // _PyMem_SetDefaultAllocator()
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_structseq.h" // _PyStructSequence_InitBuiltinWithFlags()
+#include "pycore_sysmodule.h"
#include "pycore_tuple.h" // _PyTuple_FromArray()
#include "frameobject.h" // PyFrame_FastToLocalsWithError()
@@ -78,23 +79,97 @@ _PySys_GetAttr(PyThreadState *tstate, PyObject *name)
return value;
}
-static PyObject *
-_PySys_GetObject(PyInterpreterState *interp, const char *name)
+ PyObject *
+_PySys_GetRequiredAttr(PyObject *name)
{
- PyObject *sysdict = interp->sysdict;
+ if (!PyUnicode_Check(name)) {
+ PyErr_Format(PyExc_TypeError,
+ "attribute name must be string, not '%.200s'",
+ Py_TYPE(name)->tp_name);
+ return NULL;
+ }
+ PyThreadState *tstate = _PyThreadState_GET();
+ PyObject *sysdict = tstate->interp->sysdict;
if (sysdict == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "no sys module");
return NULL;
}
- return _PyDict_GetItemStringWithError(sysdict, name);
+ PyObject *value = _PyDict_GetItemWithError(sysdict, name);
+ Py_XINCREF(value);
+ if (value == NULL && !_PyErr_Occurred(tstate)) {
+ PyErr_Format(PyExc_RuntimeError, "lost sys.%U", name);
+ }
+ return value;
}
PyObject *
-PySys_GetObject(const char *name)
+_PySys_GetRequiredAttrString(const char *name)
{
PyThreadState *tstate = _PyThreadState_GET();
+ PyObject *sysdict = tstate->interp->sysdict;
+ if (sysdict == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "no sys module");
+ return NULL;
+ }
+ PyObject *value = _PyDict_GetItemStringWithError(sysdict, name);
+ Py_XINCREF(value);
+ if (value == NULL && !_PyErr_Occurred(tstate)) {
+ PyErr_Format(PyExc_RuntimeError, "lost sys.%s", name);
+ }
+ return value;
+}
+int
+_PySys_GetOptionalAttr(PyObject *name, PyObject **value)
+{
+ if (!PyUnicode_Check(name)) {
+ PyErr_Format(PyExc_TypeError,
+ "attribute name must be string, not '%.200s'",
+ Py_TYPE(name)->tp_name);
+ *value = NULL;
+ return -1;
+ }
+ PyThreadState *tstate = _PyThreadState_GET();
+ PyObject *sysdict = tstate->interp->sysdict;
+ if (sysdict == NULL) {
+ *value = NULL;
+ return 0;
+ }
+ *value = _PyDict_GetItemWithError(sysdict, name);
+ if (*value) {
+ Py_INCREF(*value);
+ return 1;
+ }
+ return _PyErr_Occurred(tstate) ? -1 : 0;
+}
+
+int
+_PySys_GetOptionalAttrString(const char *name, PyObject **value)
+{
+ PyThreadState *tstate = _PyThreadState_GET();
+ PyObject *sysdict = tstate->interp->sysdict;
+ if (sysdict == NULL) {
+ *value = NULL;
+ return 0;
+ }
+ *value = _PyDict_GetItemStringWithError(sysdict, name);
+ if (*value) {
+ Py_INCREF(*value);
+ return 1;
+ }
+ return _PyErr_Occurred(tstate) ? -1 : 0;
+}
+
+PyObject *
+PySys_GetObject(const char *name)
+{
+ PyThreadState *tstate = _PyThreadState_GET();
+ PyObject *sysdict = tstate->interp->sysdict;
+ if (sysdict == NULL) {
+ return NULL;
+ }
PyObject *exc = _PyErr_GetRaisedException(tstate);
- PyObject *value = _PySys_GetObject(tstate->interp, name);
+ PyObject *value = _PyDict_GetItemStringWithError(sysdict, name);
/* XXX Suppress a new exception if it was raised and restore
* the old one. */
_PyErr_SetRaisedException(tstate, exc);
@@ -108,6 +183,10 @@ sys_set_object(PyInterpreterState *interp, PyObject *key,
PyObject *v)
return -1;
}
PyObject *sd = interp->sysdict;
+ if (sd == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "no sys module");
+ return -1;
+ }
if (v == NULL) {
v = _PyDict_Pop(sd, key, Py_None);
if (v == NULL) {
@@ -724,9 +803,13 @@ sys_displayhook(PyObject *module, PyObject *o)
}
if (PyObject_SetAttr(builtins, _Py_LATIN1_CHR('_'), Py_None) != 0)
return NULL;
- outf = _PySys_GetAttr(tstate, &_Py_ID(stdout));
- if (outf == NULL || outf == Py_None) {
+ outf = _PySys_GetRequiredAttr(&_Py_ID(stdout));
+ if (outf == NULL) {
+ return NULL;
+ }
+ if (outf == Py_None) {
_PyErr_SetString(tstate, PyExc_RuntimeError, "lost sys.stdout");
+ Py_DECREF(outf);
return NULL;
}
if (PyFile_WriteObject(o, outf, 0) != 0) {
@@ -737,17 +820,23 @@ sys_displayhook(PyObject *module, PyObject *o)
_PyErr_Clear(tstate);
err = sys_displayhook_unencodable(outf, o);
if (err) {
+ Py_DECREF(outf);
return NULL;
}
}
else {
+ Py_DECREF(outf);
return NULL;
}
}
- if (PyFile_WriteObject(_Py_LATIN1_CHR('\n'), outf, Py_PRINT_RAW) != 0)
+ if (PyFile_WriteObject(_Py_LATIN1_CHR('\n'), outf, Py_PRINT_RAW) != 0) {
+ Py_DECREF(outf);
return NULL;
- if (PyObject_SetAttr(builtins, _Py_LATIN1_CHR('_'), o) != 0)
+ }
+ Py_DECREF(outf);
+ if (PyObject_SetAttr(builtins, _Py_LATIN1_CHR('_'), o) != 0) {
return NULL;
+ }
Py_RETURN_NONE;
}
@@ -2610,7 +2699,10 @@ _PySys_ReadPreinitXOptions(PyConfig *config)
static PyObject *
get_warnoptions(PyThreadState *tstate)
{
- PyObject *warnoptions = _PySys_GetAttr(tstate, &_Py_ID(warnoptions));
+ PyObject *warnoptions;
+ if (_PySys_GetOptionalAttr(&_Py_ID(warnoptions), &warnoptions) < 0) {
+ return NULL;
+ }
if (warnoptions == NULL || !PyList_Check(warnoptions)) {
/* PEP432 TODO: we can reach this if warnoptions is NULL in the main
* interpreter config. When that happens, we need to properly set
@@ -2622,6 +2714,7 @@ get_warnoptions(PyThreadState *tstate)
* call optional for embedding applications, thus making this
* reachable again.
*/
+ Py_XDECREF(warnoptions);
warnoptions = PyList_New(0);
if (warnoptions == NULL) {
return NULL;
@@ -2630,7 +2723,6 @@ get_warnoptions(PyThreadState *tstate)
Py_DECREF(warnoptions);
return NULL;
}
- Py_DECREF(warnoptions);
}
return warnoptions;
}
@@ -2644,10 +2736,15 @@ PySys_ResetWarnOptions(void)
return;
}
- PyObject *warnoptions = _PySys_GetAttr(tstate, &_Py_ID(warnoptions));
- if (warnoptions == NULL || !PyList_Check(warnoptions))
+ PyObject *warnoptions;
+ if (_PySys_GetOptionalAttr(&_Py_ID(warnoptions), &warnoptions) < 0) {
+ PyErr_Clear();
return;
- PyList_SetSlice(warnoptions, 0, PyList_GET_SIZE(warnoptions), NULL);
+ }
+ if (warnoptions != NULL && PyList_Check(warnoptions)) {
+ PyList_SetSlice(warnoptions, 0, PyList_GET_SIZE(warnoptions), NULL);
+ }
+ Py_XDECREF(warnoptions);
}
static int
@@ -2659,8 +2756,10 @@ _PySys_AddWarnOptionWithError(PyThreadState *tstate,
PyObject *option)
return -1;
}
if (PyList_Append(warnoptions, option)) {
+ Py_DECREF(warnoptions);
return -1;
}
+ Py_DECREF(warnoptions);
return 0;
}
@@ -2698,16 +2797,24 @@ _Py_COMP_DIAG_POP
int
PySys_HasWarnOptions(void)
{
- PyThreadState *tstate = _PyThreadState_GET();
- PyObject *warnoptions = _PySys_GetAttr(tstate, &_Py_ID(warnoptions));
- return (warnoptions != NULL && PyList_Check(warnoptions)
- && PyList_GET_SIZE(warnoptions) > 0);
+ PyObject *warnoptions;
+ if (_PySys_GetOptionalAttr(&_Py_ID(warnoptions), &warnoptions) < 0) {
+ PyErr_Clear();
+ return 0;
+ }
+ int r = (warnoptions != NULL && PyList_Check(warnoptions) &&
+ PyList_GET_SIZE(warnoptions) > 0);
+ Py_XDECREF(warnoptions);
+ return r;
}
static PyObject *
get_xoptions(PyThreadState *tstate)
{
- PyObject *xoptions = _PySys_GetAttr(tstate, &_Py_ID(_xoptions));
+ PyObject *xoptions;
+ if (_PySys_GetOptionalAttr(&_Py_ID(_xoptions), &xoptions) < 0) {
+ return NULL;
+ }
if (xoptions == NULL || !PyDict_Check(xoptions)) {
/* PEP432 TODO: we can reach this if xoptions is NULL in the main
* interpreter config. When that happens, we need to properly set
@@ -2719,6 +2826,7 @@ get_xoptions(PyThreadState *tstate)
* call optional for embedding applications, thus making this
* reachable again.
*/
+ Py_XDECREF(xoptions);
xoptions = PyDict_New();
if (xoptions == NULL) {
return NULL;
@@ -2727,7 +2835,6 @@ get_xoptions(PyThreadState *tstate)
Py_DECREF(xoptions);
return NULL;
}
- Py_DECREF(xoptions);
}
return xoptions;
}
@@ -2766,11 +2873,13 @@ _PySys_AddXOptionWithError(const wchar_t *s)
}
Py_DECREF(name);
Py_DECREF(value);
+ Py_DECREF(opts);
return 0;
error:
Py_XDECREF(name);
Py_XDECREF(value);
+ Py_XDECREF(opts);
return -1;
}
@@ -2792,7 +2901,9 @@ PyObject *
PySys_GetXOptions(void)
{
PyThreadState *tstate = _PyThreadState_GET();
- return get_xoptions(tstate);
+ PyObject *opts = get_xoptions(tstate);
+ Py_XDECREF(opts);
+ return opts;
}
/* XXX This doc string is too long to be a single string literal in VC++ 5.0.
@@ -3517,16 +3628,15 @@ _PySys_UpdateConfig(PyThreadState *tstate)
#undef COPY_WSTR
// sys.flags
- PyObject *flags = _PySys_GetObject(interp, "flags"); // borrowed ref
+ PyObject *flags = _PySys_GetRequiredAttrString("flags");
if (flags == NULL) {
- if (!_PyErr_Occurred(tstate)) {
- _PyErr_SetString(tstate, PyExc_RuntimeError, "lost sys.flags");
- }
return -1;
}
if (set_flags_from_config(interp, flags) < 0) {
+ Py_DECREF(flags);
return -1;
}
+ Py_DECREF(flags);
SET_SYS("dont_write_bytecode", PyBool_FromLong(!config->write_bytecode));
@@ -3754,12 +3864,15 @@ PySys_SetArgvEx(int argc, wchar_t **argv, int
updatepath)
Py_FatalError("can't compute path0 from argv");
}
- PyObject *sys_path = _PySys_GetAttr(tstate, &_Py_ID(path));
- if (sys_path != NULL) {
+ PyObject *sys_path;
+ if (_PySys_GetOptionalAttr(&_Py_ID(path), &sys_path) < 0) {
+ Py_FatalError("can't get sys.path");
+ }
+ else if (sys_path != NULL) {
if (PyList_Insert(sys_path, 0, path0) < 0) {
- Py_DECREF(path0);
Py_FatalError("can't prepend path0 to sys.path");
}
+ Py_DECREF(sys_path);
}
Py_DECREF(path0);
}
@@ -3847,8 +3960,8 @@ sys_write(PyObject *key, FILE *fp, const char *format,
va_list va)
PyThreadState *tstate = _PyThreadState_GET();
PyObject *exc = _PyErr_GetRaisedException(tstate);
- file = _PySys_GetAttr(tstate, key);
written = PyOS_vsnprintf(buffer, sizeof(buffer), format, va);
+ file = _PySys_GetRequiredAttr(key);
if (sys_pyfile_write(buffer, file) != 0) {
_PyErr_Clear(tstate);
fputs(buffer, fp);
@@ -3858,6 +3971,7 @@ sys_write(PyObject *key, FILE *fp, const char *format,
va_list va)
if (sys_pyfile_write(truncated, file) != 0)
fputs(truncated, fp);
}
+ Py_XDECREF(file);
_PyErr_SetRaisedException(tstate, exc);
}
@@ -3889,15 +4003,16 @@ sys_format(PyObject *key, FILE *fp, const char *format,
va_list va)
PyThreadState *tstate = _PyThreadState_GET();
PyObject *exc = _PyErr_GetRaisedException(tstate);
- file = _PySys_GetAttr(tstate, key);
message = PyUnicode_FromFormatV(format, va);
if (message != NULL) {
+ file = _PySys_GetRequiredAttr(key);
if (sys_pyfile_write_unicode(message, file) != 0) {
_PyErr_Clear(tstate);
utf8 = PyUnicode_AsUTF8(message);
if (utf8 != NULL)
fputs(utf8, fp);
}
+ Py_XDECREF(file);
Py_DECREF(message);
}
_PyErr_SetRaisedException(tstate, exc);
diff --git a/Python/traceback.c b/Python/traceback.c
index fba3594e97ceac..1cb82c57203758 100644
--- a/Python/traceback.c
+++ b/Python/traceback.c
@@ -13,6 +13,7 @@
#include "pycore_pyarena.h" // _PyArena_Free()
#include "pycore_pyerrors.h" // _PyErr_GetRaisedException()
#include "pycore_pystate.h" // _PyThreadState_GET()
+#include "pycore_sysmodule.h" // _PySys_GetOptionalAttr()
#include "pycore_traceback.h" // EXCEPTION_TB_HEADER
#include "../Parser/pegen.h" // _PyPegen_byte_offset_to_character_offset()
@@ -349,9 +350,13 @@ _Py_FindSourceFile(PyObject *filename, char* namebuf,
size_t namelen, PyObject *
taillen = strlen(tail);
PyThreadState *tstate = _PyThreadState_GET();
- syspath = _PySys_GetAttr(tstate, &_Py_ID(path));
- if (syspath == NULL || !PyList_Check(syspath))
+ if (_PySys_GetOptionalAttr(&_Py_ID(path), &syspath) < 0) {
+ PyErr_Clear();
+ goto error;
+ }
+ if (syspath == NULL || !PyList_Check(syspath)) {
goto error;
+ }
npath = PyList_Size(syspath);
open = PyObject_GetAttr(io, &_Py_ID(open));
@@ -394,6 +399,7 @@ _Py_FindSourceFile(PyObject *filename, char* namebuf,
size_t namelen, PyObject *
result = NULL;
finally:
Py_XDECREF(open);
+ Py_XDECREF(syspath);
Py_DECREF(filebytes);
return result;
}
@@ -1064,17 +1070,21 @@ _PyTraceBack_Print_Indented(PyObject *v, int indent,
const char *margin,
PyErr_BadInternalCall();
return -1;
}
- limitv = PySys_GetObject("tracebacklimit");
- if (limitv && PyLong_Check(limitv)) {
+ if (_PySys_GetOptionalAttrString("tracebacklimit", &limitv) < 0) {
+ return -1;
+ }
+ else if (limitv != NULL && PyLong_Check(limitv)) {
int overflow;
limit = PyLong_AsLongAndOverflow(limitv, &overflow);
if (overflow > 0) {
limit = LONG_MAX;
}
else if (limit <= 0) {
+ Py_DECREF(limitv);
return 0;
}
}
+ Py_XDECREF(limitv);
if (_Py_WriteIndentedMargin(indent, header_margin, f) < 0) {
return -1;
}
_______________________________________________
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]