Issue #15368: make bytecode generation deterministic.
This commit is contained in:
parent
fc095202af
commit
6642d1f97d
|
@ -1,4 +1,4 @@
|
||||||
Python News
|
,Python News
|
||||||
+++++++++++
|
+++++++++++
|
||||||
|
|
||||||
What's New in Python 2.7.4
|
What's New in Python 2.7.4
|
||||||
|
@ -9,6 +9,9 @@ What's New in Python 2.7.4
|
||||||
Core and Builtins
|
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,
|
- 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.
|
return the proper failure return value (1). Patch contributed by Jeff Knupp.
|
||||||
|
|
||||||
|
|
|
@ -359,14 +359,31 @@ each key.
|
||||||
static PyObject *
|
static PyObject *
|
||||||
dictbytype(PyObject *src, int scope_type, int flag, int offset)
|
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 *k, *v, *dest = PyDict_New();
|
||||||
|
PyObject *sorted_keys;
|
||||||
|
|
||||||
assert(offset >= 0);
|
assert(offset >= 0);
|
||||||
if (dest == NULL)
|
if (dest == NULL)
|
||||||
return 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 */
|
/* XXX this should probably be a macro in symtable.h */
|
||||||
assert(PyInt_Check(v));
|
assert(PyInt_Check(v));
|
||||||
scope = (PyInt_AS_LONG(v) >> SCOPE_OFF) & SCOPE_MASK;
|
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) {
|
if (scope == scope_type || PyInt_AS_LONG(v) & flag) {
|
||||||
PyObject *tuple, *item = PyInt_FromLong(i);
|
PyObject *tuple, *item = PyInt_FromLong(i);
|
||||||
if (item == NULL) {
|
if (item == NULL) {
|
||||||
|
Py_DECREF(sorted_keys);
|
||||||
Py_DECREF(dest);
|
Py_DECREF(dest);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
tuple = PyTuple_Pack(2, k, k->ob_type);
|
tuple = PyTuple_Pack(2, k, k->ob_type);
|
||||||
if (!tuple || PyDict_SetItem(dest, tuple, item) < 0) {
|
if (!tuple || PyDict_SetItem(dest, tuple, item) < 0) {
|
||||||
|
Py_DECREF(sorted_keys);
|
||||||
Py_DECREF(item);
|
Py_DECREF(item);
|
||||||
Py_DECREF(dest);
|
Py_DECREF(dest);
|
||||||
Py_XDECREF(tuple);
|
Py_XDECREF(tuple);
|
||||||
|
@ -389,6 +408,7 @@ dictbytype(PyObject *src, int scope_type, int flag, int offset)
|
||||||
Py_DECREF(tuple);
|
Py_DECREF(tuple);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Py_DECREF(sorted_keys);
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue