Description
# Superlinear encoding of numbers with large coefficients
Encoding (pretty-printing) a `Scientific` number whose coefficient has many
digits took time quadratic in the number of digits: the decimal digits were
extracted by repeatedly dividing the whole coefficient by 10, once per digit.
The `Show` instance, `Data.Text.Lazy.Builder.Scientific` and
`Data.ByteString.Builder.Scientific` — which `aeson` uses to encode JSON
numbers — all share this code path. A number with one million digits took
about a minute to show, and about a tenth of a second after the fix.
This is a denial-of-service risk for applications that decode numbers from an
untrusted source and encode them again, e.g. JSON proxies, loggers or API
gateways built on `aeson`.
## Resolution
`scientific-0.3.9.0` reimplemented `normalize` and `toDecimalDigits` (the
digit-extraction primitive) to be practically linear in the coefficient size.
Note that `scientific-0.3.9.0` introduced a regression of its own; see
HSEC-2026-0012. Upgrade
directly to `scientific-0.3.10.0` or later, which fixes both issues.
## Credits
Reported by Andrzej Rybczak (@arybczak); fixed by Oleg Grenrus (@phadej).
Affected packages
| Ecosystem | Package | Affected | Fixed | Record |
|---|---|---|---|---|
| Hackage | scientific | < 0.3.9.0 | 0.3.9.0 | HSEC-2026-0011 |