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]
