spray / spray-json

A lightweight, clean and simple JSON implementation in Scala
Apache License 2.0
972 stars 190 forks source link

BigDecimal should not be created without sensible values for scale and precision #287

Open jrudolph opened 5 years ago

jrudolph commented 5 years ago

Otherwise, it's easy to create BigDecimals that are so big that any operation on them will take a long time. It's somewhat arguable that spray-json needs to care for this: if your application does anything with user-supplied BigDecimals it should cut them into digestible proportion. But on the other hand, as most of these values are somewhat unlikely, it might make sense to provide guards.

Quoting @plokhotnyuk at https://github.com/spray/spray-json/pull/283#issuecomment-434363836:

Even after successful parsing of BigDecimal values like 1e1000000000 or 1e-1000000000 users can be affected by any subsequent operations like +, %, longValue, etc.

Just try how this code works in your Scala REPL:

scala> val f = (x: BigDecimal) => x + 1
f: BigDecimal => scala.math.BigDecimal = $$Lambda$1210/93981118@790ac3e0

scala> f(BigDecimal("1e1000000000"))

or

scala> val g = (x: BigDecimal) => 1 + x
g: BigDecimal => scala.math.BigDecimal = $$Lambda$1091/1954133542@e8ea697

scala> g(BigDecimal("1e-1000000000", java.math.MathContext.UNLIMITED))

To prevent this, the parser should avoid returning of BigDecimal with too big exponent (or scale) or with MathContext.UNLIMITED by default.

BTW, in jsoniter-scala java.math.MathContext.DECIMAL128 and a corresponding ~6K limit for the scale were selected as safe defaults:

plokhotnyuk/jsoniter-scala:jsoniter-scala-macros/src/main/scala/com/github/plokhotnyuk/jsoniter_scala/macros/JsonCodecMaker.scala@master#L65-L66