summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMeador Inge <meadori@gmail.com>2012-07-18 19:28:55 (GMT)
committerMeador Inge <meadori@gmail.com>2012-07-18 19:28:55 (GMT)
commit1f336adc8f2107f5788d3176f0c24e96c1080ceb (patch)
treea1ad70dce05a1afa883c69a8bc8fe417d8aa2747
parentc5afd42df886eec6c3008f8de1de21c3413308a8 (diff)
parent2ca6315d151d9a376b46c4ae32ffeaf776da0cbc (diff)
downloadcpython-1f336adc8f2107f5788d3176f0c24e96c1080ceb.zip
cpython-1f336adc8f2107f5788d3176f0c24e96c1080ceb.tar.gz
cpython-1f336adc8f2107f5788d3176f0c24e96c1080ceb.tar.bz2
Issue #15368: make bytecode generation deterministic.
-rw-r--r--Misc/NEWS3
-rw-r--r--Python/compile.c24
2 files changed, 25 insertions, 2 deletions
diff --git a/Misc/NEWS b/Misc/NEWS
index 1f11b4a..62a9445 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,6 +10,9 @@ What's New in Python 3.3.0 Beta 2?
Core and Builtins
-----------------
+- Issue #15368: An issue that caused bytecode generation to be
+ non-deterministic has been fixed.
+
- Issue #15202: Consistently use the name "follow_symlinks" for
new parameters in os and shutil functions.
diff --git a/Python/compile.c b/Python/compile.c
index 2a1b754..12ab46b 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -397,16 +397,33 @@ 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++) {
/* XXX this should probably be a macro in symtable.h */
long vi;
+ k = PyList_GET_ITEM(sorted_keys, key_i);
+ v = PyDict_GetItem(src, k);
assert(PyLong_Check(v));
vi = PyLong_AS_LONG(v);
scope = (vi >> SCOPE_OFFSET) & SCOPE_MASK;
@@ -414,12 +431,14 @@ dictbytype(PyObject *src, int scope_type, int flag, int offset)
if (scope == scope_type || vi & flag) {
PyObject *tuple, *item = PyLong_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);
@@ -429,6 +448,7 @@ dictbytype(PyObject *src, int scope_type, int flag, int offset)
Py_DECREF(tuple);
}
}
+ Py_DECREF(sorted_keys);
return dest;
}