{"id":"HSEC-2023-0007","aliases":[],"status":"published","title":"readFloat: memory exhaustion with large exponent","description":"# `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\u003e import qualified Numeric\nghci\u003e Numeric.readFloat \"1e1000000\"    -- near instantaneous\n[(Infinity,\"\")]\nghci\u003e Numeric.readFloat \"1e10000000\"   -- perceptible pause\n[(Infinity,\"\")]\nghci\u003e Numeric.readFloat \"1e100000000\"  -- ~ 3 seconds\n[(Infinity,\"\")]\nghci\u003e Numeric.readFloat \"1e1000000000\" -- ~ 35 seconds\n[(Infinity,\"\")]\n```\n\n## In *base*\n\n`Numeric.readFloat` is defined for all `RealFrac a =\u003e a`:\n\n```haskell\nreadFloat :: RealFrac a =\u003e 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.","facts":{"in_kev":false,"known_exploited":false,"public_exploit":false,"fix_available":true},"published":"2025-11-14T14:45:34Z","modified":"2026-05-29T21:00:04Z","fixes":[{"ecosystem":"Hackage","package":"toml-reader","fixed_in":["0.2.0.0"],"sources":["osv"]}],"affected":[{"source":"osv","ecosystem":"Hackage","package":"base","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"3.0.3.1"}]}],"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"]},{"source":"osv","ecosystem":"Hackage","package":"toml-reader","ranges":[{"type":"ECOSYSTEM","events":[{"introduced":"0.1.0.0"},{"fixed":"0.2.0.0"}]}],"versions":["0.1.0.0"]}],"references":[{"url":"https://gitlab.haskell.org/ghc/ghc/-/issues/23538","tags":["report"]},{"url":"https://github.com/brandonchinn178/toml-reader/issues/8","tags":["report"]},{"url":"https://github.com/brandonchinn178/toml-reader/pull/9","tags":["fix"]}],"sources":{"osv":[{"id":"HSEC-2023-0007","title":"readFloat: memory exhaustion with large exponent","description":"# `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\u003e import qualified Numeric\nghci\u003e Numeric.readFloat \"1e1000000\"    -- near instantaneous\n[(Infinity,\"\")]\nghci\u003e Numeric.readFloat \"1e10000000\"   -- perceptible pause\n[(Infinity,\"\")]\nghci\u003e Numeric.readFloat \"1e100000000\"  -- ~ 3 seconds\n[(Infinity,\"\")]\nghci\u003e Numeric.readFloat \"1e1000000000\" -- ~ 35 seconds\n[(Infinity,\"\")]\n```\n\n## In *base*\n\n`Numeric.readFloat` is defined for all `RealFrac a =\u003e a`:\n\n```haskell\nreadFloat :: RealFrac a =\u003e 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","status":"published","published":"2025-11-14T14:45:34Z","modified":"2026-05-29T21:00:04.553436278Z","updated_at":"2026-11-02T15:47:17.805107Z"}]}}
