Skip to content
OpenAdvisories
Unscored HSEC-2026-0012

Out-of-bounds read in Eq and Ord on numbers with extreme exponents

Published Nov 3, 2026 · Updated Nov 3, 2026 · Assigned by HSEC

Description

# Out-of-bounds read in Eq and Ord on numbers with extreme exponents

`scientific-0.3.9.0` reimplemented `Eq` and `Ord` without normalising their
arguments. The new implementation short-circuits on
`integerLog10' c + e` computed in `Int`, which overflows when the base-10
exponent is close to `maxBound :: Int`. The overflowed comparison then falls
through to `magnitude (e1 - e2)`, where the exponent difference overflows to a
negative `Int` as well. `magnitude` indexed its cached power-of-ten array
without a bounds check, so the negative index performed an out-of-bounds read
and the process died with `SIGSEGV`.

With `scientific-0.3.9.0` (GHC 9.10.3, x86_64-linux), as reported in
[basvandijk/scientific#120](https://github.com/basvandijk/scientific/issues/120):

```haskell
import Data.Scientific

main :: IO ()
main = print (scientific 10 maxBound == scientific 1 minBound)
```

```
$ ./repro; echo "exit=$?"
exit=139
```

The issue was discovered when Stackage nightly test suites
(`genvalidity-hspec-aeson`, `genvalidity-sydtest-aeson`) started segfaulting
after upgrading to `scientific-0.3.9.0`: their property tests round-trip
`aeson` `Value`s, which produces `Scientific`s with extreme exponents.

Versions before `0.3.9.0` did not crash, but `Eq`/`Ord` returned invalid
results there instead (the normalisation-based implementation overflows the
exponent, reporting `scientific 10 maxBound == scientific 1 minBound` as
`True`). The same unchecked read was also reachable through `(+)` and `(-)` on
older versions, guarded only by the documented warning about the potential
`10^e` blowup — reading outside the cache is not.

## Resolution

`scientific-0.3.10.0` computes the logarithms using `Integer`, fixing both the
crash and the invalid comparison results, and bounds-checks `magnitude`, so a
negative exponent now raises an error instead of reading out of bounds. All
entry points (`Eq`, `Ord`, `(+)`, `(-)`) are covered; upgrade to
`scientific-0.3.10.0` or later.

Note that printing values with exponents close to `maxBound :: Int` remains
unreliable due to the inherent `Int` exponent overflow in `normalize`; this
limitation is documented upstream and postponed to the next major release.

## Credits

Reported by Tom Sydney Kerckhove (@NorfairKing); fixed by Oleg Grenrus
(@phadej).

Affected packages

EcosystemPackageAffectedFixedRecord
Hackage scientific >= 0.3.9.0, < 0.3.10.0 0.3.10.0 HSEC-2026-0012

References