Skip to content

Commit

Permalink
Fix race in constructing dict for instance
Browse files Browse the repository at this point in the history
  • Loading branch information
DinoV committed May 2, 2024
1 parent a37b093 commit 12d0685
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 24 deletions.
2 changes: 1 addition & 1 deletion Include/internal/pycore_dict.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ PyAPI_FUNC(PyObject *)_PyDict_LoadGlobal(PyDictObject *, PyDictObject *, PyObjec

/* Consumes references to key and value */
PyAPI_FUNC(int) _PyDict_SetItem_Take2(PyDictObject *op, PyObject *key, PyObject *value);
extern int _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr, PyObject *name, PyObject *value);
extern int _PyObjectDict_SetItem(PyTypeObject *tp, PyObject *obj, PyObject **dictptr, PyObject *name, PyObject *value);

extern int _PyDict_Pop_KnownHash(
PyDictObject *dict,
Expand Down
43 changes: 21 additions & 22 deletions Objects/dictobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -7213,7 +7213,7 @@ PyObject_GenericGetDict(PyObject *obj, void *context)
}

int
_PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr,
_PyObjectDict_SetItem(PyTypeObject *tp, PyObject *obj, PyObject **dictptr,
PyObject *key, PyObject *value)
{
PyObject *dict;
Expand All @@ -7222,37 +7222,36 @@ _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr,
PyInterpreterState *interp = _PyInterpreterState_GET();

assert(dictptr != NULL);
if ((tp->tp_flags & Py_TPFLAGS_HEAPTYPE) && (cached = CACHED_KEYS(tp))) {
assert(dictptr != NULL);
dict = *dictptr;
if (dict == NULL) {
#ifdef Py_GIL_DISABLED
Py_BEGIN_CRITICAL_SECTION(obj);
dict = *dictptr;
if (dict == NULL) {
if (dict != NULL) {
goto done;
}
#endif
if ((tp->tp_flags & Py_TPFLAGS_HEAPTYPE) && (cached = CACHED_KEYS(tp))) {
assert(!_PyType_HasFeature(tp, Py_TPFLAGS_INLINE_VALUES));
dictkeys_incref(cached);
dict = new_dict_with_shared_keys(interp, cached);
if (dict == NULL)
return -1;
*dictptr = dict;
}
if (value == NULL) {
res = PyDict_DelItem(dict, key);
}
else {
res = PyDict_SetItem(dict, key, value);
}
} else {
dict = *dictptr;
if (dict == NULL) {
dict = PyDict_New();
if (dict == NULL)
return -1;
*dictptr = dict;
}
if (value == NULL) {
res = PyDict_DelItem(dict, key);
} else {
res = PyDict_SetItem(dict, key, value);
*dictptr = dict;
#ifdef Py_GIL_DISABLED
done:
Py_END_CRITICAL_SECTION();
#endif
if (dict == NULL) {
return -1;
}
}

Py_BEGIN_CRITICAL_SECTION(dict);
res = set_or_del_lock_held((PyDictObject *)dict, key, value);
Py_END_CRITICAL_SECTION();
ASSERT_CONSISTENT(dict);
return res;
}
Expand Down
2 changes: 1 addition & 1 deletion Objects/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -1732,7 +1732,7 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name,
goto done;
}
else {
res = _PyObjectDict_SetItem(tp, dictptr, name, value);
res = _PyObjectDict_SetItem(tp, obj, dictptr, name, value);
}
}
else {
Expand Down

0 comments on commit 12d0685

Please sign in to comment.