This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/main by this push: new d42dd73a2e Fix BZ 69690 - getParameter is OK for multipart request and no config d42dd73a2e is described below commit d42dd73a2eeae52c1e7107316bc279f3f3f8ff8e Author: Mark Thomas <ma...@apache.org> AuthorDate: Wed May 21 15:23:21 2025 +0100 Fix BZ 69690 - getParameter is OK for multipart request and no config It is only if getPart() or getParts() is called for a multipart request and there is no multipart configuration that an exception should be thrown. --- java/org/apache/catalina/connector/Request.java | 10 ++- .../org/apache/catalina/connector/TestRequest.java | 85 +++++++++++++++++++++- webapps/docs/changelog.xml | 9 +++ 3 files changed, 97 insertions(+), 7 deletions(-) diff --git a/java/org/apache/catalina/connector/Request.java b/java/org/apache/catalina/connector/Request.java index c26c2263e5..1e3e060e8a 100644 --- a/java/org/apache/catalina/connector/Request.java +++ b/java/org/apache/catalina/connector/Request.java @@ -2298,7 +2298,7 @@ public class Request implements HttpServletRequest { @Override public Collection<Part> getParts() throws IOException, IllegalStateException, ServletException { - parseParts(); + parseParts(true); if (partsParseException != null) { switch (partsParseException) { @@ -2314,7 +2314,7 @@ public class Request implements HttpServletRequest { } - private void parseParts() { + private void parseParts(boolean mustParse) { // Return immediately if the parts have already been parsed if (parts != null || partsParseException != null) { @@ -2329,7 +2329,9 @@ public class Request implements HttpServletRequest { mce = new MultipartConfigElement(null, connector.getMaxPostSize(), connector.getMaxPostSize(), connector.getMaxPostSize()); } else { - partsParseException = new IllegalStateException(sm.getString("coyoteRequest.noMultipartConfig")); + if (mustParse) { + partsParseException = new IllegalStateException(sm.getString("coyoteRequest.noMultipartConfig")); + } return; } } @@ -2694,7 +2696,7 @@ public class Request implements HttpServletRequest { String mediaType = MediaType.parseMediaTypeOnly(getContentType()); if ("multipart/form-data".equals(mediaType)) { - parseParts(); + parseParts(false); if (partsParseException instanceof IllegalStateException) { parametersParseException = (IllegalStateException) partsParseException; } else if (partsParseException != null) { diff --git a/test/org/apache/catalina/connector/TestRequest.java b/test/org/apache/catalina/connector/TestRequest.java index 5c9d95bfb6..05b05b51f4 100644 --- a/test/org/apache/catalina/connector/TestRequest.java +++ b/test/org/apache/catalina/connector/TestRequest.java @@ -443,7 +443,7 @@ public class TestRequest extends TomcatBaseTest { HttpURLConnection conn = getConnection("http://localhost:" + getPort() + "/parseParametersBeforeParseParts"); - prepareRequestBug54984(conn); + prepareMultiPartRequest(conn); checkResponseBug54984(conn); @@ -451,7 +451,7 @@ public class TestRequest extends TomcatBaseTest { conn = getConnection("http://localhost:" + getPort() + "/"); - prepareRequestBug54984(conn); + prepareMultiPartRequest(conn); checkResponseBug54984(conn); @@ -617,7 +617,7 @@ public class TestRequest extends TomcatBaseTest { } } - private void prepareRequestBug54984(HttpURLConnection conn) + private void prepareMultiPartRequest(HttpURLConnection conn) throws Exception { String boundary = "-----" + System.currentTimeMillis(); conn.setRequestProperty("Content-Type", @@ -981,4 +981,83 @@ public class TestRequest extends TomcatBaseTest { } } } + + + /* + * getParameter should work with a multipart/form-data request if there is no multipart config. + */ + @Test + public void testBug69690a() throws Exception { + Tomcat tomcat = getTomcatInstance(); + Context ctx = getProgrammaticRootContext(); + Tomcat.addServlet(ctx, "Bug69690", new Bug69690Servlet()); + ctx.addServletMappingDecoded("/", "Bug69690"); + tomcat.start(); + + HttpURLConnection conn = getConnection("http://localhost:" + getPort() + "/parameter?a=b"); + + prepareMultiPartRequest(conn); + + List<String> response = new ArrayList<>(); + int status = conn.getResponseCode(); + if (status == HttpURLConnection.HTTP_OK) { + try (InputStreamReader isr = new InputStreamReader(conn.getInputStream(), "UTF-8"); + BufferedReader reader = new BufferedReader(isr)) { + String line = null; + while ((line = reader.readLine()) != null) { + response.add(line); + } + Assert.assertTrue(response.contains("OK")); + } + } else { + Assert.fail("OK status was expected: " + status); + } + + conn.disconnect(); + } + + + /* + * getPart should not work with a multipart/form-data request if there is no multipart config. + */ + @Test + public void testBug69690b() throws Exception { + Tomcat tomcat = getTomcatInstance(); + Context ctx = getProgrammaticRootContext(); + Tomcat.addServlet(ctx, "Bug69690", new Bug69690Servlet()); + ctx.addServletMappingDecoded("/", "Bug69690"); + tomcat.start(); + + HttpURLConnection conn = getConnection("http://localhost:" + getPort() + "/part?a=b"); + + prepareMultiPartRequest(conn); + + Assert.assertEquals(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, conn.getResponseCode()); + + conn.disconnect(); + } + + + private class Bug69690Servlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + resp.setCharacterEncoding(StandardCharsets.UTF_8); + resp.setContentType("text/plain"); + PrintWriter pw = resp.getWriter(); + + if (req.getRequestURI().endsWith("/parameter")) { + if ("b".equals(req.getParameter("a"))) { + pw.print("OK"); + } else { + pw.print("FAIL - Parameter 'a' not set to 'b'"); + } + } else { + // This should trigger an error since the servlet does not have a multi-part configuration. + req.getPart("any"); + } + } + } } diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 2c95245095..5296c30230 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -170,6 +170,15 @@ Add support for the <code>java:module</code> namespace which mirrors the <code>java:comp</code> namespace. (markt) </fix> + <fix> + <bug>69690</bug>: Calling <code>HttpServletRequest.getParameter()</code> + and related methods for a request with content type + <code>multipart/form-data</code> when the mapped servlet does not have a + <code>@MultipartConfig</code> or equivalent should not trigger an + exception. Note that calling <code>getPart()</code> or + <code>getParts()</code> is these circumstances will trigger an + exception. (markt) + </fix> </changelog> </subsection> <subsection name="Coyote"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org