Kaydet (Commit) 9616a82e authored tarafından bladebryan's avatar bladebryan Kaydeden (comit) Serhiy Storchaka

bpo-29960 _random.Random corrupted on exception in setstate(). (#1019)

üst 1a5856bf
...@@ -423,6 +423,7 @@ class MersenneTwister_TestBasicOps(TestBasicOps, unittest.TestCase): ...@@ -423,6 +423,7 @@ class MersenneTwister_TestBasicOps(TestBasicOps, unittest.TestCase):
self.assertRaises(ValueError, self.gen.setstate, (1, None, None)) self.assertRaises(ValueError, self.gen.setstate, (1, None, None))
def test_setstate_middle_arg(self): def test_setstate_middle_arg(self):
start_state = self.gen.getstate()
# Wrong type, s/b tuple # Wrong type, s/b tuple
self.assertRaises(TypeError, self.gen.setstate, (2, None, None)) self.assertRaises(TypeError, self.gen.setstate, (2, None, None))
# Wrong length, s/b 625 # Wrong length, s/b 625
...@@ -436,6 +437,10 @@ class MersenneTwister_TestBasicOps(TestBasicOps, unittest.TestCase): ...@@ -436,6 +437,10 @@ class MersenneTwister_TestBasicOps(TestBasicOps, unittest.TestCase):
self.gen.setstate((2, (1,)*624+(625,), None)) self.gen.setstate((2, (1,)*624+(625,), None))
with self.assertRaises((ValueError, OverflowError)): with self.assertRaises((ValueError, OverflowError)):
self.gen.setstate((2, (1,)*624+(-1,), None)) 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)" # 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 # raise ValueError. I cannot think of a simple way to achieve this, so
......
...@@ -1110,6 +1110,7 @@ Milan Oberkirch ...@@ -1110,6 +1110,7 @@ Milan Oberkirch
Pascal Oberndoerfer Pascal Oberndoerfer
Jeffrey Ollie Jeffrey Ollie
Adam Olsen Adam Olsen
Bryan Olson
Grant Olson Grant Olson
Koray Oner Koray Oner
Piet van Oostrum Piet van Oostrum
......
...@@ -317,6 +317,9 @@ Extension Modules ...@@ -317,6 +317,9 @@ Extension Modules
Library Library
------- -------
- bpo-29960: Preserve generator state when _random.Random.setstate()
raises an exception. Patch by Bryan Olson.
- bpo-29802: Fixed reference counting in module-level struct functions when - bpo-29802: Fixed reference counting in module-level struct functions when
pass arguments of wrong type. pass arguments of wrong type.
......
...@@ -348,6 +348,7 @@ random_setstate(RandomObject *self, PyObject *state) ...@@ -348,6 +348,7 @@ random_setstate(RandomObject *self, PyObject *state)
int i; int i;
unsigned long element; unsigned long element;
long index; long index;
uint32_t new_state[N];
if (!PyTuple_Check(state)) { if (!PyTuple_Check(state)) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
...@@ -364,7 +365,7 @@ random_setstate(RandomObject *self, PyObject *state) ...@@ -364,7 +365,7 @@ random_setstate(RandomObject *self, PyObject *state)
element = PyLong_AsUnsignedLong(PyTuple_GET_ITEM(state, i)); element = PyLong_AsUnsignedLong(PyTuple_GET_ITEM(state, i));
if (element == (unsigned long)-1 && PyErr_Occurred()) if (element == (unsigned long)-1 && PyErr_Occurred())
return NULL; return NULL;
self->state[i] = (uint32_t)element; new_state[i] = (uint32_t)element;
} }
index = PyLong_AsLong(PyTuple_GET_ITEM(state, i)); index = PyLong_AsLong(PyTuple_GET_ITEM(state, i));
...@@ -375,6 +376,8 @@ random_setstate(RandomObject *self, PyObject *state) ...@@ -375,6 +376,8 @@ random_setstate(RandomObject *self, PyObject *state)
return NULL; return NULL;
} }
self->index = (int)index; self->index = (int)index;
for (i = 0; i < N; i++)
self->state[i] = new_state[i];
Py_RETURN_NONE; Py_RETURN_NONE;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment