Skip to content

Commit 12d7f7c

Browse files
committed
Attempt more careful fix of use-after-free
1 parent 8c92ca6 commit 12d7f7c

File tree

1 file changed

+16
-7
lines changed

1 file changed

+16
-7
lines changed

Objects/dictobject.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7117,6 +7117,7 @@ _PyObject_SetManagedDict(PyObject *obj, PyObject *new_dict)
71177117
// since we locked it.
71187118
dict = _PyObject_ManagedDictPointer(obj)->dict;
71197119
err = _PyDict_DetachFromObject(dict, obj);
7120+
assert(err == 0 || new_dict == NULL);
71207121
if (err == 0) {
71217122
FT_ATOMIC_STORE_PTR(_PyObject_ManagedDictPointer(obj)->dict,
71227123
(PyDictObject *)Py_XNewRef(new_dict));
@@ -7149,7 +7150,21 @@ void
71497150
PyObject_ClearManagedDict(PyObject *obj)
71507151
{
71517152
if (_PyObject_SetManagedDict(obj, NULL) < 0) {
7153+
/* Must be out of memory */
7154+
assert(PyErr_Occurred() == PyExc_MemoryError);
71527155
PyErr_WriteUnraisable(NULL);
7156+
/* Clear the dict */
7157+
PyDictObject *dict = _PyObject_GetManagedDict(obj);
7158+
Py_BEGIN_CRITICAL_SECTION2(dict, obj);
7159+
dict = _PyObject_ManagedDictPointer(obj)->dict;
7160+
PyInterpreterState *interp = _PyInterpreterState_GET();
7161+
PyDictKeysObject *oldkeys = dict->ma_keys;
7162+
set_keys(dict, Py_EMPTY_KEYS);
7163+
dict->ma_values = NULL;
7164+
dictkeys_decref(interp, oldkeys, IS_DICT_SHARED(mp));
7165+
STORE_USED(dict, 0);
7166+
set_dict_inline_values(obj, NULL);
7167+
Py_END_CRITICAL_SECTION2();
71537168
}
71547169
}
71557170

@@ -7173,17 +7188,11 @@ _PyDict_DetachFromObject(PyDictObject *mp, PyObject *obj)
71737188

71747189
PyDictValues *values = copy_values(mp->ma_values);
71757190

7176-
mp->ma_values = values;
71777191
if (values == NULL) {
7178-
/* Out of memory. Clear the dict */
7179-
PyInterpreterState *interp = _PyInterpreterState_GET();
7180-
PyDictKeysObject *oldkeys = mp->ma_keys;
7181-
set_keys(mp, Py_EMPTY_KEYS);
7182-
dictkeys_decref(interp, oldkeys, IS_DICT_SHARED(mp));
7183-
STORE_USED(mp, 0);
71847192
PyErr_NoMemory();
71857193
return -1;
71867194
}
7195+
mp->ma_values = values;
71877196

71887197
FT_ATOMIC_STORE_UINT8(_PyObject_InlineValues(obj)->valid, 0);
71897198

0 commit comments

Comments
 (0)