Skip to content

Commit ae6d925

Browse files
committed
Fix race in constructing dict for instance
1 parent a37b093 commit ae6d925

File tree

3 files changed

+26
-24
lines changed

3 files changed

+26
-24
lines changed

Include/internal/pycore_dict.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ PyAPI_FUNC(PyObject *)_PyDict_LoadGlobal(PyDictObject *, PyDictObject *, PyObjec
105105

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

110110
extern int _PyDict_Pop_KnownHash(
111111
PyDictObject *dict,

Objects/dictobject.c

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7213,7 +7213,7 @@ PyObject_GenericGetDict(PyObject *obj, void *context)
72137213
}
72147214

72157215
int
7216-
_PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr,
7216+
_PyObjectDict_SetItem(PyTypeObject *tp, PyObject *obj, PyObject **dictptr,
72177217
PyObject *key, PyObject *value)
72187218
{
72197219
PyObject *dict;
@@ -7222,37 +7222,39 @@ _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr,
72227222
PyInterpreterState *interp = _PyInterpreterState_GET();
72237223

72247224
assert(dictptr != NULL);
7225-
if ((tp->tp_flags & Py_TPFLAGS_HEAPTYPE) && (cached = CACHED_KEYS(tp))) {
7226-
assert(dictptr != NULL);
7225+
dict = *dictptr;
7226+
if (dict == NULL) {
7227+
#ifdef Py_GIL_DISABLED
7228+
Py_BEGIN_CRITICAL_SECTION(obj);
72277229
dict = *dictptr;
7228-
if (dict == NULL) {
7230+
if (dict != NULL) {
7231+
goto done;
7232+
}
7233+
#endif
7234+
if ((tp->tp_flags & Py_TPFLAGS_HEAPTYPE) && (cached = CACHED_KEYS(tp))) {
72297235
assert(!_PyType_HasFeature(tp, Py_TPFLAGS_INLINE_VALUES));
72307236
dictkeys_incref(cached);
72317237
dict = new_dict_with_shared_keys(interp, cached);
7232-
if (dict == NULL)
7233-
return -1;
7234-
*dictptr = dict;
7235-
}
7236-
if (value == NULL) {
7237-
res = PyDict_DelItem(dict, key);
7238+
if (dict == NULL) {
7239+
dictkeys_decref(interp, cached, false);
7240+
}
72387241
}
72397242
else {
7240-
res = PyDict_SetItem(dict, key, value);
7241-
}
7242-
} else {
7243-
dict = *dictptr;
7244-
if (dict == NULL) {
72457243
dict = PyDict_New();
7246-
if (dict == NULL)
7247-
return -1;
7248-
*dictptr = dict;
72497244
}
7250-
if (value == NULL) {
7251-
res = PyDict_DelItem(dict, key);
7252-
} else {
7253-
res = PyDict_SetItem(dict, key, value);
7245+
*dictptr = dict;
7246+
#ifdef Py_GIL_DISABLED
7247+
done:
7248+
Py_END_CRITICAL_SECTION();
7249+
#endif
7250+
if (dict == NULL) {
7251+
return -1;
72547252
}
72557253
}
7254+
7255+
Py_BEGIN_CRITICAL_SECTION(dict);
7256+
res = set_or_del_lock_held((PyDictObject *)dict, key, value);
7257+
Py_END_CRITICAL_SECTION();
72567258
ASSERT_CONSISTENT(dict);
72577259
return res;
72587260
}

Objects/object.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1732,7 +1732,7 @@ _PyObject_GenericSetAttrWithDict(PyObject *obj, PyObject *name,
17321732
goto done;
17331733
}
17341734
else {
1735-
res = _PyObjectDict_SetItem(tp, dictptr, name, value);
1735+
res = _PyObjectDict_SetItem(tp, obj, dictptr, name, value);
17361736
}
17371737
}
17381738
else {

0 commit comments

Comments
 (0)