]> granicus.if.org Git - python/commitdiff
bpo-29438: Fixed use-after-free in key sharing dict (#40)
authorINADA Naoki <methane@users.noreply.github.com>
Mon, 13 Feb 2017 00:16:20 +0000 (09:16 +0900)
committerGitHub <noreply@github.com>
Mon, 13 Feb 2017 00:16:20 +0000 (09:16 +0900)
Misc/NEWS
Objects/dictobject.c

index e1b32add0ef3ca829253b38d0db2ab07a4145ab0..6a1abf174c35a516d408e438319c59c53fabca0c 100644 (file)
--- 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.
index 11c086ffb47ae0e4652aefc8d292d4d98fed0401..7299f36b2bf88cdd4e631fcc7a6bbb5857ebe3a3 100644 (file)
@@ -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 {