Skip to content

Commit

Permalink
Merge pull request #235 from sphereio/avoid_denial_service_big_number
Browse files Browse the repository at this point in the history
avoid denial of service with big numbers
  • Loading branch information
yanns authored Sep 29, 2020
2 parents b6f711d + 531b820 commit 32599fa
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 8 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package io.sphere.json

import com.fasterxml.jackson.databind.DeserializationFeature.{USE_BIG_DECIMAL_FOR_FLOATS, USE_BIG_INTEGER_FOR_INTS}
import com.fasterxml.jackson.databind.ObjectMapper
import org.json4s.jackson.{Json4sScalaModule, JsonMethods}

// extends the default JsonMethods to configure a different default jackson parser
private object SphereJsonParser extends JsonMethods {
override val mapper: ObjectMapper = {
val m = new ObjectMapper()
m.registerModule(new Json4sScalaModule)
m.configure(USE_BIG_INTEGER_FOR_INTS, false)
m.configure(USE_BIG_DECIMAL_FOR_FLOATS, false)
m
}
}
6 changes: 3 additions & 3 deletions json/json-core/src/main/scala/io/sphere/json/ToJSON.scala
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ object ToJSON {
}

implicit val intWriter: ToJSON[Int] = new ToJSON[Int] {
def write(i: Int): JValue = JInt(i)
def write(i: Int): JValue = JLong(i)
}

implicit val stringWriter: ToJSON[String] = new ToJSON[String] {
Expand All @@ -71,11 +71,11 @@ object ToJSON {
}

implicit val shortWriter: ToJSON[Short] = new ToJSON[Short] {
def write(s: Short): JValue = JInt(s)
def write(s: Short): JValue = JLong(s)
}

implicit val longWriter: ToJSON[Long] = new ToJSON[Long] {
def write(l: Long): JValue = JInt(l)
def write(l: Long): JValue = JLong(l)
}

implicit val floatWriter: ToJSON[Float] = new ToJSON[Float] {
Expand Down
5 changes: 3 additions & 2 deletions json/json-core/src/main/scala/io/sphere/json/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package io.sphere
import cats.data.Validated.{Invalid, Valid}
import cats.data.{NonEmptyList, ValidatedNel}
import com.fasterxml.jackson.core.JsonParseException
import com.fasterxml.jackson.core.exc.InputCoercionException
import com.fasterxml.jackson.databind.JsonMappingException

import io.sphere.util.Logging
import org.json4s.{DefaultFormats, JsonInput, StringInput}
import org.json4s.JsonAST._
Expand All @@ -19,10 +19,11 @@ package object json extends Logging {
type JValidation[A] = ValidatedNel[JSONError, A]

def parseJSON(json: JsonInput): JValidation[JValue] =
try Valid(parseJson(json)) catch {
try Valid(SphereJsonParser.parse(json, useBigDecimalForDouble = false, useBigIntForLong = false)) catch {
case e: ParseException => jsonParseError(e.getMessage)
case e: JsonMappingException => jsonParseError(e.getOriginalMessage)
case e: JsonParseException => jsonParseError(e.getOriginalMessage)
case e: InputCoercionException => jsonParseError(e.getOriginalMessage)
}

def parseJSON(json: String): JValidation[JValue] =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.sphere.json

import org.scalatest.matchers.should.Matchers
import org.scalatest.wordspec.AnyWordSpec

class BigNumberParsingSpec extends AnyWordSpec with Matchers {
import BigNumberParsingSpec._

"parsing a big number" should {
"not take much time when parsed as Double" in {
fromJSON[Double](bigNumberAsString).isValid should be (false)
}
"not take much time when parsed as Long" in {
fromJSON[Long](bigNumberAsString).isValid should be (false)
}
"not take much time when parsed as Int" in {
fromJSON[Int](bigNumberAsString).isValid should be (false)
}
}
}

object BigNumberParsingSpec {
private val bigNumberAsString = "9" * 10000000
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class ToJSONSpec extends AnyWordSpec with Matchers {
json must be (JObject(List(
"id" -> JString(id.toString),
"first_name" -> JString("bidule"),
"age" -> JInt(109)
"age" -> JLong(109)
)))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class ForProductNSpec extends AnyWordSpec with Matchers {
json must be (JObject(List(
"id" -> JString(id.toString),
"first_name" -> JString("bidule"),
"age" -> JInt(109)
"age" -> JLong(109)
)))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class TypesSwitchSpec extends AnyWordSpec with Matchers {

val jsons = m.map(Message.json.write)
jsons must be (List(
JObject("number" -> JInt(23), "type" -> JString("ClassA1")),
JObject("number" -> JLong(23), "type" -> JString("ClassA1")),
JObject("name" -> JString("world"), "type" -> JString("ClassA2")),
JObject("valid" -> JBool(false), "type" -> JString("ClassB1")),
JObject("references" -> JArray(List(JString("a23"), JString("c62"))), "type" -> JString("ClassB2"))))
Expand Down

0 comments on commit 32599fa

Please sign in to comment.