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:
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) { ---------- 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 <rep...@bugs.python.org> <http://bugs.python.org/issue27072> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com