Control: Severity -1 serious
Control: Tags -1 patch

Hi,

This is still failing today. I'm not sure why the severity was reported as important and not serious, i386 is still a release architecture.

From https://buildd.debian.org/status/fetch.php?pkg=tinyarray&arch=i386&ver=1.2.5-1&stamp=1766523209&raw=0

This is the current cause of failure:
=================================== FAILURES =================================== ______________________________ test_hash_equality ______________________________

    def test_hash_equality():
        random.seed(123)

# These refer to the width of integers stored in a tinyarray.ndarray_int. int_bits = (8 * ta.dtype_size[int]) - 1 # 8 bits per byte, minus 1 sign bit
        maxint = 2**(int_bits)

        special = [float('inf'), float('-inf'),
                   0, -1, -1.0, -1 + 0j,
303, -312424, -0.3, 1.7, 0.4j, -12.3j, 1 - 12.3j, 1.3 - 12.3j,
                   (), (-1,), (2,),
                   (0, 0), (-1, -1), (-5, 7), (3, -1, 0),
                   ((0, 1), (2, 3)), (((-1,),),)]
powers = [sign * (2**e + a) for sign in [1, -1] for a in [-1, 0, 1]
                  for e in range(int_bits)]
        powers.extend([2**int_bits - 1, -2**int_bits, -2**int_bits + 1])
small_random_ints = (random.randrange(-2**16, 2**16) for i in range(1000)) large_random_ints = (random.randrange(-maxint, maxint) for i in range(1000))
        small_random_floats = (random.gauss(0, 1) for i in range(1000))
large_random_floats = (random.gauss(0, 1e100) for i in range(1000))

        for collection in [special, powers,
                           small_random_ints, large_random_ints,
                           small_random_floats, large_random_floats]:
            for thing in collection:
                arr = ta.array(thing)
                if thing == thing:
                    assert arr == thing
                    assert not (arr != thing)
              assert hash(arr) == hash(thing), repr(thing)
E               AssertionError: -2147483648
E               assert 1 == -2
E                +  where 1 = hash(array(-2147483648))
E                +  and   -2 = hash(-2147483648)

../../../test_tinyarray.py:358: AssertionError

This happens because the code that calculates the hash overflows in 32bits with that number. It can be fixed by doing the calculation using unsigned long instead. Attaching a patch here.

I'm working on an upload to solve this issue as well as #1146590 (failure on arm64 and other arches)

--
Regards,
Marga
Description: Fix integer hash calculation for minimum signed value
 In 32bit architectures, using Py_hash_t for the sign and result variables
 leads to overflows when x is LONG_MIN, that cause the hash to evaluate
 incorrectly. So we cast to unsigned long to avoid the overflow.
Author: Maximiliano Curia <[email protected]>
--- a/src/array.cc
+++ b/src/array.cc
@@ -819,9 +819,10 @@
 {
     // For integers the hash is just the integer itself modulo _PyHASH_MODULUS
     // except for the singular case of -1.
-    // define 'sign' of the correct width to avoid overflow
-    Py_hash_t sign = x < 0 ? -1 : 1;
-    Py_hash_t result = sign * ((sign * x) % _PyHASH_MODULUS);
+    // Take the absolute value as unsigned long to avoid overflows when checking the sign.
+    unsigned long abs_x = x < 0 ? -static_cast<unsigned long>(x) : static_cast<unsigned long>(x);
+    Py_hash_t result = static_cast<Py_hash_t>(abs_x % _PyHASH_MODULUS);
+    if (x < 0) result = -result;
     return result == -1 ? -2 : result;
 }
 

Reply via email to