From 267db9886968001fda58483fd07d16512761de8e Mon Sep 17 00:00:00 2001 From: UFA-MOROZOV <74819600+UFA-MOROZOV@users.noreply.github.com> Date: Mon, 23 Sep 2024 13:26:39 +0300 Subject: [PATCH 1/4] Update ChunkedInputStream.java --- src/main/java/org/takes/rq/ChunkedInputStream.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/takes/rq/ChunkedInputStream.java b/src/main/java/org/takes/rq/ChunkedInputStream.java index b77ee1b99..eb165d44c 100644 --- a/src/main/java/org/takes/rq/ChunkedInputStream.java +++ b/src/main/java/org/takes/rq/ChunkedInputStream.java @@ -109,7 +109,12 @@ public int read(final byte[] buf, final int off, final int len) if (shift == len) { result = len; } else { - result = shift + this.read(buf, off + shift, len - shift); + int nextRead = this.read(buf, off + shift, len - shift); + if (nextRead < 1) { + result = shift; + } else { + result = shift + nextRead; + } } } return result; From 8d8bc993e31427cd36772361f844ac0ca2f2edbd Mon Sep 17 00:00:00 2001 From: UFA-MOROZOV <74819600+UFA-MOROZOV@users.noreply.github.com> Date: Tue, 1 Oct 2024 18:46:02 +0300 Subject: [PATCH 2/4] Update ChunkedInputStreamTest.java --- .../org/takes/rq/ChunkedInputStreamTest.java | 103 +++++++++++------- 1 file changed, 63 insertions(+), 40 deletions(-) diff --git a/src/test/java/org/takes/rq/ChunkedInputStreamTest.java b/src/test/java/org/takes/rq/ChunkedInputStreamTest.java index e16b345b5..1952bbb8f 100644 --- a/src/test/java/org/takes/rq/ChunkedInputStreamTest.java +++ b/src/test/java/org/takes/rq/ChunkedInputStreamTest.java @@ -54,21 +54,21 @@ void readsOneChunk() throws IOException { final String data = "1234567890abcdef"; final String length = Integer.toHexString(data.length()); final InputStream stream = new ChunkedInputStream( - IOUtils.toInputStream( - new Joined( - ChunkedInputStreamTest.CRLF, - length, - data, - ChunkedInputStreamTest.END_OF_CHUNK, - "" - ).toString(), - StandardCharsets.UTF_8 - ) + IOUtils.toInputStream( + new Joined( + ChunkedInputStreamTest.CRLF, + length, + data, + ChunkedInputStreamTest.END_OF_CHUNK, + "" + ).toString(), + StandardCharsets.UTF_8 + ) ); final byte[] buf = new byte[data.length()]; MatcherAssert.assertThat( - stream.read(buf), - Matchers.equalTo(data.length()) + stream.read(buf), + Matchers.equalTo(data.length()) ); MatcherAssert.assertThat(buf, Matchers.equalTo(data.getBytes())); MatcherAssert.assertThat(stream.available(), Matchers.equalTo(0)); @@ -83,25 +83,25 @@ void readsManyChunks() throws IOException { final String data = first + second + third; final Integer length = data.length(); final InputStream stream = new ChunkedInputStream( - IOUtils.toInputStream( - new Joined( - ChunkedInputStreamTest.CRLF, - Integer.toHexString(first.length()), - first, - Integer.toHexString(second.length()), - second, - Integer.toHexString(third.length()), - third, - ChunkedInputStreamTest.END_OF_CHUNK, - "" - ).toString(), - StandardCharsets.UTF_8 - ) + IOUtils.toInputStream( + new Joined( + ChunkedInputStreamTest.CRLF, + Integer.toHexString(first.length()), + first, + Integer.toHexString(second.length()), + second, + Integer.toHexString(third.length()), + third, + ChunkedInputStreamTest.END_OF_CHUNK, + "" + ).toString(), + StandardCharsets.UTF_8 + ) ); final byte[] buf = new byte[length]; MatcherAssert.assertThat( - stream.read(buf), - Matchers.equalTo(length) + stream.read(buf), + Matchers.equalTo(length) ); MatcherAssert.assertThat(buf, Matchers.equalTo(data.getBytes())); MatcherAssert.assertThat(stream.available(), Matchers.equalTo(0)); @@ -114,24 +114,47 @@ void ignoresParameterAfterSemiColon() throws IOException { final String ignored = ";ignored-stuff"; final String length = Integer.toHexString(data.length()); final InputStream stream = new ChunkedInputStream( - IOUtils.toInputStream( - new Joined( - ChunkedInputStreamTest.CRLF, - length + ignored, - data, - ChunkedInputStreamTest.END_OF_CHUNK, - "" - ).toString(), - StandardCharsets.UTF_8 - ) + IOUtils.toInputStream( + new Joined( + ChunkedInputStreamTest.CRLF, + length + ignored, + data, + ChunkedInputStreamTest.END_OF_CHUNK, + "" + ).toString(), + StandardCharsets.UTF_8 + ) ); final byte[] buf = new byte[data.length()]; MatcherAssert.assertThat( - stream.read(buf), - Matchers.equalTo(data.length()) + stream.read(buf), + Matchers.equalTo(data.length()) ); MatcherAssert.assertThat(buf, Matchers.equalTo(data.getBytes())); MatcherAssert.assertThat(stream.available(), Matchers.equalTo(0)); stream.close(); } + @Test + void readsWithLenGreaterThanTotalSize() throws IOException { + final String data = "Hello, World!"; + final String length = Integer.toHexString(data.length()); + final InputStream stream = new ChunkedInputStream( + IOUtils.toInputStream( + new Joined( + ChunkedInputStreamTest.CRLF, + length, + data, + ChunkedInputStreamTest.END_OF_CHUNK, + "" + ).toString(), + StandardCharsets.UTF_8 + ) + ); + final byte[] buf = new byte[data.length() + 10]; + final int bytesRead = stream.read(buf); + MatcherAssert.assertThat(bytesRead, Matchers.equalTo(data.length())); + MatcherAssert.assertThat(buf, Matchers.equalTo((data + new String(new byte[10])).getBytes())); + MatcherAssert.assertThat(stream.available(), Matchers.equalTo(0)); + stream.close(); + } } From fd7240a06f8428d13b20d360fc898342e244fc3f Mon Sep 17 00:00:00 2001 From: UFA-MOROZOV Date: Wed, 2 Oct 2024 07:35:47 +0300 Subject: [PATCH 3/4] redacted code --- .../java/org/takes/rq/ChunkedInputStream.java | 23 ++-- .../org/takes/rq/ChunkedInputStreamTest.java | 112 +++++++++--------- 2 files changed, 75 insertions(+), 60 deletions(-) diff --git a/src/main/java/org/takes/rq/ChunkedInputStream.java b/src/main/java/org/takes/rq/ChunkedInputStream.java index eb165d44c..b84f28c60 100644 --- a/src/main/java/org/takes/rq/ChunkedInputStream.java +++ b/src/main/java/org/takes/rq/ChunkedInputStream.java @@ -38,8 +38,8 @@ /** * Input stream from chunked coded http request body. * - * @since 0.31.2 * @link Chunked Transfer Coding + * @since 0.31.2 */ final class ChunkedInputStream extends InputStream { @@ -70,6 +70,7 @@ final class ChunkedInputStream extends InputStream { /** * Ctor. + * * @param stream The raw input stream */ ChunkedInputStream(final InputStream stream) { @@ -109,12 +110,13 @@ public int read(final byte[] buf, final int off, final int len) if (shift == len) { result = len; } else { - int nextRead = this.read(buf, off + shift, len - shift); - if (nextRead < 1) { - result = shift; - } else { - result = shift + nextRead; - } + result = shift + Math.max( + this.read( + buf, + off + shift, + len - shift + ), 0 + ); } } return result; @@ -127,6 +129,7 @@ public int read(final byte[] buf) throws IOException { /** * Read the CRLF terminator. + * * @throws IOException If an IO error occurs. */ private void readCrlf() throws IOException { @@ -147,6 +150,7 @@ private void readCrlf() throws IOException { /** * Read the next chunk. + * * @throws IOException If an IO error occurs. */ private void nextChunk() throws IOException { @@ -165,6 +169,7 @@ private void nextChunk() throws IOException { * Expects the stream to start with a chunksize in hex with optional * comments after a semicolon. The line must end with a CRLF: "a3; some * comment\r\n" Positions the stream at the start of the next line. + * * @param stream The new input stream. * @return The chunk size as integer * @throws IOException when the chunk size could not be parsed @@ -225,6 +230,7 @@ private enum State { /** * Extract line with chunk size from stream. + * * @param stream Input stream. * @return Line with chunk size. * @throws IOException If fails. @@ -241,6 +247,7 @@ private static ByteArrayOutputStream sizeLine(final InputStream stream) /** * Get next state for FSM. + * * @param stream Input stream. * @param state Current state. * @param line Current chunk size line. @@ -282,6 +289,7 @@ private static State next(final InputStream stream, final State state, /** * Maintain next symbol for current state = State.NORMAL. + * * @param state Current state. * @param line Current chunk size line. * @param next Next symbol. @@ -307,6 +315,7 @@ private static State nextNormal(final State state, /** * Maintain next symbol for current state = State.QUOTED_STRING. + * * @param stream Input stream. * @param state Current state. * @param line Current chunk size line. diff --git a/src/test/java/org/takes/rq/ChunkedInputStreamTest.java b/src/test/java/org/takes/rq/ChunkedInputStreamTest.java index 1952bbb8f..2d958cdcd 100644 --- a/src/test/java/org/takes/rq/ChunkedInputStreamTest.java +++ b/src/test/java/org/takes/rq/ChunkedInputStreamTest.java @@ -54,21 +54,21 @@ void readsOneChunk() throws IOException { final String data = "1234567890abcdef"; final String length = Integer.toHexString(data.length()); final InputStream stream = new ChunkedInputStream( - IOUtils.toInputStream( - new Joined( - ChunkedInputStreamTest.CRLF, - length, - data, - ChunkedInputStreamTest.END_OF_CHUNK, - "" - ).toString(), - StandardCharsets.UTF_8 - ) + IOUtils.toInputStream( + new Joined( + ChunkedInputStreamTest.CRLF, + length, + data, + ChunkedInputStreamTest.END_OF_CHUNK, + "" + ).toString(), + StandardCharsets.UTF_8 + ) ); final byte[] buf = new byte[data.length()]; MatcherAssert.assertThat( - stream.read(buf), - Matchers.equalTo(data.length()) + stream.read(buf), + Matchers.equalTo(data.length()) ); MatcherAssert.assertThat(buf, Matchers.equalTo(data.getBytes())); MatcherAssert.assertThat(stream.available(), Matchers.equalTo(0)); @@ -83,25 +83,25 @@ void readsManyChunks() throws IOException { final String data = first + second + third; final Integer length = data.length(); final InputStream stream = new ChunkedInputStream( - IOUtils.toInputStream( - new Joined( - ChunkedInputStreamTest.CRLF, - Integer.toHexString(first.length()), - first, - Integer.toHexString(second.length()), - second, - Integer.toHexString(third.length()), - third, - ChunkedInputStreamTest.END_OF_CHUNK, - "" - ).toString(), - StandardCharsets.UTF_8 - ) + IOUtils.toInputStream( + new Joined( + ChunkedInputStreamTest.CRLF, + Integer.toHexString(first.length()), + first, + Integer.toHexString(second.length()), + second, + Integer.toHexString(third.length()), + third, + ChunkedInputStreamTest.END_OF_CHUNK, + "" + ).toString(), + StandardCharsets.UTF_8 + ) ); final byte[] buf = new byte[length]; MatcherAssert.assertThat( - stream.read(buf), - Matchers.equalTo(length) + stream.read(buf), + Matchers.equalTo(length) ); MatcherAssert.assertThat(buf, Matchers.equalTo(data.getBytes())); MatcherAssert.assertThat(stream.available(), Matchers.equalTo(0)); @@ -114,46 +114,52 @@ void ignoresParameterAfterSemiColon() throws IOException { final String ignored = ";ignored-stuff"; final String length = Integer.toHexString(data.length()); final InputStream stream = new ChunkedInputStream( - IOUtils.toInputStream( - new Joined( - ChunkedInputStreamTest.CRLF, - length + ignored, - data, - ChunkedInputStreamTest.END_OF_CHUNK, - "" - ).toString(), - StandardCharsets.UTF_8 - ) + IOUtils.toInputStream( + new Joined( + ChunkedInputStreamTest.CRLF, + length + ignored, + data, + ChunkedInputStreamTest.END_OF_CHUNK, + "" + ).toString(), + StandardCharsets.UTF_8 + ) ); final byte[] buf = new byte[data.length()]; MatcherAssert.assertThat( - stream.read(buf), - Matchers.equalTo(data.length()) + stream.read(buf), + Matchers.equalTo(data.length()) ); MatcherAssert.assertThat(buf, Matchers.equalTo(data.getBytes())); MatcherAssert.assertThat(stream.available(), Matchers.equalTo(0)); stream.close(); } + @Test void readsWithLenGreaterThanTotalSize() throws IOException { final String data = "Hello, World!"; final String length = Integer.toHexString(data.length()); final InputStream stream = new ChunkedInputStream( - IOUtils.toInputStream( - new Joined( - ChunkedInputStreamTest.CRLF, - length, - data, - ChunkedInputStreamTest.END_OF_CHUNK, - "" - ).toString(), - StandardCharsets.UTF_8 - ) + IOUtils.toInputStream( + new Joined( + ChunkedInputStreamTest.CRLF, + length, + data, + ChunkedInputStreamTest.END_OF_CHUNK, + "" + ).toString(), + StandardCharsets.UTF_8 + ) ); final byte[] buf = new byte[data.length() + 10]; - final int bytesRead = stream.read(buf); - MatcherAssert.assertThat(bytesRead, Matchers.equalTo(data.length())); - MatcherAssert.assertThat(buf, Matchers.equalTo((data + new String(new byte[10])).getBytes())); + MatcherAssert.assertThat( + stream.read(buf), + Matchers.equalTo(data.length()) + ); + MatcherAssert.assertThat( + buf, + Matchers.equalTo((data + new String(new byte[10])).getBytes()) + ); MatcherAssert.assertThat(stream.available(), Matchers.equalTo(0)); stream.close(); } From 98a23898bd8f01a767f87e781595fb8b61739f3d Mon Sep 17 00:00:00 2001 From: UFA-MOROZOV Date: Wed, 2 Oct 2024 07:38:42 +0300 Subject: [PATCH 4/4] redacted code --- src/main/java/org/takes/rq/ChunkedInputStream.java | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/main/java/org/takes/rq/ChunkedInputStream.java b/src/main/java/org/takes/rq/ChunkedInputStream.java index b84f28c60..0dee6bcbf 100644 --- a/src/main/java/org/takes/rq/ChunkedInputStream.java +++ b/src/main/java/org/takes/rq/ChunkedInputStream.java @@ -37,7 +37,6 @@ /** * Input stream from chunked coded http request body. - * * @link Chunked Transfer Coding * @since 0.31.2 */ @@ -129,7 +128,6 @@ public int read(final byte[] buf) throws IOException { /** * Read the CRLF terminator. - * * @throws IOException If an IO error occurs. */ private void readCrlf() throws IOException { @@ -150,7 +148,6 @@ private void readCrlf() throws IOException { /** * Read the next chunk. - * * @throws IOException If an IO error occurs. */ private void nextChunk() throws IOException { @@ -169,7 +166,6 @@ private void nextChunk() throws IOException { * Expects the stream to start with a chunksize in hex with optional * comments after a semicolon. The line must end with a CRLF: "a3; some * comment\r\n" Positions the stream at the start of the next line. - * * @param stream The new input stream. * @return The chunk size as integer * @throws IOException when the chunk size could not be parsed @@ -230,7 +226,6 @@ private enum State { /** * Extract line with chunk size from stream. - * * @param stream Input stream. * @return Line with chunk size. * @throws IOException If fails. @@ -247,7 +242,6 @@ private static ByteArrayOutputStream sizeLine(final InputStream stream) /** * Get next state for FSM. - * * @param stream Input stream. * @param state Current state. * @param line Current chunk size line. @@ -289,7 +283,6 @@ private static State next(final InputStream stream, final State state, /** * Maintain next symbol for current state = State.NORMAL. - * * @param state Current state. * @param line Current chunk size line. * @param next Next symbol. @@ -315,7 +308,6 @@ private static State nextNormal(final State state, /** * Maintain next symbol for current state = State.QUOTED_STRING. - * * @param stream Input stream. * @param state Current state. * @param line Current chunk size line.