Package: src:tinyarray Version: 1.2.5-1 User: [email protected] Usertags: python3.15 Tags: patch, ftbfs, forky, sid
Hi! While rebuilding the python related packages against the Python 3.15rc1 version we found that tinyarray fails to build from source on arm64 [1]. This also fails on Debian's buildds [2]. It fails in arm64 with: Failed: DID NOT RAISE OverflowError When converting floats to integer, `std::numeric_limits<long>::max()` (2^63 - 1) rounds up to 2^63 in float/double, causing `*ptr > max()` to be false for 2^63. The subsequent check on the cast integer relied on architecture-specific overflow behavior that does not hold on ARM64 (where out-of-range floats saturate to positive INT64_MAX instead of negative values). So, to fix it, check bounds against exact power-of-two limits before casting to detect overflow portably across architectures. I applied the fix in the sandbox [3] to be able to build the packages that depend on tinyarray, please consider applying the patch to support the upcoming 3.15 version. Happy hacking, [1]: https://debusine.debian.net/debian/r-python-python3.15/artifact/4316397/ [2]: https://buildd.debian.org/status/fetch.php?pkg=tinyarray&arch=arm64&ver=1.2.5-1&stamp=1766523038&raw=0 [3]: https://debusine.debian.net/debian/r-python-python3.15/ -- "Can you imagine what I would do if I could do all I can?" -- Sun Tzu Saludos /\/\ /\ >< `/
Description: Fix float-to-integer overflow detection across architectures When converting floats to integer, std::numeric_limits<long>::max() (2^63 - 1) rounds up to 2^63 in float/double, causing *ptr > max() to be false for 2^63. The subsequent check on the cast integer relied on architecture-specific overflow behavior that does not hold on ARM64 (where out-of-range floats saturate to positive INT64_MAX instead of negative values). . Check bounds against exact power-of-two limits before casting to detect overflow portably across architectures. Author: Maximiliano Curia <[email protected]> diff --git a/src/conversion.hh b/src/conversion.hh index bb7de89..7da9563 100644 --- a/src/conversion.hh +++ b/src/conversion.hh @@ -177,22 +177,18 @@ inline long number_from_ptr<long, unsigned long long>(const void *data) template<typename Tdest, typename Tsrc> inline Tdest _int_from_floatptr_exact(const void *data) { - const Tsrc *ptr = reinterpret_cast<const Tsrc*>(data); - Tdest result = static_cast<Tdest>(*ptr); - - // Note: the > max and < min tests are unreliable since the floating point - // representation of the maximal/minimal value may not be exact. The two - // other tests catch these problems. This approach looks flimsy and is - // implementation-dependent, but it is tested rigourosly. - if (*ptr > std::numeric_limits<Tdest>::max() || - *ptr < std::numeric_limits<Tdest>::min() || - (*ptr > 0 && result < 0) || (*ptr < 0 && result > 0)) { + const Tsrc val = *reinterpret_cast<const Tsrc*>(data); + const Tsrc min_val = static_cast<Tsrc>(std::numeric_limits<Tdest>::min()); + const Tsrc max_val_plus_1 = -min_val; + const Tsrc min_minus_1 = min_val - static_cast<Tsrc>(1); + const bool underflow = (min_minus_1 < min_val) ? (val <= min_minus_1) : (val < min_val); + + if (!(val < max_val_plus_1) || underflow) { PyErr_Format(PyExc_OverflowError, "Float too large to be represented by long"); return -1; - } else - { - return result; + } else { + return static_cast<Tdest>(val); } }

