Projects
openEuler:24.03:SP1:Everything
netty
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 7
View file
_service:tar_scm:netty.spec
Changed
@@ -2,7 +2,7 @@ Name: netty Version: 4.1.13 -Release: 21 +Release: 22 Summary: Asynchronous event-driven network application Java framework License: ASL 2.0 URL: https://netty.io/ @@ -32,6 +32,7 @@ Patch0021: fix-strip.patch # https://github.com/netty/netty/commit/cd91cf3c99123bd1e53fd6a1de0e3d1922f05bb2 Patch0022: CVE-2022-41881.patch +Patch0023: CVE-2024-29025.patch BuildRequires: maven-local mvn(ant-contrib:ant-contrib) BuildRequires: mvn(com.jcraft:jzlib) mvn(commons-logging:commons-logging) @@ -156,6 +157,9 @@ %changelog +* Tue Nov 12 2024 yaoxin <yao_xin001@hoperun.com> - 4.1.13-22 +- Fix CVE-2024-29025 + * Wed Dec 13 2023 yaoxin <yao_xin001@hoperun.com> - 4.1.13-21 - Fix CVE-2022-41881
View file
_service:tar_scm:CVE-2024-29025.patch
Added
@@ -0,0 +1,411 @@ +From: Markus Koschany <apo@debian.org> +Date: Sat, 11 May 2024 21:52:15 +0200 +Subject: CVE-2024-29025 + +Bug-Debian: https://bugs.debian.org/1068110 +Origin: https://github.com/netty/netty/commit/0d0c6ed782d13d423586ad0c71737b2c7d02058c +--- + .../HttpPostMultipartRequestDecoder.java | 41 +++++++ + .../multipart/HttpPostRequestDecoder.java | 70 ++++++++++++ + .../HttpPostStandardRequestDecoder.java | 44 ++++++++ + .../multipart/HttpPostRequestDecoderTest.java | 103 ++++++++++++++++++ + 4 files changed, 258 insertions(+) + +diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostMultipartRequestDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostMultipartRequestDecoder.java +index 17c3e64..7cac6a0 100644 +--- a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostMultipartRequestDecoder.java ++++ b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostMultipartRequestDecoder.java +@@ -61,6 +61,16 @@ public class HttpPostMultipartRequestDecoder implements InterfaceHttpPostRequest + */ + private final HttpRequest request; + ++ /** ++ * The maximum number of fields allows by the form ++ */ ++ private final int maxFields; ++ ++ /** ++ * The maximum number of accumulated bytes when decoding a field ++ */ ++ private final int maxBufferedBytes; ++ + /** + * Default charset to use + */ +@@ -172,9 +182,34 @@ public class HttpPostMultipartRequestDecoder implements InterfaceHttpPostRequest + * errors + */ + public HttpPostMultipartRequestDecoder(HttpDataFactory factory, HttpRequest request, Charset charset) { ++ this(factory, request, charset, HttpPostRequestDecoder.DEFAULT_MAX_FIELDS, HttpPostRequestDecoder.DEFAULT_MAX_BUFFERED_BYTES); ++ } ++ ++ /** ++ * ++ * @param factory ++ * the factory used to create InterfaceHttpData ++ * @param request ++ * the request to decode ++ * @param charset ++ * the charset to use as default ++ * @param maxFields ++ * the maximum number of fields the form can have, {@code -1} to disable ++ * @param maxBufferedBytes ++ * the maximum number of bytes the decoder can buffer when decoding a field, {@code -1} to disable ++ * @throws NullPointerException ++ * for request or charset or factory ++ * @throws ErrorDataDecoderException ++ * if the default charset was wrong when decoding or other ++ * errors ++ */ ++ public HttpPostMultipartRequestDecoder(HttpDataFactory factory, HttpRequest request, Charset charset, ++ int maxFields, int maxBufferedBytes) { + this.request = checkNotNull(request, "request"); + this.charset = checkNotNull(charset, "charset"); + this.factory = checkNotNull(factory, "factory"); ++ this.maxFields = maxFields; ++ this.maxBufferedBytes = maxBufferedBytes; + // Fill default values + + setMultipart(this.request.headers().get(HttpHeaderNames.CONTENT_TYPE)); +@@ -333,6 +368,9 @@ public class HttpPostMultipartRequestDecoder implements InterfaceHttpPostRequest + isLastChunk = true; + } + parseBody(); ++ if (maxBufferedBytes > 0 && undecodedChunk != null && undecodedChunk.readableBytes() > maxBufferedBytes) { ++ throw new HttpPostRequestDecoder.TooLongFormFieldException(); ++ } + if (undecodedChunk != null && undecodedChunk.writerIndex() > discardThreshold) { + undecodedChunk.discardReadBytes(); + } +@@ -417,6 +455,9 @@ public class HttpPostMultipartRequestDecoder implements InterfaceHttpPostRequest + if (data == null) { + return; + } ++ if (maxFields > 0 && bodyListHttpData.size() >= maxFields) { ++ throw new HttpPostRequestDecoder.TooManyFormFieldsException(); ++ } + List<InterfaceHttpData> datas = bodyMapHttpData.get(data.getName()); + if (datas == null) { + datas = new ArrayList<InterfaceHttpData>(1); +diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestDecoder.java +index 0c10626..d57b63e 100644 +--- a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestDecoder.java ++++ b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostRequestDecoder.java +@@ -25,6 +25,7 @@ import io.netty.util.internal.StringUtil; + + import java.nio.charset.Charset; + import java.util.List; ++import io.netty.util.internal.ObjectUtil; + + /** + * This decoder will decode Body and can handle POST BODY. +@@ -36,6 +37,10 @@ public class HttpPostRequestDecoder implements InterfaceHttpPostRequestDecoder { + + static final int DEFAULT_DISCARD_THRESHOLD = 10 * 1024 * 1024; + ++ static final int DEFAULT_MAX_FIELDS = 128; ++ ++ static final int DEFAULT_MAX_BUFFERED_BYTES = 1024; ++ + private final InterfaceHttpPostRequestDecoder decoder; + + /** +@@ -52,6 +57,25 @@ public class HttpPostRequestDecoder implements InterfaceHttpPostRequestDecoder { + this(new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE), request, HttpConstants.DEFAULT_CHARSET); + } + ++ /** ++ * ++ * @param request ++ * the request to decode ++ * @param maxFields ++ * the maximum number of fields the form can have, {@code -1} to disable ++ * @param maxBufferedBytes ++ * the maximum number of bytes the decoder can buffer when decoding a field, {@code -1} to disable ++ * @throws NullPointerException ++ * for request ++ * @throws ErrorDataDecoderException ++ * if the default charset was wrong when decoding or other ++ * errors ++ */ ++ public HttpPostRequestDecoder(HttpRequest request, int maxFields, int maxBufferedBytes) { ++ this(new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE), request, HttpConstants.DEFAULT_CHARSET, ++ maxFields, maxBufferedBytes); ++ } ++ + /** + * + * @param factory +@@ -100,6 +124,38 @@ public class HttpPostRequestDecoder implements InterfaceHttpPostRequestDecoder { + } + } + ++ /** ++ * ++ * @param factory ++ * the factory used to create InterfaceHttpData ++ * @param request ++ * the request to decode ++ * @param charset ++ * the charset to use as default ++ * @param maxFields ++ * the maximum number of fields the form can have, {@code -1} to disable ++ * @param maxBufferedBytes ++ * the maximum number of bytes the decoder can buffer when decoding a field, {@code -1} to disable ++ * @throws NullPointerException ++ * for request or charset or factory ++ * @throws ErrorDataDecoderException ++ * if the default charset was wrong when decoding or other ++ * errors ++ */ ++ public HttpPostRequestDecoder(HttpDataFactory factory, HttpRequest request, Charset charset, ++ int maxFields, int maxBufferedBytes) { ++ ObjectUtil.checkNotNull(factory, "factory"); ++ ObjectUtil.checkNotNull(request, "request"); ++ ObjectUtil.checkNotNull(charset, "charset"); ++ ++ // Fill default values ++ if (isMultipart(request)) { ++ decoder = new HttpPostMultipartRequestDecoder(factory, request, charset, maxFields, maxBufferedBytes); ++ } else { ++ decoder = new HttpPostStandardRequestDecoder(factory, request, charset, maxFields, maxBufferedBytes); ++ } ++ } ++ + /** + * states follow NOTSTARTED PREAMBLE ( (HEADERDELIMITER DISPOSITION (FIELD | + * FILEUPLOAD))* (HEADERDELIMITER DISPOSITION MIXEDPREAMBLE (MIXEDDELIMITER +@@ -342,4 +398,18 @@ public class HttpPostRequestDecoder implements InterfaceHttpPostRequestDecoder { + super(msg, cause); + } + } ++ ++ /** ++ * Exception when the maximum number of fields for a given form is reached ++ */ ++ public static final class TooManyFormFieldsException extends DecoderException { ++ private static final long serialVersionUID = 1336267941020800769L; ++ } ++ ++ /** ++ * Exception when a field content is too long ++ */ ++ public static final class TooLongFormFieldException extends DecoderException { ++ private static final long serialVersionUID = 1336267941020800769L; ++ } + } +diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostStandardRequestDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostStandardRequestDecoder.java +index ece64d8..65a9e16 100644 +--- a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostStandardRequestDecoder.java ++++ b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostStandardRequestDecoder.java +@@ -16,6 +16,7 @@ + package io.netty.handler.codec.http.multipart; + + import io.netty.buffer.ByteBuf; ++import io.netty.handler.codec.DecoderException; + import io.netty.handler.codec.http.HttpConstants; + import io.netty.handler.codec.http.HttpContent; + import io.netty.handler.codec.http.HttpRequest; +@@ -26,6 +27,8 @@ import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.EndOfDataDec + import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.ErrorDataDecoderException; + import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.MultiPartStatus; + import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.NotEnoughDataDecoderException; ++import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.TooManyFormFieldsException; ++import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.TooLongFormFieldException; + + import java.io.IOException; + import java.nio.charset.Charset; +@@ -60,6 +63,16 @@ public class HttpPostStandardRequestDecoder implements InterfaceHttpPostRequestD + */ + private final Charset charset; + ++ /** ++ * The maximum number of fields allows by the form ++ */ ++ private final int maxFields; ++ ++ /** ++ * The maximum number of accumulated bytes when decoding a field ++ */ ++ private final int maxBufferedBytes; ++ + /** + * Does the last chunk already received + */ +@@ -145,9 +158,34 @@ public class HttpPostStandardRequestDecoder implements InterfaceHttpPostRequestD + * errors + */ + public HttpPostStandardRequestDecoder(HttpDataFactory factory, HttpRequest request, Charset charset) { ++ this(factory, request, charset, HttpPostRequestDecoder.DEFAULT_MAX_FIELDS, HttpPostRequestDecoder.DEFAULT_MAX_BUFFERED_BYTES); ++ } ++ ++ /** ++ * ++ * @param factory ++ * the factory used to create InterfaceHttpData ++ * @param request ++ * the request to decode ++ * @param charset ++ * the charset to use as default ++ * @param maxFields ++ * the maximum number of fields the form can have, {@code -1} to disable ++ * @param maxBufferedBytes ++ * the maximum number of bytes the decoder can buffer when decoding a field, {@code -1} to disable ++ * @throws NullPointerException ++ * for request or charset or factory ++ * @throws ErrorDataDecoderException ++ * if the default charset was wrong when decoding or other ++ * errors ++ */ ++ public HttpPostStandardRequestDecoder(HttpDataFactory factory, HttpRequest request, Charset charset, ++ int maxFields, int maxBufferedBytes) { + this.request = checkNotNull(request, "request"); + this.charset = checkNotNull(charset, "charset"); + this.factory = checkNotNull(factory, "factory"); ++ this.maxFields = maxFields; ++ this.maxBufferedBytes = maxBufferedBytes; + if (request instanceof HttpContent) { + // Offer automatically if the given request is als type of HttpContent + // See #1089 +@@ -287,6 +325,9 @@ public class HttpPostStandardRequestDecoder implements InterfaceHttpPostRequestD + isLastChunk = true; + } + parseBody(); ++ if (maxBufferedBytes > 0 && undecodedChunk != null && undecodedChunk.readableBytes() > maxBufferedBytes) { ++ throw new TooLongFormFieldException(); ++ } + if (undecodedChunk != null && undecodedChunk.writerIndex() > discardThreshold) { + undecodedChunk.discardReadBytes(); + } +@@ -367,6 +408,9 @@ public class HttpPostStandardRequestDecoder implements InterfaceHttpPostRequestD + if (data == null) { + return; + } ++ if (maxFields > 0 && bodyListHttpData.size() >= maxFields) { ++ throw new TooManyFormFieldsException(); ++ } + List<InterfaceHttpData> datas = bodyMapHttpData.get(data.getName()); + if (datas == null) { + datas = new ArrayList<InterfaceHttpData>(1); +diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/multipart/HttpPostRequestDecoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/multipart/HttpPostRequestDecoderTest.java +index 1334107..bdc5fd7 100644 +--- a/codec-http/src/test/java/io/netty/handler/codec/http/multipart/HttpPostRequestDecoderTest.java ++++ b/codec-http/src/test/java/io/netty/handler/codec/http/multipart/HttpPostRequestDecoderTest.java +@@ -19,6 +19,7 @@ import io.netty.buffer.ByteBuf; + import io.netty.buffer.ByteBufAllocator; + import io.netty.buffer.Unpooled; + import io.netty.buffer.UnpooledByteBufAllocator; ++import io.netty.handler.codec.DecoderException; + import io.netty.handler.codec.DecoderResult; + import io.netty.handler.codec.http.DefaultFullHttpRequest; + import io.netty.handler.codec.http.DefaultHttpContent; +@@ -491,4 +492,106 @@ public class HttpPostRequestDecoderTest { + content.release(); + } + } ++ ++ @Test ++ public void testTooManyFormFieldsPostStandardDecoder() { ++ HttpRequest req = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, "/"); ++ ++ HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(req, 1024, -1); ++ ++ int num = 0; ++ while (true) { ++ try { ++ decoder.offer(new DefaultHttpContent(Unpooled.wrappedBuffer("foo=bar&".getBytes()))); ++ } catch (DecoderException e) { ++ assertEquals(HttpPostRequestDecoder.TooManyFormFieldsException.class, e.getClass()); ++ break; ++ } ++ assertTrue(num++ < 1024); ++ } ++ assertEquals(1024, num); ++ } ++ ++ @Test ++ public void testTooManyFormFieldsPostMultipartDecoder() { ++ HttpRequest req = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, "/"); ++ req.headers().add("Content-Type", "multipart/form-data;boundary=be38b42a9ad2713f"); ++ ++ HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(req, 1024, -1); ++ decoder.offer(new DefaultHttpContent(Unpooled.wrappedBuffer("--be38b42a9ad2713f\n".getBytes()))); ++ ++ int num = 0; ++ while (true) { ++ try { ++ byte bodyBytes = ("content-disposition: form-data; name=\"title\"\n" + ++ "content-length: 10\n" + ++ "content-type: text/plain; charset=UTF-8\n" + ++ "\n" + ++ "bar-stream\n" + ++ "--be38b42a9ad2713f\n").getBytes(); ++ ByteBuf content = Unpooled.wrappedBuffer(bodyBytes); ++ decoder.offer(new DefaultHttpContent(content)); ++ } catch (DecoderException e) { ++ assertEquals(HttpPostRequestDecoder.TooManyFormFieldsException.class, e.getClass()); ++ break; ++ } ++ assertTrue(num++ < 1024); ++ } ++ assertEquals(1024, num); ++ } ++ ++ @Test ++ public void testTooLongFormFieldStandardDecoder() { ++ HttpRequest req = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, "/"); ++ ++ HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(req, -1, 16 * 1024); ++ ++ try { ++ decoder.offer(new DefaultHttpContent(Unpooled.wrappedBuffer(new byte16 * 1024 + 1))); ++ fail(); ++ } catch (DecoderException e) { ++ assertEquals(HttpPostRequestDecoder.TooLongFormFieldException.class, e.getClass()); ++ } ++ } ++ ++ @Test ++ public void testFieldGreaterThanMaxBufferedBytesStandardDecoder() { ++ HttpRequest req = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, "/"); ++ ++ HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(req, -1, 6); ++ ++ decoder.offer(new DefaultHttpContent(Unpooled.wrappedBuffer("foo=bar".getBytes()))); ++ } ++ ++ @Test ++ public void testTooLongFormFieldMultipartDecoder() { ++ HttpRequest req = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, "/"); ++ req.headers().add("Content-Type", "multipart/form-data;boundary=be38b42a9ad2713f"); ++ ++ HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(req, -1, 16 * 1024); ++ ++ try { ++ decoder.offer(new DefaultHttpContent(Unpooled.wrappedBuffer(new byte16 * 1024 + 1))); ++ fail(); ++ } catch (DecoderException e) { ++ assertEquals(HttpPostRequestDecoder.TooLongFormFieldException.class, e.getClass()); ++ } ++ } ++ ++ @Test ++ public void testFieldGreaterThanMaxBufferedBytesMultipartDecoder() { ++ HttpRequest req = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, "/"); ++ req.headers().add("Content-Type", "multipart/form-data;boundary=be38b42a9ad2713f"); ++ ++ byte bodyBytes = ("content-disposition: form-data; name=\"title\"\n" + ++ "content-length: 10\n" + ++ "content-type: text/plain; charset=UTF-8\n" + ++ "\n" + ++ "bar-stream\n" + ++ "--be38b42a9ad2713f\n").getBytes(); ++ ++ HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(req, -1, bodyBytes.length - 1); ++ ++ decoder.offer(new DefaultHttpContent(Unpooled.wrappedBuffer(bodyBytes))); ++ } + } +-- +2.47.0 +
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2