gh-116664: Ensure thread-safe dict access in _warnings (#116768)

Replace _PyDict_GetItemWithError() with PyDict_GetItemRef().
This commit is contained in:
Erlend E. Aasland 2024-03-18 10:37:48 +01:00 committed by GitHub
parent 4e45c6c54a
commit 762f489b31
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 32 additions and 29 deletions

View File

@ -1,5 +1,4 @@
#include "Python.h" #include "Python.h"
#include "pycore_dict.h" // _PyDict_GetItemWithError()
#include "pycore_interp.h" // PyInterpreterState.warnings #include "pycore_interp.h" // PyInterpreterState.warnings
#include "pycore_long.h" // _PyLong_GetZero() #include "pycore_long.h" // _PyLong_GetZero()
#include "pycore_pyerrors.h" // _PyErr_Occurred() #include "pycore_pyerrors.h" // _PyErr_Occurred()
@ -8,6 +7,8 @@
#include "pycore_sysmodule.h" // _PySys_GetAttr() #include "pycore_sysmodule.h" // _PySys_GetAttr()
#include "pycore_traceback.h" // _Py_DisplaySourceLine() #include "pycore_traceback.h" // _Py_DisplaySourceLine()
#include <stdbool.h>
#include "clinic/_warnings.c.h" #include "clinic/_warnings.c.h"
#define MODULE_NAME "_warnings" #define MODULE_NAME "_warnings"
@ -397,7 +398,7 @@ static int
already_warned(PyInterpreterState *interp, PyObject *registry, PyObject *key, already_warned(PyInterpreterState *interp, PyObject *registry, PyObject *key,
int should_set) int should_set)
{ {
PyObject *version_obj, *already_warned; PyObject *already_warned;
if (key == NULL) if (key == NULL)
return -1; return -1;
@ -406,14 +407,17 @@ already_warned(PyInterpreterState *interp, PyObject *registry, PyObject *key,
if (st == NULL) { if (st == NULL) {
return -1; return -1;
} }
version_obj = _PyDict_GetItemWithError(registry, &_Py_ID(version)); PyObject *version_obj;
if (version_obj == NULL if (PyDict_GetItemRef(registry, &_Py_ID(version), &version_obj) < 0) {
return -1;
}
bool should_update_version = (
version_obj == NULL
|| !PyLong_CheckExact(version_obj) || !PyLong_CheckExact(version_obj)
|| PyLong_AsLong(version_obj) != st->filters_version) || PyLong_AsLong(version_obj) != st->filters_version
{ );
if (PyErr_Occurred()) { Py_XDECREF(version_obj);
return -1; if (should_update_version) {
}
PyDict_Clear(registry); PyDict_Clear(registry);
version_obj = PyLong_FromLong(st->filters_version); version_obj = PyLong_FromLong(st->filters_version);
if (version_obj == NULL) if (version_obj == NULL)
@ -911,13 +915,12 @@ setup_context(Py_ssize_t stack_level,
/* Setup registry. */ /* Setup registry. */
assert(globals != NULL); assert(globals != NULL);
assert(PyDict_Check(globals)); assert(PyDict_Check(globals));
*registry = _PyDict_GetItemWithError(globals, &_Py_ID(__warningregistry__)); int rc = PyDict_GetItemRef(globals, &_Py_ID(__warningregistry__),
registry);
if (rc < 0) {
goto handle_error;
}
if (*registry == NULL) { if (*registry == NULL) {
int rc;
if (_PyErr_Occurred(tstate)) {
goto handle_error;
}
*registry = PyDict_New(); *registry = PyDict_New();
if (*registry == NULL) if (*registry == NULL)
goto handle_error; goto handle_error;
@ -926,21 +929,21 @@ setup_context(Py_ssize_t stack_level,
if (rc < 0) if (rc < 0)
goto handle_error; goto handle_error;
} }
else
Py_INCREF(*registry);
/* Setup module. */ /* Setup module. */
*module = _PyDict_GetItemWithError(globals, &_Py_ID(__name__)); rc = PyDict_GetItemRef(globals, &_Py_ID(__name__), module);
if (*module == Py_None || (*module != NULL && PyUnicode_Check(*module))) { if (rc < 0) {
Py_INCREF(*module);
}
else if (_PyErr_Occurred(tstate)) {
goto handle_error; goto handle_error;
} }
else { if (rc > 0) {
*module = PyUnicode_FromString("<string>"); if (Py_IsNone(*module) || PyUnicode_Check(*module)) {
if (*module == NULL) return 1;
goto handle_error; }
Py_DECREF(*module);
}
*module = PyUnicode_FromString("<string>");
if (*module == NULL) {
goto handle_error;
} }
return 1; return 1;
@ -1063,12 +1066,12 @@ get_source_line(PyInterpreterState *interp, PyObject *module_globals, int lineno
return NULL; return NULL;
} }
module_name = _PyDict_GetItemWithError(module_globals, &_Py_ID(__name__)); int rc = PyDict_GetItemRef(module_globals, &_Py_ID(__name__),
if (!module_name) { &module_name);
if (rc < 0 || rc == 0) {
Py_DECREF(loader); Py_DECREF(loader);
return NULL; return NULL;
} }
Py_INCREF(module_name);
/* Make sure the loader implements the optional get_source() method. */ /* Make sure the loader implements the optional get_source() method. */
(void)PyObject_GetOptionalAttr(loader, &_Py_ID(get_source), &get_source); (void)PyObject_GetOptionalAttr(loader, &_Py_ID(get_source), &get_source);