]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Issue #15368: make bytecode generation deterministic.
authorMeador Inge <meadori@gmail.com>
Wed, 18 Jul 2012 19:09:04 +0000 (14:09 -0500)
committerMeador Inge <meadori@gmail.com>
Wed, 18 Jul 2012 19:09:04 +0000 (14:09 -0500)
Misc/NEWS
Python/compile.c

index 4b05aa36dcc5671602ac7092a1992657272724a6..6a2abb5d56ce54997d8274631c5d12abded6ff84 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -1,4 +1,4 @@
-Python News
+,Python News
 +++++++++++
 
 What's New in Python 2.7.4
@@ -9,6 +9,9 @@ What's New in Python 2.7.4
 Core and Builtins
 -----------------
 
+- Issue #15368: An issue that caused bytecode generation to be
+  non-deterministic when using randomized hashing (-R) has been fixed.
+
 - Issue #15033: Fix the exit status bug when modules invoked using -m swith,
   return the proper failure return value (1). Patch contributed by Jeff Knupp.
 
index 119c60f9b23b4dd01c12a846d933e22bf5ed8275..d50344cf614de6bc777ab16e65d8fc8e613d2ba1 100644 (file)
@@ -359,14 +359,31 @@ each key.
 static PyObject *
 dictbytype(PyObject *src, int scope_type, int flag, int offset)
 {
-    Py_ssize_t pos = 0, i = offset, scope;
+    Py_ssize_t pos = 0, i = offset, scope, num_keys, key_i;
     PyObject *k, *v, *dest = PyDict_New();
+    PyObject *sorted_keys;
 
     assert(offset >= 0);
     if (dest == NULL)
         return NULL;
 
-    while (PyDict_Next(src, &pos, &k, &v)) {
+    /* Sort the keys so that we have a deterministic order on the indexes
+       saved in the returned dictionary.  These indexes are used as indexes
+       into the free and cell var storage.  Therefore if they aren't
+       deterministic, then the generated bytecode is not deterministic.
+    */
+    sorted_keys = PyDict_Keys(src);
+    if (sorted_keys == NULL)
+        return NULL;
+    if (PyList_Sort(sorted_keys) != 0) {
+        Py_DECREF(sorted_keys);
+        return NULL;
+    }
+    num_keys = PyList_GET_SIZE(src);
+
+    for (key_i = 0; key_i < num_keys; key_i++) {
+        k = PyList_GET_ITEM(sorted_keys, key_i);
+        v = PyDict_GetItem(src, k);
         /* XXX this should probably be a macro in symtable.h */
         assert(PyInt_Check(v));
         scope = (PyInt_AS_LONG(v) >> SCOPE_OFF) & SCOPE_MASK;
@@ -374,12 +391,14 @@ dictbytype(PyObject *src, int scope_type, int flag, int offset)
         if (scope == scope_type || PyInt_AS_LONG(v) & flag) {
             PyObject *tuple, *item = PyInt_FromLong(i);
             if (item == NULL) {
+                Py_DECREF(sorted_keys);
                 Py_DECREF(dest);
                 return NULL;
             }
             i++;
             tuple = PyTuple_Pack(2, k, k->ob_type);
             if (!tuple || PyDict_SetItem(dest, tuple, item) < 0) {
+                Py_DECREF(sorted_keys);
                 Py_DECREF(item);
                 Py_DECREF(dest);
                 Py_XDECREF(tuple);
@@ -389,6 +408,7 @@ dictbytype(PyObject *src, int scope_type, int flag, int offset)
             Py_DECREF(tuple);
         }
     }
+    Py_DECREF(sorted_keys);
     return dest;
 }