Skip navigation

Netty 4.2.20.Final released

We are happy to announce the release of Netty 4.2.20.Final. This is a bug-fix and security release.

Note that Netty 4.1 will be End-of-Life on July 1st, 2027.

We strongly recommend upgrading to this version to get the following security fixes:

Other significant changes are:

  • IoUring: Fix empty writev submissions after sendmsg_zc #17782
  • Do not let a negatively cached search domain shadow a positive one #17623
  • Reject Redis lines that start with LF #17793
  • Choose server key types from client's signature algorithms for TLS 1.3 #17764
  • LocalChannel: Deliver data written by the peer before it closed #17816
  • Validate padding of HEADERS frames without priority #17817
  • Don't spin in SslHandler.wrapMultiple(...) when the engine consumes nothing #17728
  • Preserve invalid SNI names in ReferenceCountedOpenSslEngine #17781
  • Optimize redundant bounds checking in ByteBuf.setBytes #17023
  • Respect SETTINGS_QPACK_BLOCKED_STREAMS for unacknowledged QPACK entries #17754
  • Release the DNS response when a query future loses a cancel race #17475
  • Lazily instantiate VarHandle JCTools queues via holder class #17750
  • Keep reading a closed QUIC stream until the end of its input #17755
  • Throw UnsupportedOperationException from AdaptiveByteBuf.memoryAddress() without an address #17820
  • HAProxyMessage: validate the length of all TLV types #17834
  • Fix HpackDynamicTable losing entries when filled to capacity #17831
  • Make AdaptiveByteBuf.memoryAddress() faster #17767
  • Validate bzip2 Huffman code lengths before building decode tables #17812
  • Validate header values on DefaultHeaders.copy(), bulk add, entry setValue and ReadOnlyHttpHeaders #17841
  • Throw DecompressionException on JdkZlib preset dictionary mismatch #17838
  • Reject HTTP version numbers that overflow int #17836
  • Apply certificate list size floor #17674
  • HAProxyMessageEncoder: encode v1 PROXY UNKNOWN headers #17837
  • HAProxyMessage: decode TLVs with an empty value at the end of the header #17835
  • Reject invalid content-length in PUSH_PROMISE with a stream error #17867
  • Honor maxAllocation for brotli in DelegatingDecompressorFrameListener #17866
  • HAProxyMessageDecoder: fix v2 header framing with a non-zero reader index #17832
  • Avoid allocating NIO buffer views in AdaptiveByteBuf.setBytes(int, ByteBuf, int, int) #17840
  • Skip JNDI nameserver lookup on IBM i #17872
  • Reset the h2c upgrade stream if the request can not be converted #17869
  • Don't size ZstdDecoder output buffers from the frame content size #17896
  • Fix NPE in Http2FrameCodec when h2c upgrade fails #17871
  • GroupsConverter: fix the x25519mlkem768 group name #17898
  • Don't count insertions twice in QPACK Insert Count Increments #17756
  • Don't lose frames when a delimiter is split across reads #17665
  • Register JFR events only once a Flight Recorder exists #17614
  • Read SOCKS5 length octets unsigned in the legacy socks decoders #17912
  • Fix truncated output in Brotli decoders #17870
  • Reject truncated QPACK prefixed integers in field section decode #17778
  • Resolve malloc/free via dlsym(RTLD_DEFAULT) in CleanerJava24Linker #17811
  • Wrap trailing ';' in Content-Disposition as ErrorDataDecoderException #17895
  • Avoid reflection when obtaining the process ID on Java 9+ #17873
  • Keep WINDOW_UPDATE credit of reserved HTTP/2 streams on activation #17611
  • IoUring: Apply IOV_MAX to each write instead of to all writes until submit #17932
  • Add consistent TLS certificate compression support #17548
  • Avoid unnecessary String allocation in WebSocketServerProtocolHandshakeHandler #16666
  • io_uring: Don't let msgHdrMemoryArray() clear the iovecs of a pending zero-copy write #17946
  • Refresh CA bundle before downloading the aarch64 GCC toolchain #17948
  • Accept empty non-final fragments in PerMessageDeflateEncoder #17943
  • Exclude the ProcessHandle stub from Surefire in common and buffer #17949
  • Verify toolchain downloads in release Dockerfiles against pinned SHA-256 #17940
  • HTTP/2: Don't pass the close promise to a deferred close #17955
  • Fix endless value iterators in ReadOnlyHttpHeaders #17961
  • Hash all 8-byte blocks in SipHash.macHash(...) when position is not 0 #17974
  • Fix AsciiString.contains(...) false negatives after a partial match #17975
  • Don't invert IP_MULTICAST_LOOP_DISABLED in NioDatagramChannelConfig #17969
  • Don't drop the last character in AsciiString.trim(CharSequence) #17968
  • Fix the region copied by Unpooled.copiedBuffer(CharSequence, int, int, Charset) #17971
  • Don't invert IP_MULTICAST_LOOP_DISABLED in NioDatagramChann… #17991
  • Treat DATA frames on reserved HTTP/2 streams as a connection error #17868
  • Http2: reject generic frames whose payload exceeds SETTINGS_MAX_FRAME_SIZE #17779
  • Don't loop forever in AbstractDiskHttpData when the file is short #17973
  • Check the second gzip magic byte in JdkZlibDecoder #17972
  • Reject reply codes with non-digit characters in SmtpResponseDecoder #17970
  • Return null or the default from read-only headers for invalid values #17967
  • MqttEncoder: Reject Variable Byte Integers larger than 268435455 #17984
  • Fix server-initiated WebSocket close handshake failing with "promise already done" #17983
  • Fix Snappy.encode(...) for input with a non-zero reader index #18019
  • Fill every remaining byte in the Java 8 SplittableRandom.nextBytes fallback #18009
  • Complete the TCP fast open connect before notifying the initial write #18008
  • Only delete socket files when binding and closing UDS channels #17980
  • Complete the TCP fast open connect before notifying the initial write… #18039
  • Use a long file offset when splicing a DefaultFileRegion with io_uring #18018
  • Read tv_nsec from the correct offset in QuicheSendInfo.getAtNanos #18045
  • Don't truncate the token length of QUIC Initial packets to an int #18046
  • Don't use a negative index in QuicCodecDispatcher #18048
  • Reject too long UDS paths in sendTo instead of truncating them #18022
  • Fix FastLz.readU16 when the reader index is not 0 #18054
  • Fail to encode DNS messages that are too large for TCP #18058
  • Return the haystack's reader index from ByteBufUtil.indexOf(...) for an empty needle #18073
  • Return -1 from StringUtil.decodeHexNibble(byte) for non-ASCII bytes #18072
  • Fix FastLz.readU16 when the reader index is not 0 #18077
  • Reject too long UDS paths in sendTo instead of truncating t… #18076
  • Don't return an entry twice when removing while iterating a primitive map #18070
  • Mark disk-based HttpData as completed after setting empty content #18069
  • Don't sign-extend the trailing bytes in SipHash #18047
  • Release a SPDY DATA frame that exceeds the session window #18089
  • Fix out-of-bounds read when validating UDS paths in the native code #18096
  • Update Brotli4j version to 1.24.0 #18097
  • Grow KQueueEventArray correctly in realloc #18102
  • Update Brotli4j version to 1.24.0 #18104
  • Grow KQueueEventArray correctly in realloc #18106
  • Send zero-length datagrams instead of dropping or duplicating them #18098
  • Read all pending data when the EOF is received before the connect is complete in kqueue #18091
  • Reject request-only and response-only pseudo-headers in invalid contexts (RFC 9113) #17752
  • Read the 4 byte Snappy literal length as unsigned #18056
  • Call FFM directly in the cleaners and link malloc/free on first use #17791
  • Deliver all data a LocalChannel peer wrote before it closed #18127
  • Make ZlibCertificateCompressionAlgorithm public #18131
  • Round up the NIO select timeout again to not busy spin #18138
  • Close an HTTP/2 stream only after its last merged DATA frame was written #18126
  • Use IP_MULTICAST_IF in leaveGroup and block without an interface #18122
  • Add opt-in Origin validation to WebSocketServerProtocolHandler (hardening) #17944
  • Add JDK27 profiles #18148
  • IoUring:Refactor io_uring write lifecycle management #17757
  • Don't lose the alert when the handshake fails in ReferenceCountedOpen… #18155
  • Fix buffer over-read in netty_boringssl_password_callback #18163
  • Fix freeing of invalid EVP_PKEY handle when parsing a private key fails #18159
  • Fix use of out-of-scope variable in netty_quiche_conn_new_scid #18162
  • Fix freeing of uninitialized dynamicMethods in netty_quiche_JNI_OnLoad #18161
  • Fix use of uninitialized pointers in quic_certificate_cb #18160
  • SslHandler: Size the unwrap output buffer for the plaintext, not the record #18028
  • Send bad_certificate alert when the TrustManager rejects the certificate #18164
  • IoUring: Verify the FileChannel is a FileChannelImpl before reading its fd #18192
  • Fix reporting of the wrong error when setting flags on an accepted fd fails #18201
  • KQueue: Verify the FileChannel is a FileChannelImpl before reading its fd #18204
  • Do not send uninitialized stack memory when sending a fd over a domain socket #18209
  • Fix underflow detection in netty_unix_util_timespec_subtract_ns #18214
  • Epoll: Verify the FileChannel is a FileChannelImpl before reading its fd #18202
  • Epoll: Fix signed integer overflow when calculating the epoll_wait timeout #18213
  • Fix read of uninitialized memory when accepting a connection on a domain socket #18212
  • Don't encode Snappy copies with an offset that does not fit into 16 bits #18055
  • Don't truncate binary memcache key and extras lengths #18041
  • Update to latest netty-tcnative release #18231
  • Security fixes #18237

For more details please see the complete release notes.

Thank You

Every idea and bug-report counts, and so we thought it is worth mentioning those who helped in this area.

Please report an unintended omission.