diff options
Diffstat (limited to 'src/main/scala/spray/json/JsonParser.scala')
-rw-r--r-- | src/main/scala/spray/json/JsonParser.scala | 42 |
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 f29c062..9fe8a72 100644 --- a/src/main/scala/spray/json/JsonParser.scala +++ b/src/main/scala/spray/json/JsonParser.scala @@ -46,7 +46,7 @@ class JsonParser(input: ParserInput, settings: JsonParserSettings = JsonParserSe def parseJsValue(allowTrailingInput: Boolean): JsValue = { ws() - `value`() + `value`(settings.maxDepth) if (!allowTrailingInput) require(EOI) jsValue @@ -57,27 +57,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] = { @@ -85,7 +91,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 } @@ -101,12 +107,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() } |