From 786cb9c2fe5bdaa620c461cf19bcbee220e577a9 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Thu, 31 Jan 2019 20:27:47 +0100 Subject: [PATCH 1/7] =?UTF-8?q?HttpObjectDecoder=20ignores=20HTTP=20traile?= =?UTF-8?q?r=20header=20when=20empty=20line=20is=20rece=E2=80=A6=20(#8799)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * HttpObjectDecoder ignores HTTP trailer header when empty line is received in seperate ByteBuf Motivation: When the empty line that termines the trailers was sent in a seperate ByteBuf we did ignore the previous parsed trailers and just returned none. Modifications: - Correct respect previous parsed trailers. - Add unit test. Result: Fixes https://github.com/netty/netty/issues/8736 (cherry picked from commit 91d3920aa298ea536be7b196f16b32b6ddd27f8d) --- .../handler/codec/http/HttpObjectDecoder.java | 75 ++++++++++--------- .../codec/http/HttpResponseDecoderTest.java | 29 +++++++ 2 files changed, 67 insertions(+), 37 deletions(-) diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java index af1d642a0397..f8220cdb04eb 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java @@ -640,49 +640,50 @@ private LastHttpContent readTrailingHeaders(ByteBuf buffer) { if (line == null) { return null; } + LastHttpContent trailer = this.trailer; + if (line.length() == 0 && trailer == null) { + // We have received the empty line which signals the trailer is complete and did not parse any trailers + // before. Just return an empty last content to reduce allocations. + return LastHttpContent.EMPTY_LAST_CONTENT; + } + CharSequence lastHeader = null; - if (line.length() > 0) { - LastHttpContent trailer = this.trailer; - if (trailer == null) { - trailer = this.trailer = new DefaultLastHttpContent(Unpooled.EMPTY_BUFFER, validateHeaders); - } - do { - char firstChar = line.charAt(0); - if (lastHeader != null && (firstChar == ' ' || firstChar == '\t')) { - List current = trailer.trailingHeaders().getAll(lastHeader); - if (!current.isEmpty()) { - int lastPos = current.size() - 1; - //please do not make one line from below code - //as it breaks +XX:OptimizeStringConcat optimization - String lineTrimmed = line.toString().trim(); - String currentLastPos = current.get(lastPos); - current.set(lastPos, currentLastPos + lineTrimmed); - } - } else { - splitHeader(line); - CharSequence headerName = name; - if (!HttpHeaderNames.CONTENT_LENGTH.contentEqualsIgnoreCase(headerName) && + if (trailer == null) { + trailer = this.trailer = new DefaultLastHttpContent(Unpooled.EMPTY_BUFFER, validateHeaders); + } + while (line.length() > 0) { + char firstChar = line.charAt(0); + if (lastHeader != null && (firstChar == ' ' || firstChar == '\t')) { + List current = trailer.trailingHeaders().getAll(lastHeader); + if (!current.isEmpty()) { + int lastPos = current.size() - 1; + //please do not make one line from below code + //as it breaks +XX:OptimizeStringConcat optimization + String lineTrimmed = line.toString().trim(); + String currentLastPos = current.get(lastPos); + current.set(lastPos, currentLastPos + lineTrimmed); + } + } else { + splitHeader(line); + CharSequence headerName = name; + if (!HttpHeaderNames.CONTENT_LENGTH.contentEqualsIgnoreCase(headerName) && !HttpHeaderNames.TRANSFER_ENCODING.contentEqualsIgnoreCase(headerName) && !HttpHeaderNames.TRAILER.contentEqualsIgnoreCase(headerName)) { - trailer.trailingHeaders().add(headerName, value); - } - lastHeader = name; - // reset name and value fields - name = null; - value = null; - } - - line = headerParser.parse(buffer); - if (line == null) { - return null; + trailer.trailingHeaders().add(headerName, value); } - } while (line.length() > 0); - - this.trailer = null; - return trailer; + lastHeader = name; + // reset name and value fields + name = null; + value = null; + } + line = headerParser.parse(buffer); + if (line == null) { + return null; + } } - return LastHttpContent.EMPTY_LAST_CONTENT; + this.trailer = null; + return trailer; } protected abstract boolean isDecodingRequest(); diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpResponseDecoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpResponseDecoderTest.java index 017dbd5ff943..f062da2bf1f4 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpResponseDecoderTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpResponseDecoderTest.java @@ -683,4 +683,33 @@ public void testConnectionClosedBeforeHeadersReceived() { assertThat(message.decoderResult().cause(), instanceOf(PrematureChannelClosureException.class)); assertNull(channel.readInbound()); } + + @Test + public void testTrailerWithEmptyLineInSeparateBuffer() { + HttpResponseDecoder decoder = new HttpResponseDecoder(); + EmbeddedChannel channel = new EmbeddedChannel(decoder); + + String headers = "HTTP/1.1 200 OK\r\n" + + "Transfer-Encoding: chunked\r\n" + + "Trailer: My-Trailer\r\n"; + assertFalse(channel.writeInbound(Unpooled.copiedBuffer(headers.getBytes(CharsetUtil.US_ASCII)))); + assertTrue(channel.writeInbound(Unpooled.copiedBuffer("\r\n".getBytes(CharsetUtil.US_ASCII)))); + + assertTrue(channel.writeInbound(Unpooled.copiedBuffer("0\r\n", CharsetUtil.US_ASCII))); + assertTrue(channel.writeInbound(Unpooled.copiedBuffer("My-Trailer: 42\r\n", CharsetUtil.US_ASCII))); + assertTrue(channel.writeInbound(Unpooled.copiedBuffer("\r\n", CharsetUtil.US_ASCII))); + + HttpResponse response = channel.readInbound(); + assertEquals(2, response.headers().size()); + assertEquals("chunked", response.headers().get(HttpHeaderNames.TRANSFER_ENCODING)); + assertEquals("My-Trailer", response.headers().get(HttpHeaderNames.TRAILER)); + + LastHttpContent lastContent = channel.readInbound(); + assertEquals(1, lastContent.trailingHeaders().size()); + assertEquals("42", lastContent.trailingHeaders().get("My-Trailer")); + assertEquals(0, lastContent.content().readableBytes()); + lastContent.release(); + + assertFalse(channel.finish()); + } } From 2e347119d2f21d3fec5917965cac2ed191762be6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=94=B0=E6=AC=A7?= Date: Mon, 4 Feb 2019 22:55:07 +0800 Subject: [PATCH 2/7] use checkPositive/checkPositiveOrZero (#8835) Motivation: We can replace some "hand-rolled" integer checks with our own static utility method to simplify the code. Modifications: Use methods provided by `ObjectUtil`. Result: Cleaner code and less duplication (cherry picked from commit 4c64c98f348131e0792ba4a92ce3d0003237d56a) --- .../handler/codec/dns/AbstractDnsRecord.java | 5 ++--- .../codec/http/DefaultHttpHeaders.java | 3 +-- .../handler/codec/http/HttpObjectDecoder.java | 21 ++++++------------- .../codec/http/HttpResponseStatus.java | 6 ++---- .../netty/handler/codec/http/HttpVersion.java | 10 ++++----- .../multipart/AbstractMemoryHttpData.java | 3 +-- .../codec/spdy/DefaultSpdyGoAwayFrame.java | 7 +++---- .../codec/spdy/DefaultSpdyStreamFrame.java | 7 +++---- .../codec/spdy/DefaultSpdySynReplyFrame.java | 3 +-- .../codec/spdy/DefaultSpdySynStreamFrame.java | 8 +++---- .../spdy/DefaultSpdyWindowUpdateFrame.java | 14 +++++-------- .../handler/codec/spdy/SpdyFrameDecoder.java | 7 +++---- .../handler/codec/spdy/SpdyHttpDecoder.java | 6 ++---- .../codec/spdy/SpdySessionHandler.java | 19 ++++++++--------- .../http2/DefaultHttp2ConnectionEncoder.java | 5 ++--- .../codec/http2/DefaultHttp2FrameWriter.java | 14 +++++-------- .../codec/http2/DefaultHttp2GoAwayFrame.java | 6 +++--- .../DefaultHttp2LocalFlowController.java | 5 ++--- .../DefaultHttp2RemoteFlowController.java | 5 ++--- .../DelegatingDecompressorFrameListener.java | 5 ++--- .../http2/UniformStreamByteDistributor.java | 5 ++--- .../WeightedFairQueueByteDistributor.java | 11 +++++----- .../binary/AbstractBinaryMemcacheDecoder.java | 6 +++--- .../codec/stomp/StompSubframeDecoder.java | 13 +++--------- 24 files changed, 74 insertions(+), 120 deletions(-) diff --git a/codec-dns/src/main/java/io/netty/handler/codec/dns/AbstractDnsRecord.java b/codec-dns/src/main/java/io/netty/handler/codec/dns/AbstractDnsRecord.java index 28b92c27f928..2ba6e573a7fd 100644 --- a/codec-dns/src/main/java/io/netty/handler/codec/dns/AbstractDnsRecord.java +++ b/codec-dns/src/main/java/io/netty/handler/codec/dns/AbstractDnsRecord.java @@ -21,6 +21,7 @@ import java.net.IDN; import static io.netty.util.internal.ObjectUtil.checkNotNull; +import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero; /** * A skeletal implementation of {@link DnsRecord}. @@ -62,9 +63,7 @@ protected AbstractDnsRecord(String name, DnsRecordType type, long timeToLive) { * @param timeToLive the TTL value of the record */ protected AbstractDnsRecord(String name, DnsRecordType type, int dnsClass, long timeToLive) { - if (timeToLive < 0) { - throw new IllegalArgumentException("timeToLive: " + timeToLive + " (expected: >= 0)"); - } + checkPositiveOrZero(timeToLive, "timeToLive"); // Convert to ASCII which will also check that the length is not too big. // See: // - https://github.com/netty/netty/issues/4937 diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpHeaders.java b/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpHeaders.java index 88af27f738e6..ef24c7558342 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpHeaders.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/DefaultHttpHeaders.java @@ -372,8 +372,7 @@ private static void validateHeaderNameElement(byte value) { default: // Check to see if the character is not an ASCII character, or invalid if (value < 0) { - throw new IllegalArgumentException("a header name cannot contain non-ASCII character: " + - value); + throw new IllegalArgumentException("a header name cannot contain non-ASCII character: " + value); } } } diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java index f8220cdb04eb..6d1d596f781c 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java @@ -15,6 +15,8 @@ */ package io.netty.handler.codec.http; +import static io.netty.util.internal.ObjectUtil.checkPositive; + import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; @@ -168,21 +170,10 @@ protected HttpObjectDecoder( protected HttpObjectDecoder( int maxInitialLineLength, int maxHeaderSize, int maxChunkSize, boolean chunkedSupported, boolean validateHeaders, int initialBufferSize) { - if (maxInitialLineLength <= 0) { - throw new IllegalArgumentException( - "maxInitialLineLength must be a positive integer: " + - maxInitialLineLength); - } - if (maxHeaderSize <= 0) { - throw new IllegalArgumentException( - "maxHeaderSize must be a positive integer: " + - maxHeaderSize); - } - if (maxChunkSize <= 0) { - throw new IllegalArgumentException( - "maxChunkSize must be a positive integer: " + - maxChunkSize); - } + checkPositive(maxInitialLineLength, "maxInitialLineLength"); + checkPositive(maxHeaderSize, "maxHeaderSize"); + checkPositive(maxChunkSize, "maxChunkSize"); + AppendableCharSequence seq = new AppendableCharSequence(initialBufferSize); lineParser = new LineParser(seq, maxInitialLineLength); headerParser = new HeaderParser(seq, maxHeaderSize); diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpResponseStatus.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpResponseStatus.java index b7e2c10d456c..ef60a41d4f3b 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpResponseStatus.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpResponseStatus.java @@ -22,6 +22,7 @@ import static io.netty.handler.codec.http.HttpConstants.SP; import static io.netty.util.ByteProcessor.FIND_ASCII_SPACE; +import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero; import static java.lang.Integer.parseInt; /** @@ -538,10 +539,7 @@ public HttpResponseStatus(int code, String reasonPhrase) { } private HttpResponseStatus(int code, String reasonPhrase, boolean bytes) { - if (code < 0) { - throw new IllegalArgumentException( - "code: " + code + " (expected: 0+)"); - } + checkPositiveOrZero(code, "code"); if (reasonPhrase == null) { throw new NullPointerException("reasonPhrase"); diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpVersion.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpVersion.java index a643f42458d9..7ba40eed90c3 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpVersion.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpVersion.java @@ -15,6 +15,8 @@ */ package io.netty.handler.codec.http; +import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero; + import io.netty.buffer.ByteBuf; import io.netty.util.CharsetUtil; @@ -165,12 +167,8 @@ private HttpVersion( } } - if (majorVersion < 0) { - throw new IllegalArgumentException("negative majorVersion"); - } - if (minorVersion < 0) { - throw new IllegalArgumentException("negative minorVersion"); - } + checkPositiveOrZero(majorVersion, "majorVersion"); + checkPositiveOrZero(minorVersion, "minorVersion"); this.protocolName = protocolName; this.majorVersion = majorVersion; diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/AbstractMemoryHttpData.java b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/AbstractMemoryHttpData.java index 31aa9ce64b5f..4cb7e567b252 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/AbstractMemoryHttpData.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/AbstractMemoryHttpData.java @@ -128,8 +128,7 @@ public void setContent(File file) throws IOException { } long newsize = file.length(); if (newsize > Integer.MAX_VALUE) { - throw new IllegalArgumentException( - "File too big to be loaded in memory"); + throw new IllegalArgumentException("File too big to be loaded in memory"); } checkSize(newsize); FileInputStream inputStream = new FileInputStream(file); diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyGoAwayFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyGoAwayFrame.java index 4d88875a6e8c..79c21f2404d2 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyGoAwayFrame.java +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyGoAwayFrame.java @@ -15,6 +15,8 @@ */ package io.netty.handler.codec.spdy; +import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero; + import io.netty.util.internal.StringUtil; /** @@ -62,10 +64,7 @@ public int lastGoodStreamId() { @Override public SpdyGoAwayFrame setLastGoodStreamId(int lastGoodStreamId) { - if (lastGoodStreamId < 0) { - throw new IllegalArgumentException("Last-good-stream-ID" - + " cannot be negative: " + lastGoodStreamId); - } + checkPositiveOrZero(lastGoodStreamId, "lastGoodStreamId"); this.lastGoodStreamId = lastGoodStreamId; return this; } diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyStreamFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyStreamFrame.java index 4618d4d4a95c..487844ecd913 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyStreamFrame.java +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyStreamFrame.java @@ -15,6 +15,8 @@ */ package io.netty.handler.codec.spdy; +import static io.netty.util.internal.ObjectUtil.checkPositive; + /** * The default {@link SpdyStreamFrame} implementation. */ @@ -39,10 +41,7 @@ public int streamId() { @Override public SpdyStreamFrame setStreamId(int streamId) { - if (streamId <= 0) { - throw new IllegalArgumentException( - "Stream-ID must be positive: " + streamId); - } + checkPositive(streamId, "streamId"); this.streamId = streamId; return this; } diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdySynReplyFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdySynReplyFrame.java index 7efc905641e3..f757d1dbd663 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdySynReplyFrame.java +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdySynReplyFrame.java @@ -20,8 +20,7 @@ /** * The default {@link SpdySynReplyFrame} implementation. */ -public class DefaultSpdySynReplyFrame extends DefaultSpdyHeadersFrame - implements SpdySynReplyFrame { +public class DefaultSpdySynReplyFrame extends DefaultSpdyHeadersFrame implements SpdySynReplyFrame { /** * Creates a new instance. diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdySynStreamFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdySynStreamFrame.java index f8adc1c5f1ca..46fe30163634 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdySynStreamFrame.java +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdySynStreamFrame.java @@ -15,6 +15,8 @@ */ package io.netty.handler.codec.spdy; +import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero; + import io.netty.util.internal.StringUtil; /** @@ -77,11 +79,7 @@ public int associatedStreamId() { @Override public SpdySynStreamFrame setAssociatedStreamId(int associatedStreamId) { - if (associatedStreamId < 0) { - throw new IllegalArgumentException( - "Associated-To-Stream-ID cannot be negative: " + - associatedStreamId); - } + checkPositiveOrZero(associatedStreamId, "associatedStreamId"); this.associatedStreamId = associatedStreamId; return this; } diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyWindowUpdateFrame.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyWindowUpdateFrame.java index f14611bac614..22b0406c80c0 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyWindowUpdateFrame.java +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/DefaultSpdyWindowUpdateFrame.java @@ -15,6 +15,9 @@ */ package io.netty.handler.codec.spdy; +import static io.netty.util.internal.ObjectUtil.checkPositive; +import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero; + import io.netty.util.internal.StringUtil; /** @@ -43,10 +46,7 @@ public int streamId() { @Override public SpdyWindowUpdateFrame setStreamId(int streamId) { - if (streamId < 0) { - throw new IllegalArgumentException( - "Stream-ID cannot be negative: " + streamId); - } + checkPositiveOrZero(streamId, "streamId"); this.streamId = streamId; return this; } @@ -58,11 +58,7 @@ public int deltaWindowSize() { @Override public SpdyWindowUpdateFrame setDeltaWindowSize(int deltaWindowSize) { - if (deltaWindowSize <= 0) { - throw new IllegalArgumentException( - "Delta-Window-Size must be positive: " + - deltaWindowSize); - } + checkPositive(deltaWindowSize, "deltaWindowSize"); this.deltaWindowSize = deltaWindowSize; return this; } diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameDecoder.java index e0d1112813b7..fc432b683096 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyFrameDecoder.java @@ -38,6 +38,8 @@ import static io.netty.handler.codec.spdy.SpdyCodecUtil.getUnsignedInt; import static io.netty.handler.codec.spdy.SpdyCodecUtil.getUnsignedMedium; import static io.netty.handler.codec.spdy.SpdyCodecUtil.getUnsignedShort; +import static io.netty.util.internal.ObjectUtil.checkPositive; + import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; @@ -95,10 +97,7 @@ public SpdyFrameDecoder(SpdyVersion spdyVersion, SpdyFrameDecoderDelegate delega if (delegate == null) { throw new NullPointerException("delegate"); } - if (maxChunkSize <= 0) { - throw new IllegalArgumentException( - "maxChunkSize must be a positive integer: " + maxChunkSize); - } + checkPositive(maxChunkSize, "maxChunkSize"); this.spdyVersion = spdyVersion.getVersion(); this.delegate = delegate; this.maxChunkSize = maxChunkSize; diff --git a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpDecoder.java index 366ad15b662f..5e16a6f4f2a7 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/spdy/SpdyHttpDecoder.java @@ -38,6 +38,7 @@ import java.util.Map; import static io.netty.handler.codec.spdy.SpdyHeaders.HttpNames.*; +import static io.netty.util.internal.ObjectUtil.checkPositive; /** * Decodes {@link SpdySynStreamFrame}s, {@link SpdySynReplyFrame}s, @@ -103,10 +104,7 @@ protected SpdyHttpDecoder(SpdyVersion version, int maxContentLength, Map= 0"); - } + checkPositiveOrZero(padding, "padding"); this.padding = padding; this.endOfStream = endOfStream; this.stream = stream; diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2FrameWriter.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2FrameWriter.java index 3fa84137042d..e77cc9ff301a 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2FrameWriter.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2FrameWriter.java @@ -61,6 +61,8 @@ import static io.netty.handler.codec.http2.Http2FrameTypes.SETTINGS; import static io.netty.handler.codec.http2.Http2FrameTypes.WINDOW_UPDATE; import static io.netty.util.internal.ObjectUtil.checkNotNull; +import static io.netty.util.internal.ObjectUtil.checkPositive; +import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero; import static java.lang.Math.max; import static java.lang.Math.min; @@ -614,15 +616,11 @@ private static void writePaddingLength(ByteBuf buf, int padding) { } private static void verifyStreamId(int streamId, String argumentName) { - if (streamId <= 0) { - throw new IllegalArgumentException(argumentName + " must be > 0"); - } + checkPositive(streamId, "streamId"); } private static void verifyStreamOrConnectionId(int streamId, String argumentName) { - if (streamId < 0) { - throw new IllegalArgumentException(argumentName + " must be >= 0"); - } + checkPositiveOrZero(streamId, "streamId"); } private static void verifyWeight(short weight) { @@ -638,9 +636,7 @@ private static void verifyErrorCode(long errorCode) { } private static void verifyWindowSizeIncrement(int windowSizeIncrement) { - if (windowSizeIncrement < 0) { - throw new IllegalArgumentException("WindowSizeIncrement must be >= 0"); - } + checkPositiveOrZero(windowSizeIncrement, "windowSizeIncrement"); } private static void verifyPingPayload(ByteBuf data) { diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2GoAwayFrame.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2GoAwayFrame.java index 77207673303f..2dbd738d04bd 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2GoAwayFrame.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2GoAwayFrame.java @@ -15,6 +15,8 @@ */ package io.netty.handler.codec.http2; +import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero; + import io.netty.buffer.ByteBuf; import io.netty.buffer.DefaultByteBufHolder; import io.netty.buffer.Unpooled; @@ -98,9 +100,7 @@ public int extraStreamIds() { @Override public Http2GoAwayFrame setExtraStreamIds(int extraStreamIds) { - if (extraStreamIds < 0) { - throw new IllegalArgumentException("extraStreamIds must be non-negative"); - } + checkPositiveOrZero(extraStreamIds, "extraStreamIds"); this.extraStreamIds = extraStreamIds; return this; } diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2LocalFlowController.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2LocalFlowController.java index 74dc3ae31c44..cac715614d35 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2LocalFlowController.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2LocalFlowController.java @@ -24,6 +24,7 @@ import static io.netty.handler.codec.http2.Http2Exception.connectionError; import static io.netty.handler.codec.http2.Http2Exception.streamError; import static io.netty.util.internal.ObjectUtil.checkNotNull; +import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero; import static java.lang.Math.max; import static java.lang.Math.min; import io.netty.buffer.ByteBuf; @@ -173,9 +174,7 @@ public void incrementWindowSize(Http2Stream stream, int delta) throws Http2Excep @Override public boolean consumeBytes(Http2Stream stream, int numBytes) throws Http2Exception { assert ctx != null && ctx.executor().inEventLoop(); - if (numBytes < 0) { - throw new IllegalArgumentException("numBytes must not be negative"); - } + checkPositiveOrZero(numBytes, "numBytes"); if (numBytes == 0) { return false; } diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2RemoteFlowController.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2RemoteFlowController.java index 217cf8dc251d..ef6ec986ee8f 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2RemoteFlowController.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/DefaultHttp2RemoteFlowController.java @@ -31,6 +31,7 @@ import static io.netty.handler.codec.http2.Http2Exception.streamError; import static io.netty.handler.codec.http2.Http2Stream.State.HALF_CLOSED_LOCAL; import static io.netty.util.internal.ObjectUtil.checkNotNull; +import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero; import static java.lang.Math.max; import static java.lang.Math.min; @@ -635,9 +636,7 @@ final void writePendingBytes() throws Http2Exception { } void initialWindowSize(int newWindowSize) throws Http2Exception { - if (newWindowSize < 0) { - throw new IllegalArgumentException("Invalid initial window size: " + newWindowSize); - } + checkPositiveOrZero(newWindowSize, "newWindowSize"); final int delta = newWindowSize - initialWindowSize; initialWindowSize = newWindowSize; diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/DelegatingDecompressorFrameListener.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/DelegatingDecompressorFrameListener.java index 78ef230c62ff..3e73bd68dd86 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/DelegatingDecompressorFrameListener.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/DelegatingDecompressorFrameListener.java @@ -33,6 +33,7 @@ import static io.netty.handler.codec.http2.Http2Error.INTERNAL_ERROR; import static io.netty.handler.codec.http2.Http2Exception.streamError; import static io.netty.util.internal.ObjectUtil.checkNotNull; +import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero; /** * A HTTP2 frame listener that will decompress data frames according to the {@code content-encoding} header for each @@ -398,9 +399,7 @@ void incrementDecompressedBytes(int delta) { * @return The number of pre-decompressed bytes that have been consumed. */ int consumeBytes(int streamId, int decompressedBytes) throws Http2Exception { - if (decompressedBytes < 0) { - throw new IllegalArgumentException("decompressedBytes must not be negative: " + decompressedBytes); - } + checkPositiveOrZero(decompressedBytes, "decompressedBytes"); if (decompressed - decompressedBytes < 0) { throw streamError(streamId, INTERNAL_ERROR, "Attempting to return too many bytes for stream %d. decompressed: %d " + diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/UniformStreamByteDistributor.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/UniformStreamByteDistributor.java index 421d3488b20c..c7e57911b8f2 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/UniformStreamByteDistributor.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/UniformStreamByteDistributor.java @@ -24,6 +24,7 @@ import static io.netty.handler.codec.http2.Http2Error.INTERNAL_ERROR; import static io.netty.handler.codec.http2.Http2Exception.connectionError; import static io.netty.util.internal.ObjectUtil.checkNotNull; +import static io.netty.util.internal.ObjectUtil.checkPositive; import static java.lang.Math.max; import static java.lang.Math.min; @@ -72,9 +73,7 @@ public void onStreamClosed(Http2Stream stream) { * Must be > 0. */ public void minAllocationChunk(int minAllocationChunk) { - if (minAllocationChunk <= 0) { - throw new IllegalArgumentException("minAllocationChunk must be > 0"); - } + checkPositive(minAllocationChunk, "minAllocationChunk"); this.minAllocationChunk = minAllocationChunk; } diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/WeightedFairQueueByteDistributor.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/WeightedFairQueueByteDistributor.java index b7c2cddf52cd..b0f3a25dc4a4 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/WeightedFairQueueByteDistributor.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/WeightedFairQueueByteDistributor.java @@ -37,6 +37,8 @@ import static io.netty.handler.codec.http2.Http2CodecUtil.streamableBytes; import static io.netty.handler.codec.http2.Http2Error.INTERNAL_ERROR; import static io.netty.handler.codec.http2.Http2Exception.connectionError; +import static io.netty.util.internal.ObjectUtil.checkPositive; +import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero; import static java.lang.Integer.MAX_VALUE; import static java.lang.Math.max; import static java.lang.Math.min; @@ -96,9 +98,8 @@ public WeightedFairQueueByteDistributor(Http2Connection connection) { } public WeightedFairQueueByteDistributor(Http2Connection connection, int maxStateOnlySize) { - if (maxStateOnlySize < 0) { - throw new IllegalArgumentException("maxStateOnlySize: " + maxStateOnlySize + " (expected: >0)"); - } else if (maxStateOnlySize == 0) { + checkPositiveOrZero(maxStateOnlySize, "maxStateOnlySize"); + if (maxStateOnlySize == 0) { stateOnlyMap = IntCollections.emptyMap(); stateOnlyRemovalQueue = EmptyPriorityQueue.instance(); } else { @@ -281,9 +282,7 @@ public boolean distribute(int maxBytes, Writer writer) throws Http2Exception { * @param allocationQuantum the amount of bytes that will be allocated to each stream. Must be > 0. */ public void allocationQuantum(int allocationQuantum) { - if (allocationQuantum <= 0) { - throw new IllegalArgumentException("allocationQuantum must be > 0"); - } + checkPositive(allocationQuantum, "allocationQuantum"); this.allocationQuantum = allocationQuantum; } diff --git a/codec-memcache/src/main/java/io/netty/handler/codec/memcache/binary/AbstractBinaryMemcacheDecoder.java b/codec-memcache/src/main/java/io/netty/handler/codec/memcache/binary/AbstractBinaryMemcacheDecoder.java index 2c9038282991..bec754afbda2 100644 --- a/codec-memcache/src/main/java/io/netty/handler/codec/memcache/binary/AbstractBinaryMemcacheDecoder.java +++ b/codec-memcache/src/main/java/io/netty/handler/codec/memcache/binary/AbstractBinaryMemcacheDecoder.java @@ -15,6 +15,8 @@ */ package io.netty.handler.codec.memcache.binary; +import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero; + import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; @@ -59,9 +61,7 @@ protected AbstractBinaryMemcacheDecoder() { * @param chunkSize the maximum chunk size of the payload. */ protected AbstractBinaryMemcacheDecoder(int chunkSize) { - if (chunkSize < 0) { - throw new IllegalArgumentException("chunkSize must be a positive integer: " + chunkSize); - } + checkPositiveOrZero(chunkSize, "chunkSize"); this.chunkSize = chunkSize; } diff --git a/codec-stomp/src/main/java/io/netty/handler/codec/stomp/StompSubframeDecoder.java b/codec-stomp/src/main/java/io/netty/handler/codec/stomp/StompSubframeDecoder.java index b4d6a1495823..0139426172f4 100644 --- a/codec-stomp/src/main/java/io/netty/handler/codec/stomp/StompSubframeDecoder.java +++ b/codec-stomp/src/main/java/io/netty/handler/codec/stomp/StompSubframeDecoder.java @@ -30,6 +30,7 @@ import static io.netty.buffer.ByteBufUtil.indexOf; import static io.netty.buffer.ByteBufUtil.readBytes; +import static io.netty.util.internal.ObjectUtil.checkPositive; /** * Decodes {@link ByteBuf}s into {@link StompHeadersSubframe}s and @@ -90,16 +91,8 @@ public StompSubframeDecoder(int maxLineLength, int maxChunkSize) { public StompSubframeDecoder(int maxLineLength, int maxChunkSize, boolean validateHeaders) { super(State.SKIP_CONTROL_CHARACTERS); - if (maxLineLength <= 0) { - throw new IllegalArgumentException( - "maxLineLength must be a positive integer: " + - maxLineLength); - } - if (maxChunkSize <= 0) { - throw new IllegalArgumentException( - "maxChunkSize must be a positive integer: " + - maxChunkSize); - } + checkPositive(maxLineLength, "maxLineLength"); + checkPositive(maxChunkSize, "maxChunkSize"); this.maxChunkSize = maxChunkSize; this.maxLineLength = maxLineLength; this.validateHeaders = validateHeaders; From 9042b2981503f906af8a6f2c547bcc7008ef5609 Mon Sep 17 00:00:00 2001 From: Idel Pivnitskiy Date: Thu, 22 Aug 2019 04:58:22 -0700 Subject: [PATCH 3/7] Use `AppendableCharSequence.charAtUnsafe(int)` in `HttpObjectDecoder` (#9492) Motivation: `HttpObjectDecoder` pre-checks that it doesn't request characters outside of the `AppendableCharSequence`'s length. `0` is always allowed because the minimal length of `AppendableCharSequence` is `1`. We can legally skip index check by using `AppendableCharSequence.charAtUnsafe(int)` in all existing cases in `HttpObjectDecoder`. Modifications: - Use `AppendableCharSequence.charAtUnsafe(int)` instead of `AppendableCharSequence.charAt(int)` in `HttpObjectDecoder`. Result: No unnecessary index checks in `HttpObjectDecoder`. (cherry picked from commit 85fcf4e58164806645b79239d0e6bf00287e26dc) --- .../io/netty/handler/codec/http/HttpObjectDecoder.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java index 6d1d596f781c..b6ce94b63e34 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java @@ -575,7 +575,7 @@ private State readHeaders(ByteBuf buffer) { } if (line.length() > 0) { do { - char firstChar = line.charAt(0); + char firstChar = line.charAtUnsafe(0); if (name != null && (firstChar == ' ' || firstChar == '\t')) { //please do not make one line from below code //as it breaks +XX:OptimizeStringConcat optimization @@ -643,7 +643,7 @@ private LastHttpContent readTrailingHeaders(ByteBuf buffer) { trailer = this.trailer = new DefaultLastHttpContent(Unpooled.EMPTY_BUFFER, validateHeaders); } while (line.length() > 0) { - char firstChar = line.charAt(0); + char firstChar = line.charAtUnsafe(0); if (lastHeader != null && (firstChar == ' ' || firstChar == '\t')) { List current = trailer.trailingHeaders().getAll(lastHeader); if (!current.isEmpty()) { @@ -727,14 +727,14 @@ private void splitHeader(AppendableCharSequence sb) { nameStart = findNonWhitespace(sb, 0); for (nameEnd = nameStart; nameEnd < length; nameEnd ++) { - char ch = sb.charAt(nameEnd); + char ch = sb.charAtUnsafe(nameEnd); if (ch == ':' || Character.isWhitespace(ch)) { break; } } for (colonEnd = nameEnd; colonEnd < length; colonEnd ++) { - if (sb.charAt(colonEnd) == ':') { + if (sb.charAtUnsafe(colonEnd) == ':') { colonEnd ++; break; } From b8c6b070af68314d824fea0a35e191f1ae533031 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Fri, 20 Sep 2019 21:02:11 +0200 Subject: [PATCH 4/7] Correctly handle whitespaces in HTTP header names as defined by RFC7230#section-3.2.4 (#9585) Motivation: When parsing HTTP headers special care needs to be taken when a whitespace is detected in the header name. Modifications: - Ignore whitespace when decoding response (just like before) - Throw exception when whitespace is detected during parsing - Add unit tests Result: Fixes https://github.com/netty/netty/issues/9571 (cherry picked from commit 39cafcb05c99f2aa9fce7e6597664c9ed6a63a95) --- .../handler/codec/http/HttpObjectDecoder.java | 16 +++++++++++++++- .../codec/http/HttpRequestDecoderTest.java | 14 ++++++++++++++ .../codec/http/HttpResponseDecoderTest.java | 15 +++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java index b6ce94b63e34..818273c8d23e 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java @@ -728,7 +728,21 @@ private void splitHeader(AppendableCharSequence sb) { nameStart = findNonWhitespace(sb, 0); for (nameEnd = nameStart; nameEnd < length; nameEnd ++) { char ch = sb.charAtUnsafe(nameEnd); - if (ch == ':' || Character.isWhitespace(ch)) { + // https://tools.ietf.org/html/rfc7230#section-3.2.4 + // + // No whitespace is allowed between the header field-name and colon. In + // the past, differences in the handling of such whitespace have led to + // security vulnerabilities in request routing and response handling. A + // server MUST reject any received request message that contains + // whitespace between a header field-name and colon with a response code + // of 400 (Bad Request). A proxy MUST remove any such whitespace from a + // response message before forwarding the message downstream. + if (ch == ':' || + // In case of decoding a request we will just continue processing and header validation + // is done in the DefaultHttpHeaders implementation. + // + // In the case of decoding a response we will "skip" the whitespace. + (!isDecodingRequest() && Character.isWhitespace(ch))) { break; } } diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestDecoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestDecoderTest.java index 45720631c40a..2b2d0cc5eb71 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestDecoderTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestDecoderTest.java @@ -320,4 +320,18 @@ public void testTooLargeHeaders() { assertTrue(request.decoderResult().cause() instanceof TooLongFrameException); assertFalse(channel.finish()); } + + @Test + public void testWhitespace() { + EmbeddedChannel channel = new EmbeddedChannel(new HttpRequestDecoder()); + String requestStr = "GET /some/path HTTP/1.1\r\n" + + "Transfer-Encoding : chunked\r\n" + + "Host: netty.io\n\r\n"; + + assertTrue(channel.writeInbound(Unpooled.copiedBuffer(requestStr, CharsetUtil.US_ASCII))); + HttpRequest request = channel.readInbound(); + assertTrue(request.decoderResult().isFailure()); + assertTrue(request.decoderResult().cause() instanceof IllegalArgumentException); + assertFalse(channel.finish()); + } } diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpResponseDecoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpResponseDecoderTest.java index f062da2bf1f4..6378a376b11c 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpResponseDecoderTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpResponseDecoderTest.java @@ -712,4 +712,19 @@ public void testTrailerWithEmptyLineInSeparateBuffer() { assertFalse(channel.finish()); } + + @Test + public void testWhitespace() { + EmbeddedChannel channel = new EmbeddedChannel(new HttpResponseDecoder()); + String requestStr = "HTTP/1.1 200 OK\r\n" + + "Transfer-Encoding : chunked\r\n" + + "Host: netty.io\n\r\n"; + + assertTrue(channel.writeInbound(Unpooled.copiedBuffer(requestStr, CharsetUtil.US_ASCII))); + HttpResponse response = channel.readInbound(); + assertFalse(response.decoderResult().isFailure()); + assertEquals(HttpHeaderValues.CHUNKED.toString(), response.headers().get(HttpHeaderNames.TRANSFER_ENCODING)); + assertEquals("netty.io", response.headers().get(HttpHeaderNames.HOST)); + assertFalse(channel.finish()); + } } From e41f0d3f87b8a9e181a82a0f9de476e5975c26bd Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Wed, 11 Dec 2019 15:49:07 +0100 Subject: [PATCH 5/7] Detect missing colon when parsing http headers with no value (#9871) Motivation: Technical speaking its valid to have http headers with no values so we should support it. That said we need to detect if these are "generated" because of an "invalid" fold. Modifications: - Detect if a colon is missing when parsing headers. - Add unit test Result: Fixes https://github.com/netty/netty/issues/9866 (cherry picked from commit a7c18d44b46e02dadfe3da225a06e5091f5f328e) --- .../handler/codec/http/HttpObjectDecoder.java | 5 +++++ .../codec/http/HttpRequestDecoderTest.java | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java index 818273c8d23e..171815266812 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java @@ -747,6 +747,11 @@ private void splitHeader(AppendableCharSequence sb) { } } + if (nameEnd == length) { + // There was no colon present at all. + throw new IllegalArgumentException("No colon found"); + } + for (colonEnd = nameEnd; colonEnd < length; colonEnd ++) { if (sb.charAtUnsafe(colonEnd) == ':') { colonEnd ++; diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestDecoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestDecoderTest.java index 2b2d0cc5eb71..414a0336b524 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestDecoderTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestDecoderTest.java @@ -334,4 +334,20 @@ public void testWhitespace() { assertTrue(request.decoderResult().cause() instanceof IllegalArgumentException); assertFalse(channel.finish()); } + + @Test + public void testHeaderWithNoValueAndMissingColon() { + EmbeddedChannel channel = new EmbeddedChannel(new HttpRequestDecoder()); + String requestStr = "GET /some/path HTTP/1.1\r\n" + + "Content-Length: 0\r\n" + + "Host:\r\n" + + "netty.io\r\n\r\n"; + + assertTrue(channel.writeInbound(Unpooled.copiedBuffer(requestStr, CharsetUtil.US_ASCII))); + HttpRequest request = channel.readInbound(); + System.err.println(request.headers().names().toString()); + assertTrue(request.decoderResult().isFailure()); + assertTrue(request.decoderResult().cause() instanceof IllegalArgumentException); + assertFalse(channel.finish()); + } } From f68e787875dec079630d3f6b9468ffbff6e6056d Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Fri, 13 Dec 2019 08:53:19 +0100 Subject: [PATCH 6/7] Verify we do not receive multiple content-length headers or a content-length and transfer-encoding: chunked header when using HTTP/1.1 (#9865) Motivation: RFC7230 states that we should not accept multiple content-length headers and also should not accept a content-length header in combination with transfer-encoding: chunked Modifications: - Check for multiple content-length headers and if found mark message as invalid - Check if we found a content-length header and also a transfer-encoding: chunked and if so mark the message as invalid - Add unit test Result: Fixes https://github.com/netty/netty/issues/9861 (cherry picked from commit 8494b046ec7e4f28dbd44bc699cc4c4c92251729) --- .../handler/codec/http/HttpObjectDecoder.java | 50 +++++++++++++-- .../codec/http/HttpRequestDecoderTest.java | 64 ++++++++++++++++--- 2 files changed, 99 insertions(+), 15 deletions(-) diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java index 171815266812..8d4fc1d42957 100644 --- a/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java +++ b/codec-http/src/main/java/io/netty/handler/codec/http/HttpObjectDecoder.java @@ -600,23 +600,61 @@ private State readHeaders(ByteBuf buffer) { if (name != null) { headers.add(name, value); } + // reset name and value fields name = null; value = null; - State nextState; + List values = headers.getAll(HttpHeaderNames.CONTENT_LENGTH); + int contentLengthValuesCount = values.size(); + + if (contentLengthValuesCount > 0) { + // Guard against multiple Content-Length headers as stated in + // https://tools.ietf.org/html/rfc7230#section-3.3.2: + // + // If a message is received that has multiple Content-Length header + // fields with field-values consisting of the same decimal value, or a + // single Content-Length header field with a field value containing a + // list of identical decimal values (e.g., "Content-Length: 42, 42"), + // indicating that duplicate Content-Length header fields have been + // generated or combined by an upstream message processor, then the + // recipient MUST either reject the message as invalid or replace the + // duplicated field-values with a single valid Content-Length field + // containing that decimal value prior to determining the message body + // length or forwarding the message. + if (contentLengthValuesCount > 1 && message.protocolVersion() == HttpVersion.HTTP_1_1) { + throw new IllegalArgumentException("Multiple Content-Length headers found"); + } + contentLength = Long.parseLong(values.get(0)); + } if (isContentAlwaysEmpty(message)) { HttpUtil.setTransferEncodingChunked(message, false); - nextState = State.SKIP_CONTROL_CHARS; + return State.SKIP_CONTROL_CHARS; } else if (HttpUtil.isTransferEncodingChunked(message)) { - nextState = State.READ_CHUNK_SIZE; + // See https://tools.ietf.org/html/rfc7230#section-3.3.3 + // + // If a message is received with both a Transfer-Encoding and a + // Content-Length header field, the Transfer-Encoding overrides the + // Content-Length. Such a message might indicate an attempt to + // perform request smuggling (Section 9.5) or response splitting + // (Section 9.4) and ought to be handled as an error. A sender MUST + // remove the received Content-Length field prior to forwarding such + // a message downstream. + // + // This is also what http_parser does: + // https://github.com/nodejs/http-parser/blob/v2.9.2/http_parser.c#L1769 + if (contentLengthValuesCount > 0 && message.protocolVersion() == HttpVersion.HTTP_1_1) { + throw new IllegalArgumentException( + "Both 'Content-Length: " + contentLength + "' and 'Transfer-Encoding: chunked' found"); + } + + return State.READ_CHUNK_SIZE; } else if (contentLength() >= 0) { - nextState = State.READ_FIXED_LENGTH_CONTENT; + return State.READ_FIXED_LENGTH_CONTENT; } else { - nextState = State.READ_VARIABLE_LENGTH_CONTENT; + return State.READ_VARIABLE_LENGTH_CONTENT; } - return nextState; } private long contentLength() { diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestDecoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestDecoderTest.java index 414a0336b524..717b58090158 100644 --- a/codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestDecoderTest.java +++ b/codec-http/src/test/java/io/netty/handler/codec/http/HttpRequestDecoderTest.java @@ -323,29 +323,75 @@ public void testTooLargeHeaders() { @Test public void testWhitespace() { - EmbeddedChannel channel = new EmbeddedChannel(new HttpRequestDecoder()); String requestStr = "GET /some/path HTTP/1.1\r\n" + "Transfer-Encoding : chunked\r\n" + "Host: netty.io\n\r\n"; - - assertTrue(channel.writeInbound(Unpooled.copiedBuffer(requestStr, CharsetUtil.US_ASCII))); - HttpRequest request = channel.readInbound(); - assertTrue(request.decoderResult().isFailure()); - assertTrue(request.decoderResult().cause() instanceof IllegalArgumentException); - assertFalse(channel.finish()); + testInvalidHeaders0(requestStr); } @Test public void testHeaderWithNoValueAndMissingColon() { - EmbeddedChannel channel = new EmbeddedChannel(new HttpRequestDecoder()); String requestStr = "GET /some/path HTTP/1.1\r\n" + "Content-Length: 0\r\n" + "Host:\r\n" + "netty.io\r\n\r\n"; + testInvalidHeaders0(requestStr); + } + + @Test + public void testMultipleContentLengthHeaders() { + String requestStr = "GET /some/path HTTP/1.1\r\n" + + "Content-Length: 1\r\n" + + "Content-Length: 0\r\n\r\n" + + "b"; + testInvalidHeaders0(requestStr); + } + + @Test + public void testMultipleContentLengthHeaders2() { + String requestStr = "GET /some/path HTTP/1.1\r\n" + + "Content-Length: 1\r\n" + + "Connection: close\r\n" + + "Content-Length: 0\r\n\r\n" + + "b"; + testInvalidHeaders0(requestStr); + } + + @Test + public void testContentLengthHeaderWithCommaValue() { + String requestStr = "GET /some/path HTTP/1.1\r\n" + + "Content-Length: 1,1\r\n\r\n" + + "b"; + testInvalidHeaders0(requestStr); + } + @Test + public void testMultipleContentLengthHeadersWithFolding() { + String requestStr = "POST / HTTP/1.1\r\n" + + "Host: example.com\r\n" + + "Connection: close\r\n" + + "Content-Length: 5\r\n" + + "Content-Length:\r\n" + + "\t6\r\n\r\n" + + "123456"; + testInvalidHeaders0(requestStr); + } + + @Test + public void testContentLengthHeaderAndChunked() { + String requestStr = "POST / HTTP/1.1\r\n" + + "Host: example.com\r\n" + + "Connection: close\r\n" + + "Content-Length: 5\r\n" + + "Transfer-Encoding: chunked\r\n\r\n" + + "0\r\n\r\n"; + testInvalidHeaders0(requestStr); + } + + private static void testInvalidHeaders0(String requestStr) { + EmbeddedChannel channel = new EmbeddedChannel(new HttpRequestDecoder()); assertTrue(channel.writeInbound(Unpooled.copiedBuffer(requestStr, CharsetUtil.US_ASCII))); HttpRequest request = channel.readInbound(); - System.err.println(request.headers().names().toString()); assertTrue(request.decoderResult().isFailure()); assertTrue(request.decoderResult().cause() instanceof IllegalArgumentException); assertFalse(channel.finish()); From e325faaea125bb125b85f5c5fc9170156bd1ac1f Mon Sep 17 00:00:00 2001 From: Dan LaRocque Date: Tue, 7 Apr 2020 06:10:37 -0500 Subject: [PATCH 7/7] Version bump to 4.1.25.7.dse MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Compared against 4.1.25.6.dse, this tag cherry-picks upstream commits that fixed bugs in HttpObjectDecoder/HttpRequestDecoder, plus two intermediate refactoring commits that indirectly affect those bugfix commits. What follows is a list of PR links, issue links, CVE links, and hashes associated with the cherry-picked commits. Verify we do not receive multiple content-length headers or a content-length and transfer-encoding: chunked header when using HTTP/1.1 (#9865) https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-7238 https://github.com/netty/netty/issues/9861 https://github.com/netty/netty/pull/9865 8494b046ec7e4f28dbd44bc699cc4c4c92251729 Detect missing colon when parsing http headers with no value (#9871) https://github.com/advisories/GHSA-cqqj-4p63-rrmm https://github.com/netty/netty/issues/9866 https://github.com/netty/netty/pull/9871 a7c18d44b46e02dadfe3da225a06e5091f5f328e Fix typos in javadocs (#9527) skipped Correctly handle whitespaces in HTTP header names as defined by RFC7230#section-3.2.4 (#9585) https://nvd.nist.gov/vuln/detail/CVE-2019-16869 https://github.com/netty/netty/issues/9571 https://github.com/netty/netty/pull/9585 39cafcb05c99f2aa9fce7e6597664c9ed6a63a95 Use `AppendableCharSequence.charAtUnsafe(int)` in `HttpObjectDecoder` (#9492) https://github.com/netty/netty/pull/9492 85fcf4e58164806645b79239d0e6bf00287e26dc use checkPositive/checkPositiveOrZero (#8835) https://github.com/netty/netty/pull/8835 4c64c98f348131e0792ba4a92ce3d0003237d56a HttpObjectDecoder ignores HTTP trailer header when empty line is rece… (#8799) https://github.com/netty/netty/issues/8736 https://github.com/netty/netty/pull/8799 91d3920aa298ea536be7b196f16b32b6ddd27f8d --- all/pom.xml | 2 +- bom/pom.xml | 65 +++++++++++----------- buffer/pom.xml | 2 +- codec-dns/pom.xml | 2 +- codec-haproxy/pom.xml | 2 +- codec-http/pom.xml | 2 +- codec-http2/pom.xml | 2 +- codec-memcache/pom.xml | 2 +- codec-mqtt/pom.xml | 2 +- codec-redis/pom.xml | 2 +- codec-smtp/pom.xml | 2 +- codec-socks/pom.xml | 2 +- codec-stomp/pom.xml | 2 +- codec-xml/pom.xml | 2 +- codec/pom.xml | 2 +- common/pom.xml | 2 +- dev-tools/pom.xml | 3 +- example/pom.xml | 2 +- handler-proxy/pom.xml | 2 +- handler/pom.xml | 2 +- microbench/pom.xml | 2 +- pom.xml | 3 +- resolver-dns/pom.xml | 2 +- resolver/pom.xml | 2 +- tarball/pom.xml | 2 +- testsuite-autobahn/pom.xml | 2 +- testsuite-http2/pom.xml | 2 +- testsuite-osgi/pom.xml | 2 +- testsuite/pom.xml | 2 +- transport-native-epoll/pom.xml | 2 +- transport-native-kqueue/pom.xml | 2 +- transport-native-unix-common-tests/pom.xml | 2 +- transport-native-unix-common/pom.xml | 2 +- transport-rxtx/pom.xml | 2 +- transport-sctp/pom.xml | 2 +- transport-udt/pom.xml | 2 +- transport/pom.xml | 2 +- 37 files changed, 68 insertions(+), 71 deletions(-) diff --git a/all/pom.xml b/all/pom.xml index 1c4aa8ce389b..cfdbb49fc50a 100644 --- a/all/pom.xml +++ b/all/pom.xml @@ -21,7 +21,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-all diff --git a/bom/pom.xml b/bom/pom.xml index 9ef41f0d292c..9abea4761c77 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -25,7 +25,7 @@ io.netty netty-bom - 4.1.25.dse + 4.1.25.7.dse pom Netty/BOM @@ -49,7 +49,6 @@ https://github.com/netty/netty scm:git:git://github.com/netty/netty.git scm:git:ssh://git@github.com/netty/netty.git - netty-4.1.25.dse @@ -69,72 +68,72 @@ io.netty netty-buffer - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-codec - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-codec-dns - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-codec-haproxy - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-codec-http - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-codec-http2 - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-codec-memcache - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-codec-mqtt - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-codec-redis - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-codec-smtp - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-codec-socks - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-codec-stomp - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-codec-xml - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-common - 4.1.25.6.dse + 4.1.25.7.dse io.netty @@ -144,90 +143,90 @@ io.netty netty-handler - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-handler-proxy - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-resolver - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-resolver-dns - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-transport - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-transport-rxtx - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-transport-sctp - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-transport-udt - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-example - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-all - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-transport-native-unix-common - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-transport-native-unix-common - 4.1.25.6.dse + 4.1.25.7.dse linux-x86_64 io.netty netty-transport-native-unix-common - 4.1.25.6.dse + 4.1.25.7.dse osx-x86_64 io.netty netty-transport-native-epoll - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-transport-native-epoll - 4.1.25.6.dse + 4.1.25.7.dse linux-x86_64 io.netty netty-transport-native-kqueue - 4.1.25.6.dse + 4.1.25.7.dse io.netty netty-transport-native-kqueue - 4.1.25.6.dse + 4.1.25.7.dse osx-x86_64 diff --git a/buffer/pom.xml b/buffer/pom.xml index 555fdd18eed8..5d3405a68c1a 100644 --- a/buffer/pom.xml +++ b/buffer/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-buffer diff --git a/codec-dns/pom.xml b/codec-dns/pom.xml index 296b9da3b24f..eaa16c25aa95 100644 --- a/codec-dns/pom.xml +++ b/codec-dns/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-codec-dns diff --git a/codec-haproxy/pom.xml b/codec-haproxy/pom.xml index 7d78c0814a00..2e30856de41a 100644 --- a/codec-haproxy/pom.xml +++ b/codec-haproxy/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-codec-haproxy diff --git a/codec-http/pom.xml b/codec-http/pom.xml index c39c9efbce0a..84607c242c98 100644 --- a/codec-http/pom.xml +++ b/codec-http/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-codec-http diff --git a/codec-http2/pom.xml b/codec-http2/pom.xml index af38c16c094c..3a069ddf5e30 100644 --- a/codec-http2/pom.xml +++ b/codec-http2/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-codec-http2 diff --git a/codec-memcache/pom.xml b/codec-memcache/pom.xml index 8ea1b03b320c..bd1f313542e2 100644 --- a/codec-memcache/pom.xml +++ b/codec-memcache/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-codec-memcache diff --git a/codec-mqtt/pom.xml b/codec-mqtt/pom.xml index ad27283493f6..46db9d2abaf6 100644 --- a/codec-mqtt/pom.xml +++ b/codec-mqtt/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-codec-mqtt diff --git a/codec-redis/pom.xml b/codec-redis/pom.xml index a722e8515f12..6b72dfa236e3 100644 --- a/codec-redis/pom.xml +++ b/codec-redis/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-codec-redis diff --git a/codec-smtp/pom.xml b/codec-smtp/pom.xml index 79cd18ea9c79..fb14d110474c 100644 --- a/codec-smtp/pom.xml +++ b/codec-smtp/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-codec-smtp diff --git a/codec-socks/pom.xml b/codec-socks/pom.xml index e1989f6d36f2..02f7d8c8ffcd 100644 --- a/codec-socks/pom.xml +++ b/codec-socks/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-codec-socks diff --git a/codec-stomp/pom.xml b/codec-stomp/pom.xml index 8360f347bcf4..e067b861c085 100644 --- a/codec-stomp/pom.xml +++ b/codec-stomp/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-codec-stomp diff --git a/codec-xml/pom.xml b/codec-xml/pom.xml index 2aba0b9768ad..3a5aff023612 100644 --- a/codec-xml/pom.xml +++ b/codec-xml/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-codec-xml diff --git a/codec/pom.xml b/codec/pom.xml index a0939082a196..5400f67dcdcf 100644 --- a/codec/pom.xml +++ b/codec/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-codec diff --git a/common/pom.xml b/common/pom.xml index 238daf04569a..582e1b01ffac 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -21,7 +21,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-common diff --git a/dev-tools/pom.xml b/dev-tools/pom.xml index 57c3d61111b4..776012d2f24a 100644 --- a/dev-tools/pom.xml +++ b/dev-tools/pom.xml @@ -25,7 +25,7 @@ io.netty netty-dev-tools - 4.1.25.6.dse + 4.1.25.7.dse Netty/Dev-Tools @@ -52,6 +52,5 @@ - netty-4.1.25.dse diff --git a/example/pom.xml b/example/pom.xml index dff1d2736f04..cc510ca0c6e4 100644 --- a/example/pom.xml +++ b/example/pom.xml @@ -21,7 +21,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-example diff --git a/handler-proxy/pom.xml b/handler-proxy/pom.xml index b76e74e2d05c..fb8c46e9d940 100644 --- a/handler-proxy/pom.xml +++ b/handler-proxy/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-handler-proxy diff --git a/handler/pom.xml b/handler/pom.xml index a5c288ac988a..9cbaad3fbdd7 100644 --- a/handler/pom.xml +++ b/handler/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-handler diff --git a/microbench/pom.xml b/microbench/pom.xml index 075debb65ed0..a83e79dd04ff 100644 --- a/microbench/pom.xml +++ b/microbench/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-microbench diff --git a/pom.xml b/pom.xml index 3ee170fe8a2a..e6927f7302f3 100644 --- a/pom.xml +++ b/pom.xml @@ -26,7 +26,7 @@ io.netty netty-parent pom - 4.1.25.6.dse + 4.1.25.7.dse Netty http://netty.io/ @@ -53,7 +53,6 @@ https://github.com/netty/netty scm:git:git://github.com/netty/netty.git scm:git:ssh://git@github.com/netty/netty.git - netty-4.1.25.dse diff --git a/resolver-dns/pom.xml b/resolver-dns/pom.xml index c24b09d0b05f..a3ad770320b4 100644 --- a/resolver-dns/pom.xml +++ b/resolver-dns/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-resolver-dns diff --git a/resolver/pom.xml b/resolver/pom.xml index 56457f6cae87..95668d000a89 100644 --- a/resolver/pom.xml +++ b/resolver/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-resolver diff --git a/tarball/pom.xml b/tarball/pom.xml index 399c3bf9fcb4..54c3a729e7cb 100644 --- a/tarball/pom.xml +++ b/tarball/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-tarball diff --git a/testsuite-autobahn/pom.xml b/testsuite-autobahn/pom.xml index addbf765f0af..4819d434549b 100644 --- a/testsuite-autobahn/pom.xml +++ b/testsuite-autobahn/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-testsuite-autobahn diff --git a/testsuite-http2/pom.xml b/testsuite-http2/pom.xml index 53418b92ad08..aceab0ec447b 100644 --- a/testsuite-http2/pom.xml +++ b/testsuite-http2/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-testsuite-http2 diff --git a/testsuite-osgi/pom.xml b/testsuite-osgi/pom.xml index 5e913d50b679..0f7e0480ad3b 100644 --- a/testsuite-osgi/pom.xml +++ b/testsuite-osgi/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-testsuite-osgi diff --git a/testsuite/pom.xml b/testsuite/pom.xml index 3aad0bffa2eb..78103967b03e 100644 --- a/testsuite/pom.xml +++ b/testsuite/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-testsuite diff --git a/transport-native-epoll/pom.xml b/transport-native-epoll/pom.xml index 477d06ff0014..f12b0c2c9fce 100644 --- a/transport-native-epoll/pom.xml +++ b/transport-native-epoll/pom.xml @@ -19,7 +19,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-transport-native-epoll diff --git a/transport-native-kqueue/pom.xml b/transport-native-kqueue/pom.xml index cfe06903fd3b..69e134c6a4d6 100644 --- a/transport-native-kqueue/pom.xml +++ b/transport-native-kqueue/pom.xml @@ -19,7 +19,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-transport-native-kqueue diff --git a/transport-native-unix-common-tests/pom.xml b/transport-native-unix-common-tests/pom.xml index 321cf86f48c6..9bfb56411530 100644 --- a/transport-native-unix-common-tests/pom.xml +++ b/transport-native-unix-common-tests/pom.xml @@ -19,7 +19,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-transport-native-unix-common-tests diff --git a/transport-native-unix-common/pom.xml b/transport-native-unix-common/pom.xml index 405a12835839..25370b64edff 100644 --- a/transport-native-unix-common/pom.xml +++ b/transport-native-unix-common/pom.xml @@ -19,7 +19,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-transport-native-unix-common diff --git a/transport-rxtx/pom.xml b/transport-rxtx/pom.xml index 2b64fc824a04..e325d237dae3 100644 --- a/transport-rxtx/pom.xml +++ b/transport-rxtx/pom.xml @@ -21,7 +21,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-transport-rxtx diff --git a/transport-sctp/pom.xml b/transport-sctp/pom.xml index 6b30a6fb76de..bd6b28816ef6 100644 --- a/transport-sctp/pom.xml +++ b/transport-sctp/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-transport-sctp diff --git a/transport-udt/pom.xml b/transport-udt/pom.xml index 69799c497f3c..9e68559448d7 100644 --- a/transport-udt/pom.xml +++ b/transport-udt/pom.xml @@ -21,7 +21,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-transport-udt diff --git a/transport/pom.xml b/transport/pom.xml index fddb1916453e..ad76607f7a50 100644 --- a/transport/pom.xml +++ b/transport/pom.xml @@ -20,7 +20,7 @@ io.netty netty-parent - 4.1.25.6.dse + 4.1.25.7.dse netty-transport