This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author Steven.Barker
Recipients Steven.Barker
Date 2016-05-21.06:07:47
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1463810870.39.0.980113200971.issue27072@psf.upfronthosting.co.za>
In-reply-to
Content
The C implementation of `_random.Random.getrandbits` is unnecessarily limited in the number of bits it can produce on 64-bit Windows systems. I learned about this issue in discussion of my answer to this stack overflow question:

 http://stackoverflow.com/questions/37356338/is-there-a-predictable-replacement-for-os-urandom-using-pythons-random-module

The argument parsing code in `getrandbits` forces its Python `int` argument to fit into a C `int` variable. On my 64-bit Windows system, any value larger than `2**31-1` causes a `OverflowError`.

Since the number of bits is directly related to how much memory we need to allocate (in the non-fast case), I think `Py_ssize_t` would be more appropriate type than a regular `int`. This probably isn't an issue on non-Windows or 64-bit systems, where `int` and `Py_ssize_t` will have the same size.

I'm attaching a very simple patch that changes the types of the relevant variables and the format code in the call to `PyArg_ParseTuple`. The code works and still passes its tests with the patch. I considered adding an additional test for this issue, but passing test cases would require allocations of several gigabytes of memory which seems a rather unfriendly thing to add in a test for a fairly minor issue.

This issue doesn't effect the pure Python implementation of `random.SystemRandom.getrandbits`, which already worked fine when large numbers of bits were requested. The documentation for `random.getrandbits` doesn't mention any limitation on the number of bits provided, so I don't imagine there will be backwards compatibility issues. I also don't expect the change to have any impact on third party `Random` replacement classes.

For convenience, here's the contents of the very short patch (which I'll also attach):

diff --git a/Modules/_randommodule.c b/Modules/_randommodule.c
index fd6b230..3bf564f 100644
--- a/Modules/_randommodule.c
+++ b/Modules/_randommodule.c
@@ -348,12 +348,12 @@ random_setstate(RandomObject *self, PyObject *state)
 static PyObject *
 random_getrandbits(RandomObject *self, PyObject *args)
 {
-    int k, i, words;
+    Py_ssize_t k, i, words;
     PY_UINT32_T r;
     PY_UINT32_T *wordarray;
     PyObject *result;

-    if (!PyArg_ParseTuple(args, "i:getrandbits", &k))
+    if (!PyArg_ParseTuple(args, "n:getrandbits", &k))
         return NULL;

     if (k <= 0) {
History
Date User Action Args
2016-05-21 06:07:50Steven.Barkersetrecipients: + Steven.Barker
2016-05-21 06:07:50Steven.Barkersetmessageid: <1463810870.39.0.980113200971.issue27072@psf.upfronthosting.co.za>
2016-05-21 06:07:49Steven.Barkerlinkissue27072 messages
2016-05-21 06:07:48Steven.Barkercreate