]> granicus.if.org Git - python/commitdiff
bpo-29438: fixed use-after-free in key sharing dict (#17)
authorINADA Naoki <methane@users.noreply.github.com>
Sun, 12 Feb 2017 04:51:30 +0000 (13:51 +0900)
committerGitHub <noreply@github.com>
Sun, 12 Feb 2017 04:51:30 +0000 (13:51 +0900)
Misc/NEWS
Objects/dictobject.c

index 48d786d8f7b50573b73c8bb6dd3e4b74fd90d729..eb870b7d48b76b685b0824991b42ef9d17ffec22 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,8 @@ What's New in Python 3.7.0 alpha 1?
 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 43584b7bb2444b1b880e60b74a8fa93f4f303594..5fe5272b1a3fd6efe02aad2dd190a711c9fde43a 100644 (file)
@@ -4352,15 +4352,19 @@ _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr,
         }
         if (value == NULL) {
             res = PyDict_DelItem(dict, key);
-            if (cached != ((PyDictObject *)dict)->ma_keys) {
+            // Since key sharing dict doesn't allow deletion, PyDict_DelItem()
+            // always converts dict to combined form.
+            if ((cached = CACHED_KEYS(tp)) != NULL) {
                 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);
-            if (was_shared && cached != ((PyDictObject *)dict)->ma_keys) {
+            if (was_shared &&
+                    (cached = CACHED_KEYS(tp)) != NULL &&
+                    cached != ((PyDictObject *)dict)->ma_keys) {
                 /* 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