diff --git a/Misc/NEWS b/Misc/NEWS index e1b32add0ef3ca..6a1abf174c35a5 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,8 @@ Release date: XXXX-XX-XX Core and Builtins ----------------- +- bpo-29438: Fixed use-after-free problem in key sharing dict. + - Issue #29319: Prevent RunMainFromImporter overwriting sys.path[0]. - Issue #29337: Fixed possible BytesWarning when compare the code objects. diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 11c086ffb47ae0..7299f36b2bf88c 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -3893,20 +3893,18 @@ _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr, } if (value == NULL) { res = PyDict_DelItem(dict, key); - if (cached != ((PyDictObject *)dict)->ma_keys) { - CACHED_KEYS(tp) = NULL; - DK_DECREF(cached); - } } else { - int was_shared = cached == ((PyDictObject *)dict)->ma_keys; + int was_shared = (cached == ((PyDictObject *)dict)->ma_keys); res = PyDict_SetItem(dict, key, value); /* PyDict_SetItem() may call dictresize() and convert split table * into combined table. In such case, convert it to split * table again and update type's shared key only when this is * the only dict sharing key with the type. */ - if (was_shared && cached != ((PyDictObject *)dict)->ma_keys) { + if (was_shared && + (cached = CACHED_KEYS(tp)) != NULL && + cached != ((PyDictObject *)dict)->ma_keys) { if (cached->dk_refcnt == 1) { CACHED_KEYS(tp) = make_keys_shared(dict); } else {
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: