aoto-tech opened a new pull request, #1067:
URL: https://github.com/apache/tomcat/pull/1067

   ## Summary
   
   Fix `DefaultServlet` byte range responses so a legal short read from the
   resource stream no longer truncates the response. Also report a premature end
   of stream as an I/O error instead of passing `-1` as the output length and
   triggering an unchecked exception.
   
   ## Problem
   
   `DefaultServlet.copyNoThrow(InputStream, ServletOutputStream, long, long)` 
uses
   the length returned by the previous read as part of its loop condition:
   
   ```java
   while ((bytesToRead > 0) && (len >= buffer.length))
   ```
   
   `InputStream.read(byte[])` may legally return a positive value smaller than 
the
   requested length without reaching EOF. The current code writes the short 
chunk
   and exits the loop while `bytesToRead` is still positive. The method returns
   `null`, leaving the caller with no I/O error for the incomplete 206 response
   body.
   
   If the stream reaches EOF before the requested range is complete, `read()`
   returns `-1`. The current comparison enters the write branch and calls
   `ServletOutputStream.write(..., -1)`, resulting in an
   `IndexOutOfBoundsException`.
   
   Both the single-range and multipart-range paths use this method. Production
   callers wrap the resource stream in `BufferedInputStream`, but the wrapper 
gives
   no guarantee of filling the requested buffer on every read.
   
   ## Reproduction
   
   A focused reproducer wraps an `InputStream` returning at most three bytes per
   read in `BufferedInputStream`.
   
   For an eight-byte source and range `0-7`:
   
   ```text
   expected body length: 8
   actual body length:   3
   returned exception:   null
   ```
   
   For a source ending before the requested range is complete, the current
   implementation throws:
   
   ```text
   java.lang.IndexOutOfBoundsException: Range [0, 0 + -1) out of bounds for 
length 2048
   ```
   
   The premature EOF case models a resource stream ending after the range length
   has been established.
   
   ## Change
   
   The range copy loop is now driven only by the number of bytes remaining. Each
   read is limited to the smaller of the buffer size and the remaining range
   length. A positive short read is written and copying continues. Premature EOF
   returns an `EOFException` through the existing `IOException` result path.
   
   No public API is changed. Streams already filling the requested buffer keep 
the
   same behavior.
   
   ## Tests
   
   ```text
   ant -noinput 
-Dtest.entry=org.apache.catalina.servlets.TestDefaultServletRangeCopy test
   Tests run: 6, Failures: 0, Errors: 0, Skipped: 0
   
   ant -noinput 
-Dtest.entry=org.apache.catalina.servlets.TestDefaultServletRangeRequests test
   Tests run: 36, Failures: 0, Errors: 0, Skipped: 0
   
   ant -noinput -Dexecute.validate=true validate
   BUILD SUCCESSFUL
   ```
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to