Files
Sueun Cho d5164d893d topdown: fix sum overflow when integer elements fit int64 but the sum does not (#8987)
## Description

`sum` has an integer fast path that accumulates elements into a plain Go
`int`. Any element that fits a machine int takes this path, so a running
total that exceeds int64 wraps silently:

```rego
sum([9223372036854775807, 1])    # -9223372036854775808  (should be 9223372036854775808)
sum({9223372036854775807, 1, 2}) # -9223372036854775806  (should be 9223372036854775810)
```

`plus` is correct for the same values (`9223372036854775807 + 1` is
`9223372036854775808`), so `sum` and `+` disagree.

#8887 (fixes #6281) added exact `big.Int` accumulation for elements that
are individually larger than 64 bits, but that fallback only runs when
an element does not fit a machine int (`n.Int()` fails). When every
element fits int64 and only the running total overflows, the fast path
is still taken and wraps.

## Fix

Guard the fast-path addition and fall back to the existing
`exactIntAccumulate` big.Int path on overflow, the accumulator `product`
already uses. Small-int, float, mixed, and >64-bit-element inputs are
unchanged.

## Test

Extended
`v1/test/cases/testdata/v1/aggregates/test-aggregates-bignum.yaml` with
a case where each element fits int64 but the sum does not: array and set
overflow, negative overflow, an at-limit value that must stay on the
fast path, and a `+` control. Results are rendered with `sprintf`
because the golden-case loader parses expected numbers as float64. The
case fails on `main` and passes with this change. Added the matching
WASM exception (#3711), as #8887 did, since the result exceeds 64 bits.

`go test ./v1/topdown/` passes.

Signed-off-by: Sueun Cho <sueun.dev@gmail.com>
2026-08-11 14:40:50 +00:00
..
2025-10-10 17:51:02 +02:00