From 8886fd0b5d0915ab95fd6cc4a68d4b4b32fc8015 Mon Sep 17 00:00:00 2001 From: Marius Lichtblau Date: Mon, 13 Oct 2025 17:58:04 +0200 Subject: [PATCH 1/2] Release data buffer even when String decoding fails Closes gh-35614 Signed-off-by: Marius Lichtblau --- .../codec/AbstractCharSequenceDecoder.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/core/codec/AbstractCharSequenceDecoder.java b/spring-core/src/main/java/org/springframework/core/codec/AbstractCharSequenceDecoder.java index 129da247b039..1918d7182db9 100644 --- a/spring-core/src/main/java/org/springframework/core/codec/AbstractCharSequenceDecoder.java +++ b/spring-core/src/main/java/org/springframework/core/codec/AbstractCharSequenceDecoder.java @@ -175,14 +175,18 @@ private Collection processDataBuffer(DataBuffer buffer, DataBufferUt public final T decode(DataBuffer dataBuffer, ResolvableType elementType, @Nullable MimeType mimeType, @Nullable Map hints) { - Charset charset = getCharset(mimeType); - T value = decodeInternal(dataBuffer, charset); - DataBufferUtils.release(dataBuffer); - LogFormatUtils.traceDebug(logger, traceOn -> { - String formatted = LogFormatUtils.formatValue(value, !traceOn); - return Hints.getLogPrefix(hints) + "Decoded " + formatted; - }); - return value; + try { + Charset charset = getCharset(mimeType); + T value = decodeInternal(dataBuffer, charset); + LogFormatUtils.traceDebug(logger, traceOn -> { + String formatted = LogFormatUtils.formatValue(value, !traceOn); + return Hints.getLogPrefix(hints) + "Decoded " + formatted; + }); + return value; + } + finally { + DataBufferUtils.release(dataBuffer); + } } private Charset getCharset(@Nullable MimeType mimeType) { From e9753758e1b4b04ea8b138d83774f53194852fc1 Mon Sep 17 00:00:00 2001 From: Marius Lichtblau Date: Tue, 14 Oct 2025 11:28:52 +0200 Subject: [PATCH 2/2] Handle exception when ByteBuf is converted to String Handle OutOfMemoryError raised by StringUTF16 when the length of the string exceeds StringUTF16.MAX_LENGTH Signed-off-by: Marius Lichtblau --- .../core/io/buffer/DataBufferLimitException.java | 4 ++++ .../springframework/core/io/buffer/NettyDataBuffer.java | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/spring-core/src/main/java/org/springframework/core/io/buffer/DataBufferLimitException.java b/spring-core/src/main/java/org/springframework/core/io/buffer/DataBufferLimitException.java index eaeac1b94104..1ac653333682 100644 --- a/spring-core/src/main/java/org/springframework/core/io/buffer/DataBufferLimitException.java +++ b/spring-core/src/main/java/org/springframework/core/io/buffer/DataBufferLimitException.java @@ -35,4 +35,8 @@ public DataBufferLimitException(String message) { super(message); } + public DataBufferLimitException(String message, Throwable cause) { + super(message, cause); + } + } diff --git a/spring-core/src/main/java/org/springframework/core/io/buffer/NettyDataBuffer.java b/spring-core/src/main/java/org/springframework/core/io/buffer/NettyDataBuffer.java index fc9bda027dcd..da376b14a1d8 100644 --- a/spring-core/src/main/java/org/springframework/core/io/buffer/NettyDataBuffer.java +++ b/spring-core/src/main/java/org/springframework/core/io/buffer/NettyDataBuffer.java @@ -374,7 +374,12 @@ public int hashCode() { @Override public String toString() { - return this.byteBuf.toString(); + try { + return this.byteBuf.toString(); + } + catch (OutOfMemoryError ex) { + throw new DataBufferLimitException("Failed to convert data buffer to string: " + ex.getMessage(), ex); + } }