mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
[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 commit0ef4ffeefd
) (cherry picked from commit7c1b76fce8
) (cherry picked from commit2ab7e1135a
)
This commit is contained in:
parent
6a268a046f
commit
89a79fc919
21 changed files with 506 additions and 162 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue