summaryrefslogtreecommitdiff
path: root/src/main/scala/spray/json/JsonParser.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/spray/json/JsonParser.scala')
-rw-r--r--src/main/scala/spray/json/JsonParser.scala42
1 files changed, 24 insertions, 18 deletions
diff --git a/src/main/scala/spray/json/JsonParser.scala b/src/main/scala/spray/json/JsonParser.scala
index ded8d6a..4a723b5 100644
--- a/src/main/scala/spray/json/JsonParser.scala
+++ b/src/main/scala/spray/json/JsonParser.scala
@@ -48,7 +48,7 @@ class JsonParser(input: ParserInput, settings: JsonParserSettings = JsonParserSe
def parseJsValue(allowTrailingInput: Boolean): JsValue = {
ws()
- `value`()
+ `value`(settings.maxDepth)
if (!allowTrailingInput)
require(EOI)
jsValue
@@ -59,27 +59,33 @@ class JsonParser(input: ParserInput, settings: JsonParserSettings = JsonParserSe
private final val EOI = '\uFFFF' // compile-time constant
// http://tools.ietf.org/html/rfc4627#section-2.1
- private def `value`(): Unit = {
- val mark = input.cursor
- def simpleValue(matched: Boolean, value: JsValue) = if (matched) jsValue = value else fail("JSON Value", mark)
- (cursorChar: @switch) match {
- case 'f' => simpleValue(`false`(), JsFalse)
- case 'n' => simpleValue(`null`(), JsNull)
- case 't' => simpleValue(`true`(), JsTrue)
- case '{' => advance(); `object`()
- case '[' => advance(); `array`()
- case '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '-' => `number`()
- case '"' => `string`(); jsValue = if (sb.length == 0) JsString.empty else JsString(sb.toString)
- case _ => fail("JSON Value")
+ private def `value`(remainingNesting: Int): Unit =
+ if (remainingNesting == 0)
+ throw new ParsingException(
+ "JSON input nested too deeply",
+ s"JSON input was nested more deeply than the configured limit of maxNesting = ${settings.maxDepth}"
+ )
+ else {
+ val mark = input.cursor
+ def simpleValue(matched: Boolean, value: JsValue) = if (matched) jsValue = value else fail("JSON Value", mark)
+ (cursorChar: @switch) match {
+ case 'f' => simpleValue(`false`(), JsFalse)
+ case 'n' => simpleValue(`null`(), JsNull)
+ case 't' => simpleValue(`true`(), JsTrue)
+ case '{' => advance(); `object`(remainingNesting)
+ case '[' => advance(); `array`(remainingNesting)
+ case '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '-' => `number`()
+ case '"' => `string`(); jsValue = if (sb.length == 0) JsString.empty else JsString(sb.toString)
+ case _ => fail("JSON Value")
+ }
}
- }
private def `false`() = advance() && ch('a') && ch('l') && ch('s') && ws('e')
private def `null`() = advance() && ch('u') && ch('l') && ws('l')
private def `true`() = advance() && ch('r') && ch('u') && ws('e')
// http://tools.ietf.org/html/rfc4627#section-2.2
- private def `object`(): Unit = {
+ private def `object`(remainingNesting: Int): Unit = {
ws()
jsValue = if (cursorChar != '}') {
@tailrec def members(map: Map[String, JsValue]): Map[String, JsValue] = {
@@ -87,7 +93,7 @@ class JsonParser(input: ParserInput, settings: JsonParserSettings = JsonParserSe
require(':')
ws()
val key = sb.toString
- `value`()
+ `value`(remainingNesting - 1)
val nextMap = map.updated(key, jsValue)
if (ws(',')) members(nextMap) else nextMap
}
@@ -102,12 +108,12 @@ class JsonParser(input: ParserInput, settings: JsonParserSettings = JsonParserSe
}
// http://tools.ietf.org/html/rfc4627#section-2.3
- private def `array`(): Unit = {
+ private def `array`(remainingNesting: Int): Unit = {
ws()
jsValue = if (cursorChar != ']') {
val list = Vector.newBuilder[JsValue]
@tailrec def values(): Unit = {
- `value`()
+ `value`(remainingNesting - 1)
list += jsValue
if (ws(',')) values()
}