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).
Info
- Published
- November 03, 2026
- Modified
- November 03, 2026
- CAPECs
- < none >
- CWEs
- 407
- Keywords
- dos, json, encoding
- Aliases
- < none >
- Related
- HSEC-2026-0012
- References
- [REPORT] https://github.com/basvandijk/scientific/pull/109
- [FIX] https://github.com/basvandijk/scientific/pull/116
- [FIX] https://github.com/basvandijk/scientific/pull/117
- [DISCUSSION] https://www.reddit.com/r/haskell/comments/1xbj59g/dont_use_scientific_for_calculations_it_can/
Affected
@hackage/scientific
- CVSS
- CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
- Versions
>=0 && <0.3.9.0- Declarations
- < none >
- Affected APIs
- < none >