diff --git a/akka-stream-tests/src/test/scala/akka/stream/scaladsl/JsonFramingSpec.scala b/akka-stream-tests/src/test/scala/akka/stream/scaladsl/JsonFramingSpec.scala index 06c97a1601..0bb19b0c7f 100644 --- a/akka-stream-tests/src/test/scala/akka/stream/scaladsl/JsonFramingSpec.scala +++ b/akka-stream-tests/src/test/scala/akka/stream/scaladsl/JsonFramingSpec.scala @@ -267,6 +267,36 @@ class JsonFramingSpec extends AkkaSpec { | } |}""".stripMargin } + + "successfully parse an escaped backslash followed by a double quote" in { + val buffer = new JsonObjectParser() + buffer.offer(ByteString( + """ + |{ + | "key": "\\" + | } + | """.stripMargin + )) + + buffer.poll().get.utf8String shouldBe """{ + | "key": "\\" + | }""".stripMargin + } + + "successfully parse a string that contains an escaped quote" in { + val buffer = new JsonObjectParser() + buffer.offer(ByteString( + """ + |{ + | "key": "\"" + | } + | """.stripMargin + )) + + buffer.poll().get.utf8String shouldBe """{ + | "key": "\"" + | }""".stripMargin + } } "has nested array" should { diff --git a/akka-stream/src/main/scala/akka/stream/impl/JsonObjectParser.scala b/akka-stream/src/main/scala/akka/stream/impl/JsonObjectParser.scala index f35895ef1b..4e03e02133 100644 --- a/akka-stream/src/main/scala/akka/stream/impl/JsonObjectParser.scala +++ b/akka-stream/src/main/scala/akka/stream/impl/JsonObjectParser.scala @@ -55,6 +55,7 @@ private[akka] class JsonObjectParser(maximumObjectLength: Int = Int.MaxValue) { private var completedObject = false private var inStringExpression = false private var isStartOfEscapeSequence = false + private var lastInput = 0.toByte /** * Appends input ByteString to internal byte string buffer. @@ -105,7 +106,7 @@ private[akka] class JsonObjectParser(maximumObjectLength: Int = Int.MaxValue) { completedObject } - private def proceed(input: Byte): Unit = + private def proceed(input: Byte): Unit = { if (input == SquareBraceStart && outsideObject) { // outer object is an array pos += 1 @@ -118,7 +119,8 @@ private[akka] class JsonObjectParser(maximumObjectLength: Int = Int.MaxValue) { pos += 1 trimFront += 1 } else if (input == Backslash) { - isStartOfEscapeSequence = true + if (lastInput == Backslash) isStartOfEscapeSequence = false + else isStartOfEscapeSequence = true pos += 1 } else if (input == DoubleQuote) { if (!isStartOfEscapeSequence) inStringExpression = !inStringExpression @@ -146,6 +148,9 @@ private[akka] class JsonObjectParser(maximumObjectLength: Int = Int.MaxValue) { throw new FramingException(s"Invalid JSON encountered at position [$pos] of [$buffer]") } + lastInput = input + } + @inline private final def insideObject: Boolean = !outsideObject