fix: avoid SIGFPE on x86_64 for ISize division overflow (#12110)

This PR fixes a SIGFPE crash on x86_64 when evaluating `(ISize.minValue
/ -1 : ISize)`, filling an omission from #11624.

Closes #12097.
This commit is contained in:
Eric Wieser 2026-01-27 11:36:07 -08:00 committed by GitHub
parent 31e4eb62b7
commit afee8aa1c1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 14 additions and 4 deletions

View file

@ -2664,15 +2664,19 @@ static inline size_t lean_isize_mul(size_t a1, size_t a2) {
static inline size_t lean_isize_div(size_t a1, size_t a2) {
ptrdiff_t lhs = (ptrdiff_t)a1;
ptrdiff_t rhs = (ptrdiff_t)a2;
return (size_t)(rhs == 0 ? 0 : lhs / rhs);
if (rhs == 0) return 0;
// Check for overflow: PTRDIFF_MIN / -1 would trap on x86 idiv
if (lhs == PTRDIFF_MIN && rhs == -1) return (size_t)PTRDIFF_MIN;
return (size_t)(lhs / rhs);
}
static inline size_t lean_isize_mod(size_t a1, size_t a2) {
ptrdiff_t lhs = (ptrdiff_t)a1;
ptrdiff_t rhs = (ptrdiff_t)a2;
return (size_t)(rhs == 0 ? lhs : lhs % rhs);
if (rhs == 0) return (size_t)lhs;
// Check for overflow: PTRDIFF_MIN / -1 would trap on x86 idiv
if (lhs == PTRDIFF_MIN && rhs == -1) return 0;
return (size_t)(lhs % rhs);
}
static inline size_t lean_isize_land(size_t a1, size_t a2) {

View file

@ -1,5 +1,7 @@
#include "util/options.h"
// I would like this to be regenerated please.
namespace lean {
options get_default_options() {
options opts;

View file

@ -15,6 +15,7 @@ and 0 for mod.
#guard (Int16.minValue / -1 : Int16) == Int16.minValue
#guard (Int32.minValue / -1 : Int32) == Int32.minValue
#guard (Int64.minValue / -1 : Int64) == Int64.minValue
#guard (ISize.minValue / -1 : ISize) == ISize.minValue
-- Test that signed mod handles overflow correctly
-- INT_MIN % -1 should return 0
@ -23,14 +24,17 @@ and 0 for mod.
#guard (Int16.minValue % -1 : Int16) == 0
#guard (Int32.minValue % -1 : Int32) == 0
#guard (Int64.minValue % -1 : Int64) == 0
#guard (ISize.minValue % -1 : ISize) == 0
-- Also test via #eval to exercise the C runtime
#eval (Int8.minValue / -1 : Int8)
#eval (Int16.minValue / -1 : Int16)
#eval (Int32.minValue / -1 : Int32)
#eval (Int64.minValue / -1 : Int64)
#eval (ISize.minValue / -1 : ISize)
#eval (Int8.minValue % -1 : Int8)
#eval (Int16.minValue % -1 : Int16)
#eval (Int32.minValue % -1 : Int32)
#eval (Int64.minValue % -1 : Int64)
#eval (ISize.minValue % -1 : ISize)