fix(arith): keep integer div exact and UB-free - #403
Conversation
div routed integer operands through doubles, silently corrupting every result above 2^53 (div 9007199254740993 1 -> 9007199254740992) and tripping UBSan at q == 2^63 (div -9223372036854775807 -1) because the q > (double)INT64_MAX guard can never fire. Integer operands now divide in int64 space with a floor correction, matching the temporal mod path; the double path is kept only for float operands with a tightened guard.
singaraiona
left a comment
There was a problem hiding this comment.
The scalar ray_idiv_fn change is correct, and the new integration/math cases pass, but this does not fix compiled query execution. select/update compile div to OP_IDIV; the I64 kernel in src/ops/expr.c still reads both operands as double before floor/cast. On this PR build:
(set T (table [v] (list [9007199254740993 123456789012345678])))
(at (select {q: (div v 1) from: T}) (quote q))
returns [9007199254740992 123456789012345680], and update has the same result. The top-level vector tests pass because that call path maps through ray_idiv_fn per element; they do not cover the query/DAG path. Please make integer OP_IDIV stay in integer space in the compiled/fallback kernels too, and add select/update regressions above 2^53.
Summary: keep integer-only div in int64 space to avoid double precision loss above 2^53 and avoid UB at the 2^63 float boundary; add math regressions for exact large integers, vector paths, float out-of-range nulls, and floor semantics. Tests: make test TEST_CORES=2.