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:
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 Values, which produces Scientifics 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.
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.
Reported by Tom Sydney Kerckhove (@NorfairKing); fixed by Oleg Grenrus (@phadej).
{
"home": "https://github.com/haskell/security-advisories",
"osvs": "https://raw.githubusercontent.com/haskell/security-advisories/refs/heads/generated/osv-export",
"repository": "https://github.com/haskell/security-advisories"
}"https://github.com/haskell/security-advisories/tree/main/advisories/published/2026/HSEC-2026-0012.md"
"https://raw.githubusercontent.com/haskell/security-advisories/refs/heads/generated/osv-export/2026/HSEC-2026-0012.json"
"https://github.com/haskell/security-advisories/blob/generated/osv-export/2026/HSEC-2026-0012.json"