aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Objects/genobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/genobject.c')
-rw-r--r--Objects/genobject.c71
1 files changed, 44 insertions, 27 deletions
diff --git a/Objects/genobject.c b/Objects/genobject.c
index 98b2c5004df..3e7d6257006 100644
--- a/Objects/genobject.c
+++ b/Objects/genobject.c
@@ -17,6 +17,7 @@
#include "pycore_pyerrors.h" // _PyErr_ClearExcState()
#include "pycore_pystate.h" // _PyThreadState_GET()
#include "pycore_warnings.h" // _PyErr_WarnUnawaitedCoroutine()
+#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()
#include "opcode_ids.h" // RESUME, etc
@@ -161,8 +162,7 @@ gen_dealloc(PyObject *self)
_PyObject_GC_UNTRACK(gen);
- if (gen->gi_weakreflist != NULL)
- PyObject_ClearWeakRefs(self);
+ FT_CLEAR_WEAKREFS(self, gen->gi_weakreflist);
_PyObject_GC_TRACK(self);
@@ -704,7 +704,8 @@ static PyObject *
gen_get_name(PyObject *self, void *Py_UNUSED(ignored))
{
PyGenObject *op = _PyGen_CAST(self);
- return Py_NewRef(op->gi_name);
+ PyObject *name = FT_ATOMIC_LOAD_PTR_ACQUIRE(op->gi_name);
+ return Py_NewRef(name);
}
static int
@@ -718,7 +719,11 @@ gen_set_name(PyObject *self, PyObject *value, void *Py_UNUSED(ignored))
"__name__ must be set to a string object");
return -1;
}
- Py_XSETREF(op->gi_name, Py_NewRef(value));
+ Py_BEGIN_CRITICAL_SECTION(self);
+ // gh-133931: To prevent use-after-free from other threads that reference
+ // the gi_name.
+ _PyObject_XSetRefDelayed(&op->gi_name, Py_NewRef(value));
+ Py_END_CRITICAL_SECTION();
return 0;
}
@@ -726,7 +731,8 @@ static PyObject *
gen_get_qualname(PyObject *self, void *Py_UNUSED(ignored))
{
PyGenObject *op = _PyGen_CAST(self);
- return Py_NewRef(op->gi_qualname);
+ PyObject *qualname = FT_ATOMIC_LOAD_PTR_ACQUIRE(op->gi_qualname);
+ return Py_NewRef(qualname);
}
static int
@@ -740,7 +746,11 @@ gen_set_qualname(PyObject *self, PyObject *value, void *Py_UNUSED(ignored))
"__qualname__ must be set to a string object");
return -1;
}
- Py_XSETREF(op->gi_qualname, Py_NewRef(value));
+ Py_BEGIN_CRITICAL_SECTION(self);
+ // gh-133931: To prevent use-after-free from other threads that reference
+ // the gi_qualname.
+ _PyObject_XSetRefDelayed(&op->gi_qualname, Py_NewRef(value));
+ Py_END_CRITICAL_SECTION();
return 0;
}
@@ -1451,7 +1461,9 @@ typedef struct PyAsyncGenAThrow {
/* Can be NULL, when in the "aclose()" mode
(equivalent of "athrow(GeneratorExit)") */
- PyObject *agt_args;
+ PyObject *agt_typ;
+ PyObject *agt_tb;
+ PyObject *agt_val;
AwaitableState agt_state;
} PyAsyncGenAThrow;
@@ -2078,7 +2090,9 @@ async_gen_athrow_dealloc(PyObject *self)
_PyObject_GC_UNTRACK(self);
Py_CLEAR(agt->agt_gen);
- Py_CLEAR(agt->agt_args);
+ Py_XDECREF(agt->agt_typ);
+ Py_XDECREF(agt->agt_tb);
+ Py_XDECREF(agt->agt_val);
PyObject_GC_Del(self);
}
@@ -2088,7 +2102,9 @@ async_gen_athrow_traverse(PyObject *self, visitproc visit, void *arg)
{
PyAsyncGenAThrow *agt = _PyAsyncGenAThrow_CAST(self);
Py_VISIT(agt->agt_gen);
- Py_VISIT(agt->agt_args);
+ Py_VISIT(agt->agt_typ);
+ Py_VISIT(agt->agt_tb);
+ Py_VISIT(agt->agt_val);
return 0;
}
@@ -2116,7 +2132,7 @@ async_gen_athrow_send(PyObject *self, PyObject *arg)
if (o->agt_state == AWAITABLE_STATE_INIT) {
if (o->agt_gen->ag_running_async) {
o->agt_state = AWAITABLE_STATE_CLOSED;
- if (o->agt_args == NULL) {
+ if (o->agt_typ == NULL) {
PyErr_SetString(
PyExc_RuntimeError,
"aclose(): asynchronous generator is already running");
@@ -2143,7 +2159,7 @@ async_gen_athrow_send(PyObject *self, PyObject *arg)
o->agt_state = AWAITABLE_STATE_ITER;
o->agt_gen->ag_running_async = 1;
- if (o->agt_args == NULL) {
+ if (o->agt_typ == NULL) {
/* aclose() mode */
o->agt_gen->ag_closed = 1;
@@ -2157,19 +2173,10 @@ async_gen_athrow_send(PyObject *self, PyObject *arg)
goto yield_close;
}
} else {
- PyObject *typ;
- PyObject *tb = NULL;
- PyObject *val = NULL;
-
- if (!PyArg_UnpackTuple(o->agt_args, "athrow", 1, 3,
- &typ, &val, &tb)) {
- return NULL;
- }
-
retval = _gen_throw((PyGenObject *)gen,
0, /* Do not close generator when
PyExc_GeneratorExit is passed */
- typ, val, tb);
+ o->agt_typ, o->agt_val, o->agt_tb);
retval = async_gen_unwrap_value(o->agt_gen, retval);
}
if (retval == NULL) {
@@ -2181,7 +2188,7 @@ async_gen_athrow_send(PyObject *self, PyObject *arg)
assert(o->agt_state == AWAITABLE_STATE_ITER);
retval = gen_send((PyObject *)gen, arg);
- if (o->agt_args) {
+ if (o->agt_typ) {
return async_gen_unwrap_value(o->agt_gen, retval);
} else {
/* aclose() mode */
@@ -2212,7 +2219,7 @@ check_error:
if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration) ||
PyErr_ExceptionMatches(PyExc_GeneratorExit))
{
- if (o->agt_args == NULL) {
+ if (o->agt_typ == NULL) {
/* when aclose() is called we don't want to propagate
StopAsyncIteration or GeneratorExit; just raise
StopIteration, signalling that this 'aclose()' await
@@ -2241,7 +2248,7 @@ async_gen_athrow_throw(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
if (o->agt_state == AWAITABLE_STATE_INIT) {
if (o->agt_gen->ag_running_async) {
o->agt_state = AWAITABLE_STATE_CLOSED;
- if (o->agt_args == NULL) {
+ if (o->agt_typ == NULL) {
PyErr_SetString(
PyExc_RuntimeError,
"aclose(): asynchronous generator is already running");
@@ -2259,7 +2266,7 @@ async_gen_athrow_throw(PyObject *self, PyObject *const *args, Py_ssize_t nargs)
}
PyObject *retval = gen_throw((PyObject*)o->agt_gen, args, nargs);
- if (o->agt_args) {
+ if (o->agt_typ) {
retval = async_gen_unwrap_value(o->agt_gen, retval);
if (retval == NULL) {
o->agt_gen->ag_running_async = 0;
@@ -2334,7 +2341,7 @@ async_gen_athrow_finalize(PyObject *op)
{
PyAsyncGenAThrow *o = (PyAsyncGenAThrow*)op;
if (o->agt_state == AWAITABLE_STATE_INIT) {
- PyObject *method = o->agt_args ? &_Py_ID(athrow) : &_Py_ID(aclose);
+ PyObject *method = o->agt_typ ? &_Py_ID(athrow) : &_Py_ID(aclose);
_PyErr_WarnUnawaitedAgenMethod(o->agt_gen, method);
}
}
@@ -2403,13 +2410,23 @@ PyTypeObject _PyAsyncGenAThrow_Type = {
static PyObject *
async_gen_athrow_new(PyAsyncGenObject *gen, PyObject *args)
{
+ PyObject *typ = NULL;
+ PyObject *tb = NULL;
+ PyObject *val = NULL;
+ if (args && !PyArg_UnpackTuple(args, "athrow", 1, 3, &typ, &val, &tb)) {
+ return NULL;
+ }
+
PyAsyncGenAThrow *o;
o = PyObject_GC_New(PyAsyncGenAThrow, &_PyAsyncGenAThrow_Type);
if (o == NULL) {
return NULL;
}
o->agt_gen = (PyAsyncGenObject*)Py_NewRef(gen);
- o->agt_args = Py_XNewRef(args);
+ o->agt_typ = Py_XNewRef(typ);
+ o->agt_tb = Py_XNewRef(tb);
+ o->agt_val = Py_XNewRef(val);
+
o->agt_state = AWAITABLE_STATE_INIT;
_PyObject_GC_TRACK((PyObject*)o);
return (PyObject*)o;