[pypy-commit] pypy py3.6: Leave internal state unchanged if _random.Random.setstate() raises an exception (bpo-29960)

rlamy pypy.commits at gmail.com
Thu Sep 12 11:10:17 EDT 2019


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: py3.6
Changeset: r97463:2cbe9ff66003
Date: 2019-09-12 16:09 +0100
http://bitbucket.org/pypy/pypy/changeset/2cbe9ff66003/

Log:	Leave internal state unchanged if _random.Random.setstate() raises
	an exception (bpo-29960)

diff --git a/pypy/module/_random/interp_random.py b/pypy/module/_random/interp_random.py
--- a/pypy/module/_random/interp_random.py
+++ b/pypy/module/_random/interp_random.py
@@ -70,15 +70,17 @@
         # independent of platfrom, since the below condition is only
         # true on 32 bit platforms anyway
         w_add = space.pow(space.newint(2), space.newint(32), space.w_None)
+        _state = [r_uint(0)] * rrandom.N
         for i in range(rrandom.N):
             w_item = space.getitem(w_state, space.newint(i))
             if space.is_true(space.lt(w_item, w_zero)):
                 w_item = space.add(w_item, w_add)
-            self._rnd.state[i] = space.uint_w(w_item)
+            _state[i] = space.uint_w(w_item)
         w_item = space.getitem(w_state, space.newint(rrandom.N))
         index = space.int_w(w_item)
         if index < 0 or index > rrandom.N:
             raise oefmt(space.w_ValueError, "invalid state")
+        self._rnd.state = _state
         self._rnd.index = index
 
     @unwrap_spec(k=int)
diff --git a/pypy/module/_random/test/test_random.py b/pypy/module/_random/test/test_random.py
--- a/pypy/module/_random/test/test_random.py
+++ b/pypy/module/_random/test/test_random.py
@@ -41,6 +41,18 @@
         # does not crash
         rnd1.setstate((-1, ) * 624 + (0, ))
 
+    def test_failed_setstate(self):
+        import _random
+        rnd = _random.Random()
+        rnd.seed()
+        start_state = rnd.getstate()
+        raises(TypeError, rnd.setstate, None)
+        raises(ValueError, rnd.setstate, (1, 2, 3))
+        raises(TypeError, rnd.setstate, ('a',)*624 + (1,))
+        raises(ValueError, rnd.setstate, (1,)*624 + (625,))
+        # None of these failed calls should have changed the state
+        assert rnd.getstate() == start_state
+
     def test_state_repr(self):
         # since app-level jumpahead salts with repr(state),
         # it is important the repr is consistent with cpython


More information about the pypy-commit mailing list