bpo-44260: Do not read system entropy without need in Random() (GH-26455)
![](https://secure.gravatar.com/avatar/cc7737cd64a84f1b5c61a160798e97ee.jpg?s=120&d=mm&r=g)
https://github.com/python/cpython/commit/a6a20658814e8668966fc86de0e80a47728... commit: a6a20658814e8668966fc86de0e80a4772864781 branch: main author: Serhiy Storchaka <storchaka@gmail.com> committer: serhiy-storchaka <storchaka@gmail.com> date: 2021-05-31T23:24:20+03:00 summary: bpo-44260: Do not read system entropy without need in Random() (GH-26455) files: A Misc/NEWS.d/next/Library/2021-05-30-13-32-09.bpo-44260.ROEbVd.rst M Lib/test/test_random.py M Modules/_randommodule.c diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py index c2dd50b981bb2..448624b79be5d 100644 --- a/Lib/test/test_random.py +++ b/Lib/test/test_random.py @@ -374,23 +374,6 @@ def test_pickling(self): restoredseq = [newgen.random() for i in range(10)] self.assertEqual(origseq, restoredseq) - @test.support.cpython_only - def test_bug_41052(self): - # _random.Random should not be allowed to serialization - import _random - for proto in range(pickle.HIGHEST_PROTOCOL + 1): - r = _random.Random() - self.assertRaises(TypeError, pickle.dumps, r, proto) - - @test.support.cpython_only - def test_bug_42008(self): - # _random.Random should call seed with first element of arg tuple - import _random - r1 = _random.Random() - r1.seed(8675309) - r2 = _random.Random(8675309) - self.assertEqual(r1.random(), r2.random()) - def test_bug_1727780(self): # verify that version-2-pickles can be loaded # fine, whether they are created on 32-bit or 64-bit @@ -573,6 +556,25 @@ def test_randbelow_logic(self, _log=log, int=int): self.assertTrue(2**k > n > 2**(k-1)) # note the stronger assertion +class TestRawMersenneTwister(unittest.TestCase): + @test.support.cpython_only + def test_bug_41052(self): + # _random.Random should not be allowed to serialization + import _random + for proto in range(pickle.HIGHEST_PROTOCOL + 1): + r = _random.Random() + self.assertRaises(TypeError, pickle.dumps, r, proto) + + @test.support.cpython_only + def test_bug_42008(self): + # _random.Random should call seed with first element of arg tuple + import _random + r1 = _random.Random() + r1.seed(8675309) + r2 = _random.Random(8675309) + self.assertEqual(r1.random(), r2.random()) + + class MersenneTwister_TestBasicOps(TestBasicOps, unittest.TestCase): gen = random.Random() diff --git a/Misc/NEWS.d/next/Library/2021-05-30-13-32-09.bpo-44260.ROEbVd.rst b/Misc/NEWS.d/next/Library/2021-05-30-13-32-09.bpo-44260.ROEbVd.rst new file mode 100644 index 0000000000000..a63af627e6fbf --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-05-30-13-32-09.bpo-44260.ROEbVd.rst @@ -0,0 +1,2 @@ +The :class:`random.Random` constructor no longer reads system entropy +without need. diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c index 0137e34da650a..7ad4299bc321b 100644 --- a/Modules/_randommodule.c +++ b/Modules/_randommodule.c @@ -263,10 +263,10 @@ random_seed_time_pid(RandomObject *self) init_by_array(self, key, Py_ARRAY_LENGTH(key)); } -static PyObject * +static int random_seed(RandomObject *self, PyObject *arg) { - PyObject *result = NULL; /* guilty until proved innocent */ + int result = -1; /* guilty until proved innocent */ PyObject *n = NULL; uint32_t *key = NULL; size_t bits, keyused; @@ -280,7 +280,7 @@ random_seed(RandomObject *self, PyObject *arg) use the current time and process identifier. */ random_seed_time_pid(self); } - Py_RETURN_NONE; + return 0; } /* This algorithm relies on the number being unsigned. @@ -339,8 +339,7 @@ random_seed(RandomObject *self, PyObject *arg) #endif init_by_array(self, key, keyused); - Py_INCREF(Py_None); - result = Py_None; + result = 0; Done: Py_XDECREF(n); @@ -365,7 +364,10 @@ static PyObject * _random_Random_seed_impl(RandomObject *self, PyObject *n) /*[clinic end generated code: output=0fad1e16ba883681 input=78d6ef0d52532a54]*/ { - return random_seed(self, n); + if (random_seed(self, n) < 0) { + return NULL; + } + Py_RETURN_NONE; } /*[clinic input] @@ -515,39 +517,26 @@ _random_Random_getrandbits_impl(RandomObject *self, int k) return result; } -static PyObject * -random_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +static int +random_init(RandomObject *self, PyObject *args, PyObject *kwds) { - RandomObject *self; - PyObject *tmp; PyObject *arg = NULL; - _randomstate *state = _randomstate_type(type); + _randomstate *state = _randomstate_type(Py_TYPE(self)); - if (type == (PyTypeObject*)state->Random_Type && + if (Py_IS_TYPE(self, (PyTypeObject *)state->Random_Type) && !_PyArg_NoKeywords("Random()", kwds)) { - return NULL; + return -1; } - self = (RandomObject *)PyType_GenericAlloc(type, 0); - if (self == NULL) - return NULL; - if (PyTuple_GET_SIZE(args) > 1) { PyErr_SetString(PyExc_TypeError, "Random() requires 0 or 1 argument"); - return NULL; + return -1; } if (PyTuple_GET_SIZE(args) == 1) arg = PyTuple_GET_ITEM(args, 0); - tmp = random_seed(self, arg); - if (tmp == NULL) { - Py_DECREF(self); - return NULL; - } - Py_DECREF(tmp); - - return (PyObject *)self; + return random_seed(self, arg); } @@ -566,7 +555,8 @@ PyDoc_STRVAR(random_doc, static PyType_Slot Random_Type_slots[] = { {Py_tp_doc, (void *)random_doc}, {Py_tp_methods, random_methods}, - {Py_tp_new, random_new}, + {Py_tp_new, PyType_GenericNew}, + {Py_tp_init, random_init}, {Py_tp_free, PyObject_Free}, {0, 0}, };
participants (1)
-
serhiy-storchaka