This is an automated email from the ASF dual-hosted git repository. rmannibucau pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/johnzon.git
The following commit(s) were added to refs/heads/master by this push: new 62ed694 [JOHNZON-216] ensure escaped characters don't break the parser and autoajust algorithm 62ed694 is described below commit 62ed6949eb3e2053c6ea6720ef0125004f20b89a Author: Romain Manni-Bucau <rmannibu...@gmail.com> AuthorDate: Tue Aug 4 08:56:24 2020 +0200 [JOHNZON-216] ensure escaped characters don't break the parser and autoajust algorithm --- .../apache/johnzon/core/JsonStreamParserImpl.java | 34 +++++++++++++--------- .../johnzon/core/JsonParserStreamingTest.java | 30 ++++++++++++++++--- .../org/apache/johnzon/core/JsonParserTest.java | 9 +++--- 3 files changed, 51 insertions(+), 22 deletions(-) diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonStreamParserImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonStreamParserImpl.java index bf4a2c0..3e75b5c 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonStreamParserImpl.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonStreamParserImpl.java @@ -160,6 +160,9 @@ public class JsonStreamParserImpl extends JohnzonJsonParserImpl implements JsonC //append a single char to the value buffer private void appendToCopyBuffer(final char c) { + if (fallBackCopyBufferLength >= fallBackCopyBuffer.length - 1) { + doAutoAdjust(1); + } fallBackCopyBuffer[fallBackCopyBufferLength++] = c; } @@ -173,19 +176,7 @@ public class JsonStreamParserImpl extends JohnzonJsonParserImpl implements JsonC } if (fallBackCopyBufferLength >= fallBackCopyBuffer.length - length) { // not good at runtime but handled - if (!autoAdjust) { - throw new ArrayIndexOutOfBoundsException("Buffer too small for such a long string"); - } - - final char[] newArray = new char[fallBackCopyBuffer.length + Math.max(getBufferExtends(fallBackCopyBuffer.length), length)]; - // TODO: log to adjust size once? - System.arraycopy(fallBackCopyBuffer, 0, newArray, 0, fallBackCopyBufferLength); - System.arraycopy(buffer, startOfValueInBuffer, newArray, fallBackCopyBufferLength, length); - if (releaseFallBackCopyBufferLength) { - bufferProvider.release(fallBackCopyBuffer); - releaseFallBackCopyBufferLength = false; - } - fallBackCopyBuffer = newArray; + doAutoAdjust(length); } else { System.arraycopy(buffer, startOfValueInBuffer, fallBackCopyBuffer, fallBackCopyBufferLength, length); } @@ -195,6 +186,22 @@ public class JsonStreamParserImpl extends JohnzonJsonParserImpl implements JsonC startOfValueInBuffer = endOfValueInBuffer = -1; } + private void doAutoAdjust(final int length) { + if (!autoAdjust) { + throw new ArrayIndexOutOfBoundsException("Buffer too small for such a long string"); + } + + final char[] newArray = new char[fallBackCopyBuffer.length + Math.max(getBufferExtends(fallBackCopyBuffer.length), length)]; + // TODO: log to adjust size once? + System.arraycopy(fallBackCopyBuffer, 0, newArray, 0, fallBackCopyBufferLength); + System.arraycopy(buffer, startOfValueInBuffer, newArray, fallBackCopyBufferLength, length); + if (releaseFallBackCopyBufferLength) { + bufferProvider.release(fallBackCopyBuffer); + releaseFallBackCopyBufferLength = false; + } + fallBackCopyBuffer = newArray; + } + /** * @return the amount of bytes the current buffer should get extended with */ @@ -614,7 +621,6 @@ public class JsonStreamParserImpl extends JohnzonJsonParserImpl implements JsonC //another escape chars, for example \t } else { appendToCopyBuffer(Strings.asEscapedChar(n)); - } } else { diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserStreamingTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserStreamingTest.java index 2cc5d21..dfdff4e 100644 --- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserStreamingTest.java +++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserStreamingTest.java @@ -18,17 +18,39 @@ */ package org.apache.johnzon.core; -import java.io.StringReader; -import java.util.stream.Collectors; +import org.junit.Test; import javax.json.Json; import javax.json.stream.JsonParser; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringReader; +import java.nio.charset.StandardCharsets; +import java.util.stream.Collectors; +import java.util.stream.IntStream; -import org.junit.Test; - +import static java.util.stream.Collectors.joining; import static org.junit.Assert.assertEquals; public class JsonParserStreamingTest { + @Test + public void parseEscapeCharacters() throws IOException { + final int len = 8192; + final byte[] bytes = ("{\"source\":\"" + + IntStream.range(0, 16558).mapToObj(it -> "\\").collect(joining("")) + + "\t\"}").getBytes(StandardCharsets.UTF_8); + + final BufferStrategy.BufferProvider<char[]> bs = BufferStrategyFactory.valueOf("QUEUE").newCharProvider(len); + try (final InputStream stream = new ByteArrayInputStream(bytes)) { + final JsonStreamParserImpl impl = new JsonStreamParserImpl(stream, len, bs, bs, false); + while (impl.hasNext()) { + impl.next(); + } + } catch (final ArrayIndexOutOfBoundsException aioobe) { + assertEquals("Buffer too small for such a long string", aioobe.getMessage()); + } + } @Test public void testArrayStream() { diff --git a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserTest.java b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserTest.java index bbc8d71..d388f5f 100644 --- a/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserTest.java +++ b/johnzon-core/src/test/java/org/apache/johnzon/core/JsonParserTest.java @@ -32,6 +32,7 @@ import java.io.StringReader; import java.math.BigDecimal; import java.math.BigInteger; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -57,10 +58,10 @@ import org.junit.Test; public class JsonParserTest { - static final Charset UTF_8 = Charset.forName("UTF-8"); - static final Charset UTF_16BE = Charset.forName("UTF-16BE"); - static final Charset UTF_16LE = Charset.forName("UTF-16LE"); - static final Charset UTF_16 = Charset.forName("UTF-16"); + static final Charset UTF_8 = StandardCharsets.UTF_8; + static final Charset UTF_16BE = StandardCharsets.UTF_16BE; + static final Charset UTF_16LE = StandardCharsets.UTF_16LE; + static final Charset UTF_16 = StandardCharsets.UTF_16; static final Charset UTF_32LE = Charset.forName("UTF-32LE"); static final Charset UTF_32BE = Charset.forName("UTF-32BE");