[ 
https://issues.apache.org/jira/browse/HDDS-16336?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18109602#comment-18109602
 ] 

Chi-Hsuan Huang commented on HDDS-16336:
----------------------------------------

{quote}do not put the inverted check before start >= length, or bytes=11-10 
would change from 416 to 200. - 
HDDS-16336(https://issues.apache.org/jira/browse/HDDS-16336)
{quote}
Thanks [~marktsai]  AWS comparison really helps. 👍 Just curious, did you happen 
to measure `bytes=11-10` on AWS too? If it differs, should we follow up?

> S3 GET inverted Range with start inside object yields negative Content-Length
> -----------------------------------------------------------------------------
>
>                 Key: HDDS-16336
>                 URL: https://issues.apache.org/jira/browse/HDDS-16336
>             Project: Apache Ozone
>          Issue Type: Bug
>            Reporter: Meng-Shuan Tsai
>            Assignee: Meng-Shuan Tsai
>            Priority: Major
>              Labels: pull-request-available
>
> h3. What
> Bug in S3 Gateway GetObject. When {{Range}} is inverted ({{start > end}}) but 
> {{start}} is still inside the object (e.g. object length 10, {{Range: 
> bytes=8-3}}), the gateway prepares HTTP 206 with a *negative* 
> {{Content-Length}} and then fails while streaming with 
> {{NegativeArraySizeException}}.
> A satisfiable range ({{bytes=0-8}}) already returns 206. An unsatisfiable 
> range whose start is past the last byte ({{bytes=11-20}}) already returns 416 
> {{InvalidRange}}. This ticket is only the inverted-but-in-bounds case.
> h3. Steps to reproduce
> # Put a 10-byte object.
> # {{GET}} with header {{Range: bytes=8-3}}.
> Observed: request does not complete as 200/206/416; streaming allocates {{new 
> byte[getIOBufferSize(-4)]}} and throws {{NegativeArraySizeException}}.
> h3. Root cause
> {{RangeHeaderParserUtil.parseRangeHeader}} does not check {{start > end}} 
> when {{start < length}}:
> [RangeHeaderParserUtil.java 
> (L69–L81)|https://github.com/apache/ozone/blob/79464b60d7661e89a5d934623a6998f7aff6cbca/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/util/RangeHeaderParserUtil.java#L69-L81]
> {code:java}
> } else {
>   if (end >= length) {
>     end = length - 1;
>   }
> }
> {code}
> Result for {{bytes=8-3}}, length 10: {{start=8}}, {{end=3}}, 
> {{readFull=false}}, {{inValidRange=false}}.
> {{ObjectEndpoint.handleGetRequest}} then treats it as a partial read:
> * {{copyLength = end - start + 1 = -4}} ([ObjectEndpoint.java 
> L449|https://github.com/apache/ozone/blob/79464b60d7661e89a5d934623a6998f7aff6cbca/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ObjectEndpoint.java#L449])
> * status 206, {{Content-Length: -4}}
> * {{new byte[getIOBufferSize(-4)]}} → {{NegativeArraySizeException}} (not NPE)
> {{TestRangeHeaderParserUtil}} covers {{bytes=11-8}} (start past EOF → 
> {{readFull}}, 200) and {{bytes=11-10}} (both ends past EOF → 
> {{inValidRange}}, 416). There is no case for {{start < length && start > 
> end}}.
> h3. Expected (S3-compatible GET)
> RFC 9110 says the server MAY ignore or reject an invalid ranges-specifier. 
> AWS GetObject documents {{Range}} via RFC 9110; the InvalidRange error is 
> 416, without spelling out inverted ranges.
> Observed AWS GetObject (2026-08-30, {{ap-northeast-1}}, 10-byte object, 
> presigned GET):
> || Range || HTTP || Notes ||
> | {{bytes=8-3}} | *200* | full body, {{Content-Length: 10}}, no 
> {{Content-Range}} (Range ignored) |
> | {{bytes=11-20}} | *416* | {{InvalidRange}}, {{ActualObjectSize=10}} |
> | {{bytes=0-8}} | *206* | {{Content-Range: bytes 0-8/10}} (control: Range 
> works) |
> Ozone should not crash. Proposed fix: when {{start < length && start > end}}, 
> set {{readFull = true}} (ignore Range, HTTP 200), matching AWS GET and RFC 
> MAY ignore.
> h3. Proposed change
> * Parser only: in the {{start < length}} branch, if {{start > end}} then 
> {{readFull = true}} (and {{start=0}}, {{end=length-1}}). Do not put the 
> inverted check before {{start >= length}}, or {{bytes=11-10}} would change 
> from 416 to 200.
> * Unit test in {{TestRangeHeaderParserUtil}} for {{bytes=8-3}}. Keep existing 
> {{bytes=11-8}} (read full) as-is.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to