From a19b51b7e0c7763c6992cf113b6dbdfe00f58451 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Mon, 29 Sep 2025 09:29:34 +0100 Subject: [PATCH] Handle invalid position in ResourceHttpMessageWriter Closes gh-35536 --- .../http/codec/ResourceHttpMessageWriter.java | 16 +++++++++++++--- .../codec/ResourceHttpMessageWriterTests.java | 9 +++++++++ 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/http/codec/ResourceHttpMessageWriter.java b/spring-web/src/main/java/org/springframework/http/codec/ResourceHttpMessageWriter.java index 7c7e9573713..3a32540e0e4 100644 --- a/spring-web/src/main/java/org/springframework/http/codec/ResourceHttpMessageWriter.java +++ b/spring-web/src/main/java/org/springframework/http/codec/ResourceHttpMessageWriter.java @@ -233,8 +233,7 @@ public class ResourceHttpMessageWriter implements HttpMessageWriter { ranges = request.getHeaders().getRange(); } catch (IllegalArgumentException ex) { - response.setStatusCode(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE); - return response.setComplete(); + return handleInvalidRange(response); } return Mono.from(inputStream).flatMap(resource -> { @@ -242,7 +241,13 @@ public class ResourceHttpMessageWriter implements HttpMessageWriter { return writeResource(resource, elementType, mediaType, response, hints); } response.setStatusCode(HttpStatus.PARTIAL_CONTENT); - List regions = HttpRange.toResourceRegions(ranges, resource); + List regions; + try { + regions = HttpRange.toResourceRegions(ranges, resource); + } + catch (IllegalArgumentException ex) { + return handleInvalidRange(response); + } MediaType resourceMediaType = getResourceMediaType(mediaType, resource, hints); if (regions.size() == 1){ ResourceRegion region = regions.get(0); @@ -268,6 +273,11 @@ public class ResourceHttpMessageWriter implements HttpMessageWriter { }); } + private static Mono handleInvalidRange(ServerHttpResponse response) { + response.setStatusCode(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE); + return response.setComplete(); + } + private Mono writeSingleRegion(ResourceRegion region, ReactiveHttpOutputMessage message, Map hints) { diff --git a/spring-web/src/test/java/org/springframework/http/codec/ResourceHttpMessageWriterTests.java b/spring-web/src/test/java/org/springframework/http/codec/ResourceHttpMessageWriterTests.java index 19af37c5610..436513a3fb6 100644 --- a/spring-web/src/test/java/org/springframework/http/codec/ResourceHttpMessageWriterTests.java +++ b/spring-web/src/test/java/org/springframework/http/codec/ResourceHttpMessageWriterTests.java @@ -156,6 +156,15 @@ class ResourceHttpMessageWriterTests { assertThat(this.response.getStatusCode()).isEqualTo(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE); } + @Test // gh-35536 + void invalidRangePosition() { + + testWrite(get("/").header(HttpHeaders.RANGE, "bytes=2000-5000").build()); + + assertThat(this.response.getHeaders().getFirst(HttpHeaders.ACCEPT_RANGES)).isEqualTo("bytes"); + assertThat(this.response.getStatusCode()).isEqualTo(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE); + } + private void testWrite(MockServerHttpRequest request) { Mono mono = this.writer.write(this.input, null, null, TEXT_PLAIN, request, this.response, HINTS);