[New-bugs-announce] [issue27072] random.getrandbits is limited to 2**31-1 bits on 64-bit Windows

Steven Barker report at bugs.python.org
Sat May 21 02:07:50 EDT 2016

New submission from Steven Barker:

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:


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) {

components: Library (Lib)
files: getrandbits.diff
keywords: patch
messages: 265987
nosy: Steven.Barker
priority: normal
severity: normal
status: open
title: random.getrandbits is limited to 2**31-1 bits on 64-bit Windows
type: enhancement
versions: Python 3.6
Added file: http://bugs.python.org/file42919/getrandbits.diff

Python tracker <report at bugs.python.org>

More information about the New-bugs-announce mailing list