From e6df66d52152156ba8bcda64b37f4995bda72d2f Mon Sep 17 00:00:00 2001 From: Graham Markall Date: Fri, 14 Jan 2022 21:24:40 +0000 Subject: [PATCH] Fix #7713: Ensure _prng_random_hash return has correct bitwidth When the hash width is 32 bits, get_next_int32 needs to be used because that returns a 32-bit integer, as opposed to get_next_int, which returns a 64-bit integer regardless of the supplied bitwidth. This commit also alters the signature of _prng_random_hash to use _Py_hash_t as the return type - it will be equal to types.intp, but the intent should be clearer. --- numba/cpython/hashing.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/numba/cpython/hashing.py b/numba/cpython/hashing.py index 5a8673b04b..227fc4e1c5 100644 --- a/numba/cpython/hashing.py +++ b/numba/cpython/hashing.py @@ -18,7 +18,8 @@ from numba.core import errors from numba.core import types, utils from numba.core.unsafe.bytes import grab_byte, grab_uint64_t -from numba.cpython.randomimpl import get_state_ptr, get_next_int, const_int +from numba.cpython.randomimpl import (const_int, get_next_int, get_next_int32, + get_state_ptr) _py38_or_later = utils.PYVERSION >= (3, 8) _py310_or_later = utils.PYVERSION >= (3, 10) @@ -137,11 +138,23 @@ def _prng_random_hash(tyctx): def impl(cgctx, builder, signature, args): state_ptr = get_state_ptr(cgctx, builder, "internal") - bits = const_int(types.intp.bitwidth) - value = get_next_int(cgctx, builder, state_ptr, bits, False) + bits = const_int(_hash_width) + + # Why not just use get_next_int() with the correct bitwidth? + # get_next_int() always returns an i64, because the bitwidth it is + # passed may not be a compile-time constant, so it needs to allocate + # the largest unit of storage that may be required. Therefore, if the + # hash width is 32, then we need to use get_next_int32() to ensure we + # don't return a wider-than-expected hash, even if everything above + # the low 32 bits would have been zero. + if _hash_width == 32: + value = get_next_int32(cgctx, builder, state_ptr) + else: + value = get_next_int(cgctx, builder, state_ptr, bits, False) + return value - sig = types.intp() + sig = _Py_hash_t() return sig, impl