From c227c08a95b0480941c81b705ae860416166ee8a Mon Sep 17 00:00:00 2001 From: 17krishna8 <17krishna8@users.noreply.github.com> Date: Sat, 17 Oct 2026 04:31:52 +0000 Subject: [PATCH] May ignore a Range header whose value is not well-formed A Range header whose value does not hold up when parsed made a resource request fail with NumberFormatException or ArrayIndexOutOfBoundsException instead of serving the resource: 'bytes=5' has no dash to split on, 'bytes=1-x' and numbers beyond the long range fail the number parsing, and a value without a '=' separator fed the whole header text to the parser. RFC 9110, section 14.2, lets a server ignore a Range header with an invalid ranges-specifier, so such a request now falls back to serving the whole resource: the content range meta data is only set for a header of the form bytes=- where both parts are valid long values. --- .../PackageResourceReferenceTest.java | 8 ++++ .../request/resource/AbstractResource.java | 43 ++++++++++++------- 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/wicket-core-tests/src/test/java/org/apache/wicket/core/request/resource/PackageResourceReferenceTest.java b/wicket-core-tests/src/test/java/org/apache/wicket/core/request/resource/PackageResourceReferenceTest.java index 3e230660255..1d1457bfba9 100644 --- a/wicket-core-tests/src/test/java/org/apache/wicket/core/request/resource/PackageResourceReferenceTest.java +++ b/wicket-core-tests/src/test/java/org/apache/wicket/core/request/resource/PackageResourceReferenceTest.java @@ -298,6 +298,14 @@ void testContentRange() assertEquals("var_style_en.txt", makeRangeRequest("bytes=9-")); assertEquals("resource_var_style_en.txt", makeRangeRequest("bytes=-")); assertEquals("resource_var_style_en.txt", makeRangeRequest("bytes=-25")); + + // malformed ranges are ignored + assertEquals("resource_var_style_en.txt", makeRangeRequest("bytes=5")); + assertEquals("resource_var_style_en.txt", makeRangeRequest("bytes=abc")); + assertEquals("resource_var_style_en.txt", makeRangeRequest("bytes=1-x")); + assertEquals("resource_var_style_en.txt", + makeRangeRequest("bytes=99999999999999999999-")); + assertEquals("resource_var_style_en.txt", makeRangeRequest("bytes 5-10")); } private String makeRangeRequest(String range) diff --git a/wicket-core/src/main/java/org/apache/wicket/request/resource/AbstractResource.java b/wicket-core/src/main/java/org/apache/wicket/request/resource/AbstractResource.java index 91464131df8..dbb8af03400 100644 --- a/wicket-core/src/main/java/org/apache/wicket/request/resource/AbstractResource.java +++ b/wicket-core/src/main/java/org/apache/wicket/request/resource/AbstractResource.java @@ -732,25 +732,38 @@ protected void setRequestRangeMetaData(WebRequest webRequest) // fixing white spaces rangeHeader = rangeHeader.replaceAll(" ", ""); - String range = rangeHeader.substring(rangeHeader.indexOf('=') + 1, - rangeHeader.length()); - - // support only the first range (WICKET-5995) - final int idxOfComma = range.indexOf(','); - String firstRange = idxOfComma > -1 ? range.substring(0, idxOfComma) : range; + int eqIndex = rangeHeader.indexOf('='); - String[] rangeParts = Strings.split(firstRange, '-'); + String range = eqIndex > -1 ? rangeHeader.substring(eqIndex + 1) : null; - String startByteString = rangeParts[0]; - String endByteString = rangeParts[1]; + if (range != null) + { + // support only the first range (WICKET-5995) + final int idxOfComma = range.indexOf(','); + String firstRange = idxOfComma > -1 ? range.substring(0, idxOfComma) : range; - long startbyte = !Strings.isEmpty(startByteString) ? Long.parseLong(startByteString) : 0; - long endbyte = !Strings.isEmpty(endByteString) ? Long.parseLong(endByteString) : -1; + String[] rangeParts = Strings.split(firstRange, '-'); - // Make the content range information available for the whole request cycle - RequestCycle requestCycle = RequestCycle.get(); - requestCycle.setMetaData(CONTENT_RANGE_STARTBYTE, startbyte); - requestCycle.setMetaData(CONTENT_RANGE_ENDBYTE, endbyte); + if (rangeParts.length == 2) + { + try + { + long startbyte = !Strings.isEmpty(rangeParts[0]) + ? Long.parseLong(rangeParts[0]) : 0; + long endbyte = !Strings.isEmpty(rangeParts[1]) + ? Long.parseLong(rangeParts[1]) : -1; + + // Make the content range information available for the whole request cycle + RequestCycle requestCycle = RequestCycle.get(); + requestCycle.setMetaData(CONTENT_RANGE_STARTBYTE, startbyte); + requestCycle.setMetaData(CONTENT_RANGE_ENDBYTE, endbyte); + } + catch (NumberFormatException e) + { + // a malformed range is ignored and the whole resource is served + } + } + } } }