This is an automated email from the ASF dual-hosted git repository. rmaucher pushed a commit to branch 11.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit dd0febe2f98b2cf53813d8152780eb8f5c93ac00 Author: opencode <[email protected]> AuthorDate: Wed Sep 30 10:44:48 2026 +0200 Fix InputBuffer.skip() consuming and returning more characters than requested by comparing and advancing by the remaining count (n - nRead) rather than the original count, and add a regression test --- .../org/apache/catalina/connector/InputBuffer.java | 4 +- .../apache/catalina/connector/TestInputBuffer.java | 61 ++++++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/java/org/apache/catalina/connector/InputBuffer.java b/java/org/apache/catalina/connector/InputBuffer.java index 10fe74c300..5fc9285b5e 100644 --- a/java/org/apache/catalina/connector/InputBuffer.java +++ b/java/org/apache/catalina/connector/InputBuffer.java @@ -520,8 +520,8 @@ public class InputBuffer extends Reader implements ByteChunk.ByteInputChannel, A long nRead = 0; while (nRead < n) { - if (cb.remaining() >= n) { - cb.position(cb.position() + (int) n); + if (cb.remaining() >= (n - nRead)) { + cb.position(cb.position() + (int) (n - nRead)); nRead = n; } else { nRead += cb.remaining(); diff --git a/test/org/apache/catalina/connector/TestInputBuffer.java b/test/org/apache/catalina/connector/TestInputBuffer.java index 55d3ad142f..bb7ce5ce76 100644 --- a/test/org/apache/catalina/connector/TestInputBuffer.java +++ b/test/org/apache/catalina/connector/TestInputBuffer.java @@ -23,6 +23,9 @@ import java.io.Writer; import java.nio.charset.MalformedInputException; import java.nio.charset.StandardCharsets; import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServlet; @@ -102,6 +105,36 @@ public class TestInputBuffer extends TomcatBaseTest { } + @Test + public void testSkip() throws Exception { + Tomcat tomcat = getTomcatInstance(); + Context root = tomcat.addContext("", TEMP_DIR); + Tomcat.addServlet(root, "Skip", new SkipServlet()); + root.addServletMapping("/test", "Skip"); + + // Limit socket reads to 10 bytes so skip() has to refill repeatedly + Assert.assertTrue(tomcat.getConnector().setProperty("socket.appReadBufSize", "10")); + + tomcat.start(); + + StringBuilder body = new StringBuilder(); + for (int i = 0; i < 210; i++) { + body.append((char) ('a' + i % 26)); + } + + ByteChunk bc = new ByteChunk(); + Map<String,List<String>> responseHeaders = new HashMap<>(); + int rc = postUrl(body.toString().getBytes(StandardCharsets.US_ASCII), + "http://localhost:" + getPort() + "/test", bc, responseHeaders); + bc.setCharset(StandardCharsets.US_ASCII); + + Assert.assertEquals(HttpServletResponse.SC_OK, rc); + // One character read, then 20 skipped before the remainder was echoed + Assert.assertEquals("20", responseHeaders.get("X-Skip").get(0)); + Assert.assertEquals(body.substring(21), bc.toString()); + } + + private void doUtf8BodyTest(String description, int[] input, String expected) throws Exception { byte[] bytes = new byte[input.length]; @@ -159,6 +192,34 @@ public class TestInputBuffer extends TomcatBaseTest { } + private static class SkipServlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + Reader r = req.getReader(); + StringBuilder result = new StringBuilder(); + + // Consume one character so the skip below starts with 9 buffered chars + r.read(); + long skipped = r.skip(20); + + char[] cbuf = new char[80]; + int n = r.read(cbuf); + while (n > 0) { + result.append(cbuf, 0, n); + n = r.read(cbuf); + } + + resp.setHeader("X-Skip", Long.toString(skipped)); + resp.setContentType("text/plain"); + resp.setCharacterEncoding("US-ASCII"); + resp.getWriter().write(result.toString()); + } + } + + private static class Bug60400Servlet extends HttpServlet { private static final long serialVersionUID = 1L; --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
