]> granicus.if.org Git - python/commitdiff
[2.7] bpo-29960 _random.Random corrupted on exception in setstate(). … (#1289)
authorMariatta <Mariatta@users.noreply.github.com>
Sat, 27 May 2017 14:19:55 +0000 (07:19 -0700)
committerGitHub <noreply@github.com>
Sat, 27 May 2017 14:19:55 +0000 (07:19 -0700)
(cherry picked from commit 9616a82e7802241a4b74cf7ae38d43c37bf66e48)

Lib/test/test_random.py
Misc/ACKS
Misc/NEWS
Modules/_randommodule.c

index e4876fd0902e701d76cebc010817d2595a536a39..90d334a835a2a7f7bf1e94bfe9f735ce5a231a98 100644 (file)
@@ -311,6 +311,7 @@ class MersenneTwister_TestBasicOps(TestBasicOps):
         self.assertRaises(ValueError, self.gen.setstate, (1, None, None))
 
     def test_setstate_middle_arg(self):
+        start_state = self.gen.getstate()
         # Wrong type, s/b tuple
         self.assertRaises(TypeError, self.gen.setstate, (2, None, None))
         # Wrong length, s/b 625
@@ -324,6 +325,10 @@ class MersenneTwister_TestBasicOps(TestBasicOps):
             self.gen.setstate((2, (1,)*624+(625,), None))
         with self.assertRaises((ValueError, OverflowError)):
             self.gen.setstate((2, (1,)*624+(-1,), None))
+        # Failed calls to setstate() should not have changed the state.
+        bits100 = self.gen.getrandbits(100)
+        self.gen.setstate(start_state)
+        self.assertEqual(self.gen.getrandbits(100), bits100)
 
     def test_referenceImplementation(self):
         # Compare the python implementation with results from the original
index b7b58a7b1c95b8730d67756a8c0befb7ec74701e..95be42717a0c09cbcc7264326dff2a42a8e2e6b4 100644 (file)
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1021,6 +1021,7 @@ Milan Oberkirch
 Pascal Oberndoerfer
 Jeffrey Ollie
 Adam Olsen
+Bryan Olson
 Grant Olson
 Koray Oner
 Piet van Oostrum
index e56af3a60c849bab6639abe3b58090ca4a7dd291..c8ba45abefc581d010643e8752c3a1feac590dd1 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -49,6 +49,9 @@ Extension Modules
 Library
 -------
 
+- bpo-29960: Preserve generator state when _random.Random.setstate()
+  raises an exception.  Patch by Bryan Olson.
+
 - bpo-30310: tkFont now supports unicode options (e.g. font family).
 
 - bpo-30414: multiprocessing.Queue._feed background running
index 4b9b0eb35d076b7dc9f2a0a856b4fcf228633f3a..852b810ae21955788be157935564010c0d41098d 100644 (file)
@@ -341,6 +341,7 @@ random_setstate(RandomObject *self, PyObject *state)
     int i;
     unsigned long element;
     long index;
+    unsigned long new_state[N];
 
     if (!PyTuple_Check(state)) {
         PyErr_SetString(PyExc_TypeError,
@@ -357,7 +358,7 @@ random_setstate(RandomObject *self, PyObject *state)
         element = PyLong_AsUnsignedLong(PyTuple_GET_ITEM(state, i));
         if (element == (unsigned long)-1 && PyErr_Occurred())
             return NULL;
-        self->state[i] = element & 0xffffffffUL; /* Make sure we get sane state */
+        new_state[i] = element & 0xffffffffUL; /* Make sure we get sane state */
     }
 
     index = PyLong_AsLong(PyTuple_GET_ITEM(state, i));
@@ -368,6 +369,8 @@ random_setstate(RandomObject *self, PyObject *state)
         return NULL;
     }
     self->index = (int)index;
+    for (i = 0; i < N; i++)
+        self->state[i] = new_state[i];
 
     Py_INCREF(Py_None);
     return Py_None;