From bf36f49dc5454dae4d21ead33474eb3783d34a05 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Thu, 7 Nov 2019 09:09:42 +0100 Subject: [PATCH] Corrupt multipart should not hang SynchronossPartHttpMessageReader This commit notifies the Synchronoss listener that the buffer stream has ended. Closes gh-23768 --- .../SynchronossPartHttpMessageReader.java | 7 +++++++ ...SynchronossPartHttpMessageReaderTests.java | 20 +++++++++++++++++++ .../http/codec/multipart/invalid.multipart | 5 +++++ 3 files changed, 32 insertions(+) create mode 100644 spring-web/src/test/resources/org/springframework/http/codec/multipart/invalid.multipart diff --git a/spring-web/src/main/java/org/springframework/http/codec/multipart/SynchronossPartHttpMessageReader.java b/spring-web/src/main/java/org/springframework/http/codec/multipart/SynchronossPartHttpMessageReader.java index 47f40fccf6..c303b1f7e7 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/multipart/SynchronossPartHttpMessageReader.java +++ b/spring-web/src/main/java/org/springframework/http/codec/multipart/SynchronossPartHttpMessageReader.java @@ -261,6 +261,13 @@ public class SynchronossPartHttpMessageReader extends LoggingCodecSupport implem } } + @Override + protected void hookOnComplete() { + if (this.listener != null) { + this.listener.onAllPartsFinished(); + } + } + @Override protected void hookFinally(SignalType type) { try { diff --git a/spring-web/src/test/java/org/springframework/http/codec/multipart/SynchronossPartHttpMessageReaderTests.java b/spring-web/src/test/java/org/springframework/http/codec/multipart/SynchronossPartHttpMessageReaderTests.java index 8533dd426d..8c09becc43 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/multipart/SynchronossPartHttpMessageReaderTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/multipart/SynchronossPartHttpMessageReaderTests.java @@ -18,6 +18,7 @@ package org.springframework.http.codec.multipart; import java.io.File; import java.io.IOException; +import java.nio.channels.ReadableByteChannel; import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.Map; @@ -46,6 +47,7 @@ import org.springframework.mock.http.server.reactive.test.MockServerHttpRequest; import org.springframework.util.MultiValueMap; import static java.util.Collections.emptyMap; +import static java.util.Collections.singletonMap; import static org.assertj.core.api.Assertions.assertThat; import static org.springframework.core.ResolvableType.forClassWithGenerics; import static org.springframework.http.HttpHeaders.CONTENT_TYPE; @@ -142,6 +144,24 @@ public class SynchronossPartHttpMessageReaderTests extends AbstractLeakCheckingT subscriber.cancel(); } + @Test + void gh23768() throws IOException { + ReadableByteChannel channel = new ClassPathResource("invalid.multipart", getClass()).readableChannel(); + Flux body = DataBufferUtils.readByteChannel(() -> channel, this.bufferFactory, 1024); + + MediaType contentType = new MediaType("multipart", "form-data", + singletonMap("boundary", "NbjrKgjbsaMLdnMxMfDpD6myWomYc0qNX0w")); + ServerHttpRequest request = MockServerHttpRequest.post("/") + .contentType(contentType) + .body(body); + + Mono> parts = this.reader.readMono(PARTS_ELEMENT_TYPE, request, emptyMap()); + + StepVerifier.create(parts) + .assertNext(result -> assertThat(result).isEmpty()) + .verifyComplete(); + } + @Test void readTooManyParts() { testMultipartExceptions(reader -> reader.setMaxParts(1), ex -> { diff --git a/spring-web/src/test/resources/org/springframework/http/codec/multipart/invalid.multipart b/spring-web/src/test/resources/org/springframework/http/codec/multipart/invalid.multipart new file mode 100644 index 0000000000..9f09680d04 --- /dev/null +++ b/spring-web/src/test/resources/org/springframework/http/codec/multipart/invalid.multipart @@ -0,0 +1,5 @@ +--NbjrKgjbsaMLdnMxMfDpD6myWomYc0qNX0w +Content-Disposition: form-data; name="part-00-name" + +post-payload-text-23456789ABCDEF:post-payload-0001-3456789ABCDEF:post-payload-0002-3456789ABCDEF:post-payload-0003-3456789ABCDEF +--NbjrKgjbsaMLdnMxMfDpD6myWomYc -- GitLab