diff options
author | Meador Inge <meadori@gmail.com> | 2012-07-18 19:28:55 (GMT) |
---|---|---|
committer | Meador Inge <meadori@gmail.com> | 2012-07-18 19:28:55 (GMT) |
commit | 1f336adc8f2107f5788d3176f0c24e96c1080ceb (patch) | |
tree | a1ad70dce05a1afa883c69a8bc8fe417d8aa2747 | |
parent | c5afd42df886eec6c3008f8de1de21c3413308a8 (diff) | |
parent | 2ca6315d151d9a376b46c4ae32ffeaf776da0cbc (diff) | |
download | cpython-1f336adc8f2107f5788d3176f0c24e96c1080ceb.zip cpython-1f336adc8f2107f5788d3176f0c24e96c1080ceb.tar.gz cpython-1f336adc8f2107f5788d3176f0c24e96c1080ceb.tar.bz2 |
Issue #15368: make bytecode generation deterministic.
-rw-r--r-- | Misc/NEWS | 3 | ||||
-rw-r--r-- | Python/compile.c | 24 |
2 files changed, 25 insertions, 2 deletions
@@ -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; } |