-
-
Notifications
You must be signed in to change notification settings - Fork 32.1k
gh-132617: Fix dict.update()
mutation check
#134815
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Use `ma_used` instead of `ma_keys->dk_nentries` for modification check so that we only check if the dictionary is modified, not if new keys are added to a different dictionary that shared the same keys object.
dict.update()
mutation checkdict.update()
mutation check
@@ -3858,7 +3858,7 @@ dict_dict_merge(PyInterpreterState *interp, PyDictObject *mp, PyDictObject *othe | |||
} | |||
} | |||
|
|||
Py_ssize_t orig_size = other->ma_keys->dk_nentries; | |||
Py_ssize_t orig_size = other->ma_used; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ma_used is too weak. It cannot detect del d["a"]; d["b"] = None
.
For better check:
- For all table, check
other->ma_keys
is not changed. - For combined table, check
other->ma_keys->dk_nentries
is not changed. - For split table, check
other->ma_values->size
is not changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's the same condition we use in iterators and elsewhere. I don't think we should strengthen any of the checks. These are heuristic checks, they're not going to be perfect, but if we decide to do so, I think we should do that in a subsequent PR and not backport that change.
Lines 5169 to 5174 in 469a564
if (di->di_used != d->ma_used) { | |
PyErr_SetString(PyExc_RuntimeError, | |
"dictionary changed size during iteration"); | |
di->di_used = -1; /* Make this state sticky */ | |
return NULL; | |
} |
Use
ma_used
instead ofma_keys->dk_nentries
for modification check so that we only check if the dictionary is modified, not if new keys are added to a different dictionary that shared the same keys object.dict.update()
mutation check too broad #132617