summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2021-05-31 20:24:20 (GMT)
committerGitHub <noreply@github.com>2021-05-31 20:24:20 (GMT)
commita6a20658814e8668966fc86de0e80a4772864781 (patch)
treea3dd1e6bf04fd70ec20fe5829605f248e450bb86
parent78d9a9b1904f0e1d9db1e941c19782f4f5a881d4 (diff)
downloadcpython-a6a20658814e8668966fc86de0e80a4772864781.zip
cpython-a6a20658814e8668966fc86de0e80a4772864781.tar.gz
cpython-a6a20658814e8668966fc86de0e80a4772864781.tar.bz2
bpo-44260: Do not read system entropy without need in Random() (GH-26455)
-rw-r--r--Lib/test/test_random.py36
-rw-r--r--Misc/NEWS.d/next/Library/2021-05-30-13-32-09.bpo-44260.ROEbVd.rst2
-rw-r--r--Modules/_randommodule.c44
3 files changed, 38 insertions, 44 deletions
diff --git a/Lib/test/test_random.py b/Lib/test/test_random.py
index c2dd50b..448624b 100644
--- a/Lib/test/test_random.py
+++ b/Lib/test/test_random.py
@@ -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
index 0000000..a63af62
--- /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 0137e34..7ad4299 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},
};