]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-44260: Do not read system entropy without need in Random() (GH-26455)
authorSerhiy Storchaka <storchaka@gmail.com>
Mon, 31 May 2021 20:24:20 +0000 (23:24 +0300)
committerGitHub <noreply@github.com>
Mon, 31 May 2021 20:24:20 +0000 (23:24 +0300)
Lib/test/test_random.py
Misc/NEWS.d/next/Library/2021-05-30-13-32-09.bpo-44260.ROEbVd.rst [new file with mode: 0644]
Modules/_randommodule.c

index c2dd50b981bb2e8e457207946498aed0f07b6058..448624b79be5dba3d02c08e4d591c9567f5dfab8 100644 (file)
@@ -374,23 +374,6 @@ class TestBasicOps:
             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 @@ class SystemRandom_TestBasicOps(TestBasicOps, unittest.TestCase):
             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 (file)
index 0000000..a63af62
--- /dev/null
@@ -0,0 +1,2 @@
+The :class:`random.Random` constructor no longer reads system entropy
+without need.
index 0137e34da650a186010953157654b6fe41173c51..7ad4299bc321b3c50fe04460b2c2df8ebc6b9855 100644 (file)
@@ -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},
 };