From ff15843ccf0b8cc8dff287b8cc1e8d42a805762a Mon Sep 17 00:00:00 2001 From: David Christiansen Date: Mon, 19 Jun 2023 17:07:22 +0200 Subject: [PATCH] HSEC-2023-0007: readFloat memory exhaustion with large exponent --- advisories/hackage/base/HSEC-2023-0007.md | 78 +++++++++++++++++++ .../hackage/toml-reader/HSEC-2023-0007.md | 1 + 2 files changed, 79 insertions(+) create mode 100644 advisories/hackage/base/HSEC-2023-0007.md create mode 120000 advisories/hackage/toml-reader/HSEC-2023-0007.md diff --git a/advisories/hackage/base/HSEC-2023-0007.md b/advisories/hackage/base/HSEC-2023-0007.md new file mode 100644 index 00000000..0987d8c8 --- /dev/null +++ b/advisories/hackage/base/HSEC-2023-0007.md @@ -0,0 +1,78 @@ +```toml +[advisory] +id = "HSEC-2023-0007" +cwe = [1284, 789] +keywords = ["toml", "parser", "dos"] + +[[affected]] +package = "base" +cvss = "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H" +[[affected.versions]] +# it was introduced earlier, but this is the earliest version on Hackage +introduced = "3.0.3.1" + +[[affected]] +package = "toml-reader" +cvss = "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H" +[[affected.versions]] +introduced = "0.1.0.0" +fixed = "0.2.0.0" + +[[references]] +type = "REPORT" +url = "https://gitlab.haskell.org/ghc/ghc/-/issues/23538" +[[references]] +type = "REPORT" +url = "https://github.com/brandonchinn178/toml-reader/issues/8" +[[references]] +type = "FIX" +url = "https://github.com/brandonchinn178/toml-reader/pull/9" + +``` + +# `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. diff --git a/advisories/hackage/toml-reader/HSEC-2023-0007.md b/advisories/hackage/toml-reader/HSEC-2023-0007.md new file mode 120000 index 00000000..68d51e39 --- /dev/null +++ b/advisories/hackage/toml-reader/HSEC-2023-0007.md @@ -0,0 +1 @@ +../base/HSEC-2023-0007.md \ No newline at end of file