Skip to content

Commit 6642d1f

Browse files
committed
Issue #15368: make bytecode generation deterministic.
1 parent fc09520 commit 6642d1f

File tree

2 files changed

+26
-3
lines changed

2 files changed

+26
-3
lines changed

Misc/NEWS

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Python News
1+
,Python News
22
+++++++++++
33

44
What's New in Python 2.7.4
@@ -9,6 +9,9 @@ What's New in Python 2.7.4
99
Core and Builtins
1010
-----------------
1111

12+
- Issue #15368: An issue that caused bytecode generation to be
13+
non-deterministic when using randomized hashing (-R) has been fixed.
14+
1215
- Issue #15033: Fix the exit status bug when modules invoked using -m swith,
1316
return the proper failure return value (1). Patch contributed by Jeff Knupp.
1417

Python/compile.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -359,27 +359,46 @@ each key.
359359
static PyObject *
360360
dictbytype(PyObject *src, int scope_type, int flag, int offset)
361361
{
362-
Py_ssize_t pos = 0, i = offset, scope;
362+
Py_ssize_t pos = 0, i = offset, scope, num_keys, key_i;
363363
PyObject *k, *v, *dest = PyDict_New();
364+
PyObject *sorted_keys;
364365

365366
assert(offset >= 0);
366367
if (dest == NULL)
367368
return NULL;
368369

369-
while (PyDict_Next(src, &pos, &k, &v)) {
370+
/* Sort the keys so that we have a deterministic order on the indexes
371+
saved in the returned dictionary. These indexes are used as indexes
372+
into the free and cell var storage. Therefore if they aren't
373+
deterministic, then the generated bytecode is not deterministic.
374+
*/
375+
sorted_keys = PyDict_Keys(src);
376+
if (sorted_keys == NULL)
377+
return NULL;
378+
if (PyList_Sort(sorted_keys) != 0) {
379+
Py_DECREF(sorted_keys);
380+
return NULL;
381+
}
382+
num_keys = PyList_GET_SIZE(src);
383+
384+
for (key_i = 0; key_i < num_keys; key_i++) {
385+
k = PyList_GET_ITEM(sorted_keys, key_i);
386+
v = PyDict_GetItem(src, k);
370387
/* XXX this should probably be a macro in symtable.h */
371388
assert(PyInt_Check(v));
372389
scope = (PyInt_AS_LONG(v) >> SCOPE_OFF) & SCOPE_MASK;
373390

374391
if (scope == scope_type || PyInt_AS_LONG(v) & flag) {
375392
PyObject *tuple, *item = PyInt_FromLong(i);
376393
if (item == NULL) {
394+
Py_DECREF(sorted_keys);
377395
Py_DECREF(dest);
378396
return NULL;
379397
}
380398
i++;
381399
tuple = PyTuple_Pack(2, k, k->ob_type);
382400
if (!tuple || PyDict_SetItem(dest, tuple, item) < 0) {
401+
Py_DECREF(sorted_keys);
383402
Py_DECREF(item);
384403
Py_DECREF(dest);
385404
Py_XDECREF(tuple);
@@ -389,6 +408,7 @@ dictbytype(PyObject *src, int scope_type, int flag, int offset)
389408
Py_DECREF(tuple);
390409
}
391410
}
411+
Py_DECREF(sorted_keys);
392412
return dest;
393413
}
394414

0 commit comments

Comments
 (0)