mirror of https://github.com/python/cpython
gh-123657: Fix crash and refleak in `decimal.getcontext()` (GH-123703)
This commit is contained in:
parent
8311b11800
commit
853588e24c
|
@ -0,0 +1,2 @@
|
||||||
|
Fix crash and memory leak in :func:`decimal.getcontext`. It crashed when using
|
||||||
|
a thread-local context by ``--with-decimal-contextvar=no``.
|
|
@ -76,8 +76,9 @@ typedef struct {
|
||||||
#ifndef WITH_DECIMAL_CONTEXTVAR
|
#ifndef WITH_DECIMAL_CONTEXTVAR
|
||||||
/* Key for thread state dictionary */
|
/* Key for thread state dictionary */
|
||||||
PyObject *tls_context_key;
|
PyObject *tls_context_key;
|
||||||
/* Invariant: NULL or the most recently accessed thread local context */
|
/* Invariant: NULL or a strong reference to the most recently accessed
|
||||||
struct PyDecContextObject *cached_context;
|
thread local context. */
|
||||||
|
struct PyDecContextObject *cached_context; /* Not borrowed */
|
||||||
#else
|
#else
|
||||||
PyObject *current_context_var;
|
PyObject *current_context_var;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1419,12 +1420,6 @@ context_dealloc(PyDecContextObject *self)
|
||||||
{
|
{
|
||||||
PyTypeObject *tp = Py_TYPE(self);
|
PyTypeObject *tp = Py_TYPE(self);
|
||||||
PyObject_GC_UnTrack(self);
|
PyObject_GC_UnTrack(self);
|
||||||
#ifndef WITH_DECIMAL_CONTEXTVAR
|
|
||||||
decimal_state *state = get_module_state_by_def(Py_TYPE(self));
|
|
||||||
if (self == state->cached_context) {
|
|
||||||
state->cached_context = NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
(void)context_clear(self);
|
(void)context_clear(self);
|
||||||
tp->tp_free(self);
|
tp->tp_free(self);
|
||||||
Py_DECREF(tp);
|
Py_DECREF(tp);
|
||||||
|
@ -1701,7 +1696,8 @@ current_context_from_dict(decimal_state *modstate)
|
||||||
|
|
||||||
/* Cache the context of the current thread, assuming that it
|
/* Cache the context of the current thread, assuming that it
|
||||||
* will be accessed several times before a thread switch. */
|
* will be accessed several times before a thread switch. */
|
||||||
modstate->cached_context = (PyDecContextObject *)tl_context;
|
Py_XSETREF(modstate->cached_context,
|
||||||
|
(PyDecContextObject *)Py_NewRef(tl_context));
|
||||||
modstate->cached_context->tstate = tstate;
|
modstate->cached_context->tstate = tstate;
|
||||||
|
|
||||||
/* Borrowed reference with refcount==1 */
|
/* Borrowed reference with refcount==1 */
|
||||||
|
@ -1769,7 +1765,7 @@ PyDec_SetCurrentContext(PyObject *self, PyObject *v)
|
||||||
Py_INCREF(v);
|
Py_INCREF(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
state->cached_context = NULL;
|
Py_CLEAR(state->cached_context);
|
||||||
if (PyDict_SetItem(dict, state->tls_context_key, v) < 0) {
|
if (PyDict_SetItem(dict, state->tls_context_key, v) < 0) {
|
||||||
Py_DECREF(v);
|
Py_DECREF(v);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -6122,6 +6118,16 @@ decimal_traverse(PyObject *module, visitproc visit, void *arg)
|
||||||
Py_VISIT(state->Rational);
|
Py_VISIT(state->Rational);
|
||||||
Py_VISIT(state->SignalTuple);
|
Py_VISIT(state->SignalTuple);
|
||||||
|
|
||||||
|
if (state->signal_map != NULL) {
|
||||||
|
for (DecCondMap *cm = state->signal_map; cm->name != NULL; cm++) {
|
||||||
|
Py_VISIT(cm->ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (state->cond_map != NULL) {
|
||||||
|
for (DecCondMap *cm = state->cond_map + 1; cm->name != NULL; cm++) {
|
||||||
|
Py_VISIT(cm->ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue