From 231e6a5b7d92a7455b5c64f8e4a71a6fcc73cfd1 Mon Sep 17 00:00:00 2001 From: Andrew McCall Date: Fri, 23 Dec 2016 21:10:26 +0000 Subject: [PATCH] Calls to discardSomeReadBytes() causes the JsonDecoder to get corrupted Modification: Added a lastReaderIndex value and if the current readerIndex has been reset, resets the idx and the decoder. Result: Fixes #6156. --- .../handler/codec/json/JsonObjectDecoder.java | 8 +++++ .../codec/json/JsonObjectDecoderTest.java | 32 +++++++++++++++++++ 2 files changed, 40 insertions(+) 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 7af1d74646..cd5db99ff7 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 @@ -45,6 +45,8 @@ public class JsonObjectDecoder extends ByteToMessageDecoder { private int openBraces; private int idx; + private int lastReaderIndex; + private int state; private boolean insideString; @@ -88,6 +90,11 @@ public class JsonObjectDecoder extends ByteToMessageDecoder { return; } + if (this.idx > in.readerIndex() && lastReaderIndex != in.readerIndex()) { + this.idx = in.readerIndex(); + reset(); + } + // index of next byte to process. int idx = this.idx; int wrtIdx = in.writerIndex(); @@ -170,6 +177,7 @@ public class JsonObjectDecoder extends ByteToMessageDecoder { } else { this.idx = idx; } + this.lastReaderIndex = in.readerIndex(); } /** 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 083b4eb1d4..e1f28a5794 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 @@ -276,4 +276,36 @@ public class JsonObjectDecoderTest { assertFalse(ch.finish()); } + + @Test + public void testCorruptedFrameException() { + final String part1 = "{\"a\":{\"b\":{\"c\":{ \"d\":\"27301\", \"med\":\"d\", \"path\":\"27310\"} }," + + " \"status\":\"OK\" } }{\""; + final String part2 = "a\":{\"b\":{\"c\":{\"ory\":[{\"competi\":[{\"event\":[{" + "\"externalI\":{\"external\"" + + ":[{\"id\":\"O\"} ]"; + + EmbeddedChannel ch = new EmbeddedChannel(new JsonObjectDecoder()); + + ByteBuf res; + + ch.writeInbound(Unpooled.copiedBuffer(part1, CharsetUtil.UTF_8)); + res = ch.readInbound(); + assertEquals("{\"a\":{\"b\":{\"c\":{ \"d\":\"27301\", \"med\":\"d\", \"path\":\"27310\"} }, " + + "\"status\":\"OK\" } }", res.toString(CharsetUtil.UTF_8)); + res.release(); + + ch.writeInbound(Unpooled.copiedBuffer(part2, CharsetUtil.UTF_8)); + res = ch.readInbound(); + + assertNull(res); + + ch.writeInbound(Unpooled.copiedBuffer("}}]}]}]}}}}", CharsetUtil.UTF_8)); + res = ch.readInbound(); + + assertEquals("{\"a\":{\"b\":{\"c\":{\"ory\":[{\"competi\":[{\"event\":[{" + "\"externalI\":{" + + "\"external\":[{\"id\":\"O\"} ]}}]}]}]}}}}", res.toString(CharsetUtil.UTF_8)); + res.release(); + + assertFalse(ch.finish()); + } }