Skip to content

Commit

Permalink
HSEC-2023-0007: readFloat memory exhaustion with large exponent
Browse files Browse the repository at this point in the history
  • Loading branch information
david-christiansen authored and frasertweedale committed Jul 22, 2023
1 parent d262773 commit 06fbe0b
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 0 deletions.
78 changes: 78 additions & 0 deletions advisories/hackage/base/HSEC-2023-0007.md
Original file line number Diff line number Diff line change
@@ -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.
1 change: 1 addition & 0 deletions advisories/hackage/toml-reader/HSEC-2023-0007.md

0 comments on commit 06fbe0b

Please sign in to comment.