From ce1ae0eb8bfec1fc77a2c1c67b34ac1ea1eb327c Mon Sep 17 00:00:00 2001 From: Xiaoyan Lin Date: Tue, 3 May 2016 19:32:18 -0700 Subject: [PATCH] Handle the backslash with double quote in JsonObjectDecoder Motivation: The double quote may be escaped in a JSON string, but JsonObjectDecoder doesn't handle it. Resolves #5157. Modifications: Don't end a JSON string when processing an escaped double quote. Result: JsonObjectDecoder can handle backslash and double quote in a JSON string correctly. --- .../handler/codec/json/JsonObjectDecoder.java | 19 ++++++-- .../codec/json/JsonObjectDecoderTest.java | 45 +++++++++++++++++++ 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/codec/src/main/java/io/netty/handler/codec/json/JsonObjectDecoder.java b/codec/src/main/java/io/netty/handler/codec/json/JsonObjectDecoder.java index b791e41037..a34334b6c0 100644 --- a/codec/src/main/java/io/netty/handler/codec/json/JsonObjectDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/json/JsonObjectDecoder.java @@ -190,9 +190,22 @@ public class JsonObjectDecoder extends ByteToMessageDecoder { // also contain braces/brackets and that could lead to incorrect results. if (!insideString) { insideString = true; - // If the double quote wasn't escaped then this is the end of a string. - } else if (in.getByte(idx - 1) != '\\') { - insideString = false; + } else { + int backslashCount = 0; + idx--; + while (idx >= 0) { + if (in.getByte(idx) == '\\') { + backslashCount++; + idx--; + } else { + break; + } + } + // The double quote isn't escaped only if there are even "\"s. + if (backslashCount % 2 == 0) { + // Since the double quote isn't escaped then this is the end of a string. + insideString = false; + } } } } diff --git a/codec/src/test/java/io/netty/handler/codec/json/JsonObjectDecoderTest.java b/codec/src/test/java/io/netty/handler/codec/json/JsonObjectDecoderTest.java index 08ece60917..083b4eb1d4 100644 --- a/codec/src/test/java/io/netty/handler/codec/json/JsonObjectDecoderTest.java +++ b/codec/src/test/java/io/netty/handler/codec/json/JsonObjectDecoderTest.java @@ -87,6 +87,51 @@ public class JsonObjectDecoderTest { assertFalse(ch.finish()); } + @Test + public void testBackslashInString1() { + EmbeddedChannel ch = new EmbeddedChannel(new JsonObjectDecoder()); + // {"foo" : "bar\""} + String json = "{\"foo\" : \"bar\\\"\"}"; + System.out.println(json); + ch.writeInbound(Unpooled.copiedBuffer(json, CharsetUtil.UTF_8)); + + ByteBuf res = ch.readInbound(); + assertEquals(json, res.toString(CharsetUtil.UTF_8)); + res.release(); + + assertFalse(ch.finish()); + } + + @Test + public void testBackslashInString2() { + EmbeddedChannel ch = new EmbeddedChannel(new JsonObjectDecoder()); + // {"foo" : "bar\\"} + String json = "{\"foo\" : \"bar\\\\\"}"; + System.out.println(json); + ch.writeInbound(Unpooled.copiedBuffer(json, CharsetUtil.UTF_8)); + + ByteBuf res = ch.readInbound(); + assertEquals(json, res.toString(CharsetUtil.UTF_8)); + res.release(); + + assertFalse(ch.finish()); + } + + @Test + public void testBackslashInString3() { + EmbeddedChannel ch = new EmbeddedChannel(new JsonObjectDecoder()); + // {"foo" : "bar\\\""} + String json = "{\"foo\" : \"bar\\\\\\\"\"}"; + System.out.println(json); + ch.writeInbound(Unpooled.copiedBuffer(json, CharsetUtil.UTF_8)); + + ByteBuf res = ch.readInbound(); + assertEquals(json, res.toString(CharsetUtil.UTF_8)); + res.release(); + + assertFalse(ch.finish()); + } + @Test public void testMultipleJsonObjectsInOneWrite() { EmbeddedChannel ch = new EmbeddedChannel(new JsonObjectDecoder());