Skip to content

Commit 06fbe0b

Browse files
david-christiansenfrasertweedale
authored andcommitted
HSEC-2023-0007: readFloat memory exhaustion with large exponent
1 parent d262773 commit 06fbe0b

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
```toml
2+
[advisory]
3+
id = "HSEC-2023-0007"
4+
cwe = [1284, 789]
5+
keywords = ["toml", "parser", "dos"]
6+
7+
[[affected]]
8+
package = "base"
9+
cvss = "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
10+
[[affected.versions]]
11+
# it was introduced earlier, but this is the earliest version on Hackage
12+
introduced = "3.0.3.1"
13+
14+
[[affected]]
15+
package = "toml-reader"
16+
cvss = "CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H"
17+
[[affected.versions]]
18+
introduced = "0.1.0.0"
19+
fixed = "0.2.0.0"
20+
21+
[[references]]
22+
type = "REPORT"
23+
url = "https://gitlab.haskell.org/ghc/ghc/-/issues/23538"
24+
[[references]]
25+
type = "REPORT"
26+
url = "https://github.com/brandonchinn178/toml-reader/issues/8"
27+
[[references]]
28+
type = "FIX"
29+
url = "https://github.com/brandonchinn178/toml-reader/pull/9"
30+
31+
```
32+
33+
# `readFloat`: memory exhaustion with large exponent
34+
35+
`Numeric.readFloat` takes time and memory linear in the size of the
36+
number _denoted_ by the input string. In particular, processing a
37+
number expressed in scientific notation with a very large exponent
38+
could cause a denial of service. The slowdown is observable on a
39+
modern machine running GHC 9.4.4:
40+
41+
```
42+
ghci> import qualified Numeric
43+
ghci> Numeric.readFloat "1e1000000" -- near instantaneous
44+
[(Infinity,"")]
45+
ghci> Numeric.readFloat "1e10000000" -- perceptible pause
46+
[(Infinity,"")]
47+
ghci> Numeric.readFloat "1e100000000" -- ~ 3 seconds
48+
[(Infinity,"")]
49+
ghci> Numeric.readFloat "1e1000000000" -- ~ 35 seconds
50+
[(Infinity,"")]
51+
```
52+
53+
## In *base*
54+
55+
`Numeric.readFloat` is defined for all `RealFrac a => a`:
56+
57+
```haskell
58+
readFloat :: RealFrac a => ReadS a
59+
```
60+
61+
The `RealFrac` type class does not express any bounds on the size of
62+
values representable in the types for which instances exist, so
63+
bounds checking is not possible (in this *generic* function).
64+
`readFloat` uses to `Text.Read.Lex.numberToRational` which, among
65+
other things, calculates `10 ^ exponent`, which seems to take linear
66+
time and memory.
67+
68+
**Mitigation:** use `read`. The `Read` instances for `Float` and
69+
`Double` perform bounds checks on the exponent, via
70+
`Text.Read.Lex.numberToRangedRational`.
71+
72+
73+
## In *toml-reader*
74+
75+
The issue was detected in *toml-reader* version 0.1.0.0, and
76+
mitigated in version 0.2.0.0 by immediately returning `Infinity`
77+
when the exponent is large enough that there's no reason to process
78+
it.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../base/HSEC-2023-0007.md

0 commit comments

Comments
 (0)