From ba2bb0858969aebfe6d83090ecfbcb8c10356486 Mon Sep 17 00:00:00 2001 From: Marius Lichtblau Date: Mon, 13 Oct 2025 17:58:04 +0200 Subject: [PATCH] Release DataBuffer in AbstractCharSequenceDecoder if String creation fails See gh-35625 Signed-off-by: Marius Lichtblau --- .../codec/AbstractCharSequenceDecoder.java | 20 +++++++++++-------- .../io/buffer/DataBufferLimitException.java | 4 ++++ .../core/io/buffer/NettyDataBuffer.java | 7 ++++++- 3 files changed, 22 insertions(+), 9 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 65fbdc51b0b..07dee48b0b9 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 @@ public abstract class AbstractCharSequenceDecoder extend 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) { 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 eaeac1b9410..1ac65333368 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 class DataBufferLimitException extends IllegalStateException { 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 7ba28200d68..28a9eede4ac 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 @@ -379,7 +379,12 @@ public class NettyDataBuffer implements PooledDataBuffer { @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); + } }