HSEC-2026-0012 json
Out-of-bounds read in Eq and Ord on numbers with extreme exponents
published 2026-11-03 5 d ago modified 2026-11-03 5 d ago
- cvss
- 8.2
- version 3.1, OSV
- cisa kev
- Not listed
- not in CISA's catalog
- epss
- —
- no score, EPSS covers CVEs only
- public exploits
- 0
- none known
Summary
# 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).
Patch / fix
CVSS scores
| assigned by | version | score | vector |
|---|---|---|---|
| OSV | 3.1 | 8.2 | CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:H |
Affected packages
| ecosystem | package | affected | fixed in |
|---|---|---|---|
| hackage | scientific | >=0.3.9.0, <0.3.10.0 |
0.3.10.0 |
References
Sources
- OSV HSEC-2026-0012
Fencer Vulns keeps one entry per vulnerability: the CVE id wins, then GHSA, and records that alias each other are merged, except that two CVEs always keep separate entries. The same data is available as JSON.