-
-
Notifications
You must be signed in to change notification settings - Fork 165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Scala 3 parser can be DoS'ed by JSON object with keys that have the same hash code #416
Comments
Here a self-contained reproduction copy pasted from the jsoniter-scala benchmark: import upickle.default._
object Main {
def zeroHashCodeStrings: Iterator[String] = {
def charAndHash(h: Int): Iterator[(Char, Int)] = ('!' to '~').iterator.map(ch => (ch, (h + ch) * 31))
for {
(ch0, h0) <- charAndHash(0)
(ch1, h1) <- charAndHash(h0)
(ch2, h2) <- charAndHash(h1) if ((h2 + 32) * 923521 ^ (h2 + 127) * 923521) < 0
(ch3, h3) <- charAndHash(h2) if ((h3 + 32) * 29791 ^ (h3 + 127) * 29791) < 0
(ch4, h4) <- charAndHash(h3) if ((h4 + 32) * 961 ^ (h4 + 127) * 961) < 0
(ch5, h5) <- charAndHash(h4) if ((h5 + 32) * 31 ^ (h5 + 127) * 31) < 0
(ch6, h6) <- charAndHash(h5) if (h6 + 32 ^ h6 + 127) < 0
(ch7, _) <- charAndHash(h6) if h6 + ch7 == 0
} yield new String(Array(ch0, ch1, ch2, ch3, ch4, ch5, ch6, ch7))
}
val jsonString =
zeroHashCodeStrings
.map(s => ujson.write(s))
.take(1000000)
.mkString("{", s":null,", ":null}")
case class Foo()
implicit val rw: ReadWriter[Foo] = macroRW[Foo]
def main(args: Array[String]): Unit = {
// in any Scala version
ujson.read(jsonString)
// Scala 3 only
upickle.default.read[Foo](jsonString)
}
} |
It would be nice if we could fix the problem for |
sure open an issue. Not sure how feasible it is to change though, we would lose the ordering guarantees that LinkedHashMap gives us which I'm not convinced is a good tradeoff for this edge case. But open an issue and we can discuss there |
Sub-quadratic decreasing of Scala 3 parser throughput when number of JSON object fields (with keys that have the same hash code) is increasing
On contemporary CPUs parsing of such JSON object (with a sequence of 100000 fields like below that is ~1.6Mb) can took more than 5 minutes for Scala 3 parser:
Below are results of the benchmark where
size
is a number of such fields:uPickle version
2.0.0
Scala version
3.2.1
JDK version
11+
Steps to reproduce
To run that benchmarks on your JDK:
sbt
and/or ensure that it already installed properly:jsoniter-scala
repo:The text was updated successfully, but these errors were encountered: