mirror of
https://github.com/open-policy-agent/opa.git
synced 2026-08-12 19:32:48 -06:00
d5164d893d
## 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>