Found while implementing #660; pre-existing on current main.
value_to_string's VAL_NUM case (src/eigenscript.c:1461) tests
if (n == (long long)n && fabs(n) < 9007199254740992.0)
The (long long)n cast is the left conjunct, so it's evaluated before the magnitude check — undefined behavior (float-cast-overflow) whenever |n| >= 2^63. UBSan flags this class; in practice the runtime's number path clamps near-overflow magnitudes to ±1e308 before many callers, but any path that reaches value_to_string with a huge double hits the cast first.
Fix is a one-liner — swap the conjuncts so the range check guards the cast:
if (fabs(n) < 9007199254740992.0 && n == (long long)n)
(#660's dump formatter already orders it this way on its own copy.) Happy to fold this into a small PR if you'd like.
Found while implementing #660; pre-existing on current
main.value_to_string's VAL_NUM case (src/eigenscript.c:1461) testsThe
(long long)ncast is the left conjunct, so it's evaluated before the magnitude check — undefined behavior (float-cast-overflow) whenever|n| >= 2^63. UBSan flags this class; in practice the runtime's number path clamps near-overflow magnitudes to ±1e308 before many callers, but any path that reachesvalue_to_stringwith a huge double hits the cast first.Fix is a one-liner — swap the conjuncts so the range check guards the cast:
(#660's dump formatter already orders it this way on its own copy.) Happy to fold this into a small PR if you'd like.