hsec-2023-0007
osv_haskell# `readFloat`: memory exhaustion with large exponent `Numeric.readFloat` takes time and memory linear in the size of the number _denoted_ by the input string. In particular, processing a number expressed in scientific notation with a very large exponent could cause a denial of service. The slowdown is observable on a modern machine running GHC 9.4.4: ``` ghci> import qualified Numeric ghci> Numeric.readFloat "1e1000000" -- near instantaneous [(Infinity,"")] ghci> Numeric.readFloat "1e10000000" -- perceptible pause [(Infinity,"")] ghci> Numeric.readFloat "1e100000000" -- ~ 3 seconds [(Infinity,"")] ghci> Numeric.readFloat "1e1000000000" -- ~ 35 seconds [(Infinity,"")] ``` ## In *base* `Numeric.readFloat` is defined for all `RealFrac a => a`: ```haskell readFloat :: RealFrac a => ReadS a ``` The `RealFrac` type class does not express any bounds on the size of values representable in the types for which instances exist, so bounds checking is not possible (in this *generic* function). `readFloat` uses to `Text.Read.Lex.numberToRational` which, among other things, calculates `10 ^ exponent`, which seems to take linear time and memory. **Mitigation:** use `read`. The `Read` instances for `Float` and `Double` perform bounds checks on the exponent, via `Text.Read.Lex.numberToRangedRational`. ## In *toml-reader* The issue was detected in *toml-reader* version 0.1.0.0, and mitigated in version 0.2.0.0 by immediately returning `Infinity` when the exponent is large enough that there's no reason to process it.
- Published
- unknown
- Last Modified
- unknown
CVSS details not available.
No product information available.
No linked vulnerabilities found.
{
"affected": [
{
"database_specific": {
"human_link": "https://github.com/haskell/security-advisories/tree/main/advisories/published/2023/HSEC-2023-0007.md",
"osv": "https://raw.githubusercontent.com/haskell/security-advisories/refs/heads/generated/osv-export/2023/HSEC-2023-0007.json",
"source": "https://github.com/haskell/security-advisories/blob/generated/osv-export/2023/HSEC-2023-0007.json"
},
"package": {
"ecosystem": "Hackage",
"name": "base",
"purl": "pkg:hackage/base"
},
"ranges": [
{
"events": [
{
"introduced": "3.0.3.1"
}
],
"type": "ECOSYSTEM"
}
],
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
],
"versions": [
"3.0.3.1",
"3.0.3.2",
"4.0.0.0",
"4.1.0.0",
"4.10.0.0",
"4.10.1.0",
"4.11.0.0",
"4.11.1.0",
"4.12.0.0",
"4.13.0.0",
"4.14.0.0",
"4.14.1.0",
"4.14.2.0",
"4.14.3.0",
"4.15.0.0",
"4.15.1.0",
"4.16.0.0",
"4.16.1.0",
"4.16.2.0",
"4.16.3.0",
"4.16.4.0",
"4.17.0.0",
"4.17.1.0",
"4.17.2.0",
"4.17.2.1",
"4.18.0.0",
"4.18.1.0",
"4.18.2.0",
"4.18.2.1",
"4.18.3.0",
"4.19.0.0",
"4.19.1.0",
"4.19.2.0",
"4.2.0.0",
"4.2.0.1",
"4.2.0.2",
"4.20.0.0",
"4.20.0.1",
"4.20.1.0",
"4.20.2.0",
"4.21.0.0",
"4.21.1.0",
"4.21.2.0",
"4.22.0.0",
"4.3.0.0",
"4.3.1.0",
"4.4.0.0",
"4.4.1.0",
"4.5.0.0",
"4.5.1.0",
"4.6.0.0",
"4.6.0.1",
"4.7.0.0",
"4.7.0.1",
"4.7.0.2",
"4.8.0.0",
"4.8.1.0",
"4.8.2.0",
"4.9.0.0",
"4.9.1.0"
]
},
{
"database_specific": {
"human_link": "https://github.com/haskell/security-advisories/tree/main/advisories/published/2023/HSEC-2023-0007.md",
"osv": "https://raw.githubusercontent.com/haskell/security-advisories/refs/heads/generated/osv-export/2023/HSEC-2023-0007.json",
"source": "https://github.com/haskell/security-advisories/blob/generated/osv-export/2023/HSEC-2023-0007.json"
},
"package": {
"ecosystem": "Hackage",
"name": "toml-reader",
"purl": "pkg:hackage/toml-reader"
},
"ranges": [
{
"events": [
{
"introduced": "0.1.0.0"
},
{
"fixed": "0.2.0.0"
}
],
"type": "ECOSYSTEM"
}
],
"severity": [
{
"score": "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H",
"type": "CVSS_V3"
}
],
"versions": [
"0.1.0.0"
]
}
],
"database_specific": {
"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"
},
"details": "# `readFloat`: memory exhaustion with large exponent\n\n`Numeric.readFloat` takes time and memory linear in the size of the\nnumber _denoted_ by the input string. In particular, processing a\nnumber expressed in scientific notation with a very large exponent\ncould cause a denial of service. The slowdown is observable on a\nmodern machine running GHC 9.4.4:\n\n```\nghci> import qualified Numeric\nghci> Numeric.readFloat \"1e1000000\" -- near instantaneous\n[(Infinity,\"\")]\nghci> Numeric.readFloat \"1e10000000\" -- perceptible pause\n[(Infinity,\"\")]\nghci> Numeric.readFloat \"1e100000000\" -- ~ 3 seconds\n[(Infinity,\"\")]\nghci> Numeric.readFloat \"1e1000000000\" -- ~ 35 seconds\n[(Infinity,\"\")]\n```\n\n## In *base*\n\n`Numeric.readFloat` is defined for all `RealFrac a => a`:\n\n```haskell\nreadFloat :: RealFrac a => ReadS a\n```\n\nThe `RealFrac` type class does not express any bounds on the size of\nvalues representable in the types for which instances exist, so\nbounds checking is not possible (in this *generic* function).\n`readFloat` uses to `Text.Read.Lex.numberToRational` which, among\nother things, calculates `10 ^ exponent`, which seems to take linear\ntime and memory.\n\n**Mitigation:** use `read`. The `Read` instances for `Float` and\n`Double` perform bounds checks on the exponent, via\n`Text.Read.Lex.numberToRangedRational`.\n\n\n## In *toml-reader*\n\nThe issue was detected in *toml-reader* version 0.1.0.0, and\nmitigated in version 0.2.0.0 by immediately returning `Infinity`\nwhen the exponent is large enough that there's no reason to process\nit.\n",
"id": "HSEC-2023-0007",
"modified": "2026-05-29T21:00:04.553436278Z",
"published": "2025-11-14T14:45:34Z",
"references": [
{
"type": "REPORT",
"url": "https://gitlab.haskell.org/ghc/ghc/-/issues/23538"
},
{
"type": "REPORT",
"url": "https://github.com/brandonchinn178/toml-reader/issues/8"
},
{
"type": "FIX",
"url": "https://github.com/brandonchinn178/toml-reader/pull/9"
}
],
"schema_version": "1.7.5",
"summary": "readFloat: memory exhaustion with large exponent"
}