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

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)
This commit is contained in:
Serhiy Storchaka 2025-02-26 00:50:26 +02:00 committed by GitHub
parent b0d3f49195
commit 7c1b76fce8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 505 additions and 180 deletions

View file

@ -11,7 +11,7 @@
#include "pycore_pyerrors.h" // _PyErr_NoMemory()
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_pythonrun.h" // _Py_SourceAsString()
#include "pycore_sysmodule.h" // _PySys_GetAttr()
#include "pycore_sysmodule.h" // _PySys_GetRequiredAttr()
#include "pycore_tuple.h" // _PyTuple_FromArray()
#include "clinic/bltinmodule.c.h"
@ -457,18 +457,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;
@ -2063,18 +2061,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;
@ -2083,6 +2083,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) {
@ -2092,6 +2093,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;
}
@ -2104,11 +2106,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;
}
}
@ -2120,14 +2124,17 @@ 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) {
if (_PyFile_Flush(file) < 0) {
Py_DECREF(file);
return NULL;
}
}
Py_DECREF(file);
Py_RETURN_NONE;
}
@ -2152,36 +2159,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 */
@ -2200,8 +2212,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) {
@ -2214,7 +2227,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);
}
}
@ -2342,10 +2355,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:
@ -2355,7 +2371,7 @@ builtin_input_impl(PyObject *module, PyObject *prompt)
Py_XDECREF(stdout_errors);
Py_XDECREF(po);
if (tty)
return NULL;
goto error;
PyErr_Clear();
}
@ -2363,12 +2379,22 @@ 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;
}
if (_PyFile_Flush(fout) < 0) {
PyErr_Clear();
}
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;
}