{"id":"HSEC-2026-0012","aliases":[],"status":"published","title":"Out-of-bounds read in Eq and Ord on numbers with extreme exponents","description":"# Out-of-bounds read in Eq and Ord on numbers with extreme exponents\n\n`scientific-0.3.9.0` reimplemented `Eq` and `Ord` without normalising their\narguments. The new implementation short-circuits on\n`integerLog10' c + e` computed in `Int`, which overflows when the base-10\nexponent is close to `maxBound :: Int`. The overflowed comparison then falls\nthrough to `magnitude (e1 - e2)`, where the exponent difference overflows to a\nnegative `Int` as well. `magnitude` indexed its cached power-of-ten array\nwithout a bounds check, so the negative index performed an out-of-bounds read\nand the process died with `SIGSEGV`.\n\nWith `scientific-0.3.9.0` (GHC 9.10.3, x86_64-linux), as reported in\n[basvandijk/scientific#120](https://github.com/basvandijk/scientific/issues/120):\n\n```haskell\nimport Data.Scientific\n\nmain :: IO ()\nmain = print (scientific 10 maxBound == scientific 1 minBound)\n```\n\n```\n$ ./repro; echo \"exit=$?\"\nexit=139\n```\n\nThe issue was discovered when Stackage nightly test suites\n(`genvalidity-hspec-aeson`, `genvalidity-sydtest-aeson`) started segfaulting\nafter upgrading to `scientific-0.3.9.0`: their property tests round-trip\n`aeson` `Value`s, which produces `Scientific`s with extreme exponents.\n\nVersions before `0.3.9.0` did not crash, but `Eq`/`Ord` returned invalid\nresults there instead (the normalisation-based implementation overflows the\nexponent, reporting `scientific 10 maxBound == scientific 1 minBound` as\n`True`). The same unchecked read was also reachable through `(+)` and `(-)` on\nolder versions, guarded only by the documented warning about the potential\n`10^e` blowup — reading outside the cache is not.\n\n## Resolution\n\n`scientific-0.3.10.0` computes the logarithms using `Integer`, fixing both the\ncrash and the invalid comparison results, and bounds-checks `magnitude`, so a\nnegative exponent now raises an error instead of reading out of bounds. All\nentry points (`Eq`, `Ord`, `(+)`, `(-)`) are covered; upgrade to\n`scientific-0.3.10.0` or later.\n\nNote that printing values with exponents close to `maxBound :: Int` remains\nunreliable due to the inherent `Int` exponent overflow in `normalize`; this\nlimitation is documented upstream and postponed to the next major release.\n\n## Credits\n\nReported by Tom Sydney Kerckhove (@NorfairKing); fixed by Oleg Grenrus\n(@phadej).","facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"published":"2026-11-03T22:32:58Z","modified":"2026-11-03T22:45:02Z","fixes":[{"ecosystem":"Hackage","package":"scientific","fixed_in":["0.3.10.0"],"sources":["osv"]}],"affected":[{"source":"osv","ecosystem":"Hackage","package":"scientific","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0.3.9.0"},{"fixed":"0.3.10.0"}]}],"versions":["0.3.9.0"]}],"references":[{"url":"https://github.com/basvandijk/scientific/issues/120","tags":["report"]},{"url":"https://github.com/NorfairKing/validity/issues/121","tags":["report"]},{"url":"https://github.com/basvandijk/scientific/pull/121","tags":["fix"]},{"url":"https://www.reddit.com/r/haskell/comments/1xbj59g/dont_use_scientific_for_calculations_it_can/","tags":["discussion"]}],"sources":{"osv":[{"id":"HSEC-2026-0012","title":"Out-of-bounds read in Eq and Ord on numbers with extreme exponents","description":"# Out-of-bounds read in Eq and Ord on numbers with extreme exponents\n\n`scientific-0.3.9.0` reimplemented `Eq` and `Ord` without normalising their\narguments. The new implementation short-circuits on\n`integerLog10' c + e` computed in `Int`, which overflows when the base-10\nexponent is close to `maxBound :: Int`. The overflowed comparison then falls\nthrough to `magnitude (e1 - e2)`, where the exponent difference overflows to a\nnegative `Int` as well. `magnitude` indexed its cached power-of-ten array\nwithout a bounds check, so the negative index performed an out-of-bounds read\nand the process died with `SIGSEGV`.\n\nWith `scientific-0.3.9.0` (GHC 9.10.3, x86_64-linux), as reported in\n[basvandijk/scientific#120](https://github.com/basvandijk/scientific/issues/120):\n\n```haskell\nimport Data.Scientific\n\nmain :: IO ()\nmain = print (scientific 10 maxBound == scientific 1 minBound)\n```\n\n```\n$ ./repro; echo \"exit=$?\"\nexit=139\n```\n\nThe issue was discovered when Stackage nightly test suites\n(`genvalidity-hspec-aeson`, `genvalidity-sydtest-aeson`) started segfaulting\nafter upgrading to `scientific-0.3.9.0`: their property tests round-trip\n`aeson` `Value`s, which produces `Scientific`s with extreme exponents.\n\nVersions before `0.3.9.0` did not crash, but `Eq`/`Ord` returned invalid\nresults there instead (the normalisation-based implementation overflows the\nexponent, reporting `scientific 10 maxBound == scientific 1 minBound` as\n`True`). The same unchecked read was also reachable through `(+)` and `(-)` on\nolder versions, guarded only by the documented warning about the potential\n`10^e` blowup — reading outside the cache is not.\n\n## Resolution\n\n`scientific-0.3.10.0` computes the logarithms using `Integer`, fixing both the\ncrash and the invalid comparison results, and bounds-checks `magnitude`, so a\nnegative exponent now raises an error instead of reading out of bounds. All\nentry points (`Eq`, `Ord`, `(+)`, `(-)`) are covered; upgrade to\n`scientific-0.3.10.0` or later.\n\nNote that printing values with exponents close to `maxBound :: Int` remains\nunreliable due to the inherent `Int` exponent overflow in `normalize`; this\nlimitation is documented upstream and postponed to the next major release.\n\n## Credits\n\nReported by Tom Sydney Kerckhove (@NorfairKing); fixed by Oleg Grenrus\n(@phadej).\n","status":"published","published":"2026-11-03T22:32:58Z","modified":"2026-11-03T22:45:02.61304144Z","updated_at":"2026-11-03T22:59:30.419462Z"}]}}
