summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMariatta <Mariatta@users.noreply.github.com>2017-05-27 14:19:40 (GMT)
committerGitHub <noreply@github.com>2017-05-27 14:19:40 (GMT)
commit440bc4f4b2690b99541e87bedfdb0dc4abbc0501 (patch)
tree434a113097f34f7db6c92c7ff3d0a47cb760aab5
parenta815b5a100f38b883b08d39567c5557de2c19a53 (diff)
downloadcpython-440bc4f4b2690b99541e87bedfdb0dc4abbc0501.zip
cpython-440bc4f4b2690b99541e87bedfdb0dc4abbc0501.tar.gz
cpython-440bc4f4b2690b99541e87bedfdb0dc4abbc0501.tar.bz2
[3.5] bpo-29960 _random.Random corrupted on exception in setstate(). … (#1288)
(cherry picked from commit 9616a82e7802241a4b74cf7ae38d43c37bf66e48)
-rw-r--r--Lib/test/test_random.py5
-rw-r--r--Misc/ACKS1
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/_randommodule.c5
4 files changed, 13 insertions, 1 deletions
diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py
index e80ed17..83a663f 100644
--- a/Lib/test/test_random.py
+++ b/Lib/test/test_random.py
@@ -348,6 +348,7 @@ class MersenneTwister_TestBasicOps(TestBasicOps, unittest.TestCase):
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
@@ -361,6 +362,10 @@ class MersenneTwister_TestBasicOps(TestBasicOps, unittest.TestCase):
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)
# Little trick to make "tuple(x % (2**32) for x in internalstate)"
# raise ValueError. I cannot think of a simple way to achieve this, so
diff --git a/Misc/ACKS b/Misc/ACKS
index d91d9c1..53f6879 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -1090,6 +1090,7 @@ Milan Oberkirch
Pascal Oberndoerfer
Jeffrey Ollie
Adam Olsen
+Bryan Olson
Grant Olson
Koray Oner
Piet van Oostrum
diff --git a/Misc/NEWS b/Misc/NEWS
index 5aed87a..f399734 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -56,6 +56,9 @@ Extension Modules
Library
-------
+- bpo-29960: Preserve generator state when _random.Random.setstate()
+ raises an exception. Patch by Bryan Olson.
+
- bpo-30414: multiprocessing.Queue._feed background running
thread do not break from main loop on exception.
diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c
index 9ce7882..acb116d 100644
--- a/Modules/_randommodule.c
+++ b/Modules/_randommodule.c
@@ -313,6 +313,7 @@ random_setstate(RandomObject *self, PyObject *state)
int i;
unsigned long element;
long index;
+ PY_UINT32_T new_state[N];
if (!PyTuple_Check(state)) {
PyErr_SetString(PyExc_TypeError,
@@ -329,7 +330,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] = (PY_UINT32_T)element;
+ new_state[i] = (PY_UINT32_T)element;
}
index = PyLong_AsLong(PyTuple_GET_ITEM(state, i));
@@ -340,6 +341,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;