mirror of https://github.com/python/cpython
Issue #15368: make bytecode generation deterministic.
This commit is contained in:
parent
0b350c6b3e
commit
2ca6315d15
|
@ -10,6 +10,9 @@ What's New in Python 3.2.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 #15020: The program name used to search for Python's path is now
|
- Issue #15020: The program name used to search for Python's path is now
|
||||||
"python3" under Unix, not "python".
|
"python3" under Unix, not "python".
|
||||||
|
|
||||||
|
|
|
@ -367,16 +367,33 @@ 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++) {
|
||||||
/* XXX this should probably be a macro in symtable.h */
|
/* XXX this should probably be a macro in symtable.h */
|
||||||
long vi;
|
long vi;
|
||||||
|
k = PyList_GET_ITEM(sorted_keys, key_i);
|
||||||
|
v = PyDict_GetItem(src, k);
|
||||||
assert(PyLong_Check(v));
|
assert(PyLong_Check(v));
|
||||||
vi = PyLong_AS_LONG(v);
|
vi = PyLong_AS_LONG(v);
|
||||||
scope = (vi >> SCOPE_OFFSET) & SCOPE_MASK;
|
scope = (vi >> SCOPE_OFFSET) & SCOPE_MASK;
|
||||||
|
@ -384,12 +401,14 @@ dictbytype(PyObject *src, int scope_type, int flag, int offset)
|
||||||
if (scope == scope_type || vi & flag) {
|
if (scope == scope_type || vi & flag) {
|
||||||
PyObject *tuple, *item = PyLong_FromLong(i);
|
PyObject *tuple, *item = PyLong_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);
|
||||||
|
@ -399,6 +418,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