-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
HSEC-2023-0007: readFloat memory exhaustion with large exponent
- Loading branch information
1 parent
d262773
commit ff15843
Showing
2 changed files
with
79 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../base/HSEC-2023-0007.md |