[Python-checkins] cpython (2.7): Closes #14591: Random.jumpahead could produce an invalid MT state on 64-bit

mark.dickinson python-checkins at python.org
Sat Jun 30 18:19:49 CEST 2012


http://hg.python.org/cpython/rev/6df0b4ed8617
changeset:   77877:6df0b4ed8617
branch:      2.7
parent:      77863:739dd3f628b4
user:        Mark Dickinson <mdickinson at enthought.com>
date:        Sat Jun 30 17:19:35 2012 +0100
summary:
  Closes #14591: Random.jumpahead could produce an invalid MT state on 64-bit machines.

files:
  Lib/test/test_random.py |   8 ++++++++
  Misc/NEWS               |   3 +++
  Modules/_randommodule.c |  19 +++++++++++++++++--
  3 files changed, 28 insertions(+), 2 deletions(-)


diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py
--- a/Lib/test/test_random.py
+++ b/Lib/test/test_random.py
@@ -57,6 +57,14 @@
             self.assertRaises(TypeError, self.gen.jumpahead)  # needs an arg
             self.assertRaises(TypeError, self.gen.jumpahead, 2, 3)  # too many
 
+    def test_jumpahead_produces_valid_state(self):
+        # From http://bugs.python.org/issue14591.
+        self.gen.seed(199210368)
+        self.gen.jumpahead(13550674232554645900)
+        for i in range(500):
+            val = self.gen.random()
+            self.assertLess(val, 1.0)
+
     def test_sample(self):
         # For the entire allowable range of 0 <= k <= N, validate that
         # the sample is of the correct length and contains only unique items
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -75,6 +75,9 @@
 Library
 -------
 
+- Issue #14591: Fix bug in Random.jumpahead that could produce an invalid
+  Mersenne Twister state on 64-bit machines.
+
 - Issue #5346: Preserve permissions of mbox, MMDF and Babyl mailbox
   files on flush().
 
diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c
--- a/Modules/_randommodule.c
+++ b/Modules/_randommodule.c
@@ -400,7 +400,7 @@
     long i, j;
     PyObject *iobj;
     PyObject *remobj;
-    unsigned long *mt, tmp;
+    unsigned long *mt, tmp, nonzero;
 
     if (!PyInt_Check(n) && !PyLong_Check(n)) {
         PyErr_Format(PyExc_TypeError, "jumpahead requires an "
@@ -427,8 +427,23 @@
         mt[j] = tmp;
     }
 
-    for (i = 0; i < N; i++)
+    nonzero = 0;
+    for (i = 1; i < N; i++) {
         mt[i] += i+1;
+        mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
+        nonzero |= mt[i];
+    }
+
+    /* Ensure the state is nonzero: in the unlikely event that mt[1] through
+       mt[N-1] are all zero, set the MSB of mt[0] (see issue #14591). In the
+       normal case, we fall back to the pre-issue 14591 behaviour for mt[0]. */
+    if (nonzero) {
+        mt[0] += 1;
+        mt[0] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
+    }
+    else {
+        mt[0] = 0x80000000UL;
+    }
 
     self->index = N;
     Py_INCREF(Py_None);

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list