On Thu, Nov 20, 2025 at 4:30 PM Dimitris Soumis <[email protected]> wrote:
>
> On Thu, Nov 20, 2025 at 4:57 PM Rémy Maucherat <[email protected]> wrote:
>
> > On Thu, Nov 20, 2025 at 3:39 PM <[email protected]> wrote:
> > >
> > > This is an automated email from the ASF dual-hosted git repository.
> > >
> > > dsoumis 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 799b6f314d Add a unit test for CVE-2023-24998 and CVE-2023-28709
> > > 799b6f314d is described below
> > >
> > > commit 799b6f314d84ccabf52bd6b384e8cb3f2c4d7521
> > > Author: Dimitris Soumis <[email protected]>
> > > AuthorDate: Wed Nov 19 16:33:27 2025 +0200
> > >
> > >     Add a unit test for CVE-2023-24998 and CVE-2023-28709
> >
> > It is probably good to have an explicit named test as much as
> > possible, but out of curiosity I looked if the test coverage improved
> > and it seems not (in particular Request.parseParts looks the same). So
> > leave this test there, but it is something to keep in mind when adding
> > tests.
> > Also: it is not because code is run over that some useful assertions
> > are tested. So it's complicated ;)
> >
> I agree that aggregating CVE tests can lead to duplication without moving
> meaningful coverage. However, how do we proceed with these?
> If I implement extra assertions (the useful ones) we drift away from
> replicating the CVE.

Most of the time the test should be added. Maybe sometimes it is
possible to skip a test, especially if it is complex and already
tested elsewhere.

Rémy

> >
> > Rémy
> >
> > > ---
> > >  .../apache/tomcat/security/TestSecurity2023.java   | 143
> > +++++++++++++++++++++
> > >  1 file changed, 143 insertions(+)
> > >
> > > diff --git a/test/org/apache/tomcat/security/TestSecurity2023.java
> > b/test/org/apache/tomcat/security/TestSecurity2023.java
> > > new file mode 100644
> > > index 0000000000..34f6cff0c5
> > > --- /dev/null
> > > +++ b/test/org/apache/tomcat/security/TestSecurity2023.java
> > > @@ -0,0 +1,143 @@
> > > +/*
> > > + * Licensed to the Apache Software Foundation (ASF) under one or more
> > > + * contributor license agreements.  See the NOTICE file distributed with
> > > + * this work for additional information regarding copyright ownership.
> > > + * The ASF licenses this file to You under the Apache License, Version
> > 2.0
> > > + * (the "License"); you may not use this file except in compliance with
> > > + * the License.  You may obtain a copy of the License at
> > > + *
> > > + *      http://www.apache.org/licenses/LICENSE-2.0
> > > + *
> > > + * Unless required by applicable law or agreed to in writing, software
> > > + * distributed under the License is distributed on an "AS IS" BASIS,
> > > + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> > implied.
> > > + * See the License for the specific language governing permissions and
> > > + * limitations under the License.
> > > + */
> > > +
> > > +package org.apache.tomcat.security;
> > > +
> > > +import java.io.IOException;
> > > +import java.io.InputStream;
> > > +import java.io.OutputStream;
> > > +import java.io.Serial;
> > > +import java.net.HttpURLConnection;
> > > +import java.net.URI;
> > > +import java.net.URISyntaxException;
> > > +
> > > +import jakarta.servlet.MultipartConfigElement;
> > > +import jakarta.servlet.ServletException;
> > > +import jakarta.servlet.http.HttpServlet;
> > > +import jakarta.servlet.http.HttpServletRequest;
> > > +import jakarta.servlet.http.HttpServletResponse;
> > > +
> > > +import org.junit.Assert;
> > > +import org.junit.Test;
> > > +
> > > +import static org.apache.catalina.startup.SimpleHttpClient.CRLF;
> > > +import org.apache.catalina.Context;
> > > +import org.apache.catalina.Wrapper;
> > > +import org.apache.catalina.startup.Tomcat;
> > > +import org.apache.catalina.startup.TomcatBaseTest;
> > > +
> > > +public class TestSecurity2023 extends TomcatBaseTest {
> > > +    /*
> > > +     * https://www.cve.org/CVERecord?id=CVE-2023-24998
> > > +     *
> > > +     * Fixed in
> > > +     * 11.0.0-M3
> > https://github.com/apache/tomcat/commit/063e2e81ede50c287f737cc8e2915ce7217e886e
> > > +     * 10.1.5
> > https://github.com/apache/tomcat/commit/8a2285f13affa961cc65595aad999db5efae45ce
> > > +     * 9.0.71
> > https://github.com/apache/tomcat/commit/cf77cc545de0488fb89e24294151504a7432df74
> > > +     *
> > > +     * https://www.cve.org/CVERecord?id=CVE-2023-28709
> > > +     *
> > > +     * Fixed in
> > > +     * 11.0.0-M5
> > https://github.com/apache/tomcat/commit/d53d8e7f77042cc32a3b98f589496a1ef5088e38
> > > +     * 10.1.8
> > https://github.com/apache/tomcat/commit/ba848da71c523d94950d3c53c19ea155189df9dc
> > > +     * 9.0.74
> > https://github.com/apache/tomcat/commit/fbd81421629afe8b8a3922d59020cde81caea861
> > > +     */
> > > +    @Test
> > > +    public void testCVE_2023_24998_CVE_2023_28709() throws Exception {
> > > +        Tomcat tomcat = getTomcatInstance();
> > > +        tomcat.getConnector().setMaxParameterCount(2);
> > > +        Context context = tomcat.addContext("", null);
> > > +        Wrapper wrapper = Tomcat.addServlet(context, "test", new
> > TestServlet());
> > > +        wrapper.setMultipartConfigElement(new
> > MultipartConfigElement(""));
> > > +        context.addServletMappingDecoded("/", "test");
> > > +
> > > +        tomcat.start();
> > > +
> > > +        final String path = "http://localhost:"; + getPort() + "/";
> > > +        int status = postMultipart(path, null, 1);
> > > +        Assert.assertEquals(HttpServletResponse.SC_OK, status);
> > > +
> > > +        status = postMultipart(path, null, 3);
> > > +
> > Assert.assertEquals(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE,
> > status);
> > > +
> > > +        status = postMultipart(path,"x=1", 1);
> > > +        Assert.assertEquals(HttpServletResponse.SC_OK, status);
> > > +
> > > +        status = postMultipart(path, "x=1&y=2", 1);
> > > +
> > Assert.assertEquals(HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE,
> > status);
> > > +    }
> > > +
> > > +    @SuppressWarnings("StatementWithEmptyBody")
> > > +    private static int postMultipart(String path, String
> > queryStringParams, int parts) throws IOException, URISyntaxException {
> > > +        String urlStr = path + (queryStringParams == null ||
> > queryStringParams.isEmpty() ? "" : "?" + queryStringParams);
> > > +        String boundary = "--simpleboundary";
> > > +
> > > +        byte[] body = buildMultipartBody(boundary, parts);
> > > +        HttpURLConnection conn = (HttpURLConnection) new
> > URI(urlStr).toURL().openConnection();
> > > +        conn.setDoOutput(true);
> > > +        conn.setRequestProperty("Content-Type", "multipart/form-data;
> > boundary=" + boundary);
> > > +        conn.setRequestProperty("Content-Length",
> > String.valueOf(body.length));
> > > +        conn.setReadTimeout(1000000);
> > > +
> > > +        try (OutputStream os = conn.getOutputStream()) {
> > > +            os.write(body);
> > > +        }
> > > +
> > > +        int rc = conn.getResponseCode();
> > > +        InputStream inputStream = null;
> > > +        if (rc == HttpServletResponse.SC_OK) {
> > > +            inputStream = conn.getInputStream();
> > > +        } else if (rc ==
> > HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE) {
> > > +            inputStream = conn.getErrorStream();
> > > +        }
> > > +        if (inputStream != null) {
> > > +            while (inputStream.read() != -1) {}
> > > +            inputStream.close();
> > > +        }
> > > +
> > > +        return rc;
> > > +    }
> > > +
> > > +    private static byte[] buildMultipartBody(String boundary, int
> > parts) {
> > > +        StringBuilder sb = new StringBuilder();
> > > +        for (int i = 0; i < parts; i++) {
> > > +            sb.append("--");
> > > +            sb.append(boundary);
> > > +            sb.append(CRLF);
> > > +            sb.append("Content-Disposition: form-data; name=\"part\"");
> > > +            sb.append(CRLF);
> > > +            sb.append(CRLF);
> > > +            sb.append("bodyOfPart");
> > > +            sb.append(CRLF);
> > > +        }
> > > +        sb.append("--");
> > > +        sb.append(boundary);
> > > +        sb.append("--");
> > > +        sb.append(CRLF);
> > > +        return sb.toString().getBytes();
> > > +    }
> > > +
> > > +    public static class TestServlet extends HttpServlet {
> > > +        @Serial
> > > +        private static final long serialVersionUID = 1L;
> > > +
> > > +        @Override
> > > +        protected void doPost(HttpServletRequest req,
> > HttpServletResponse resp) throws IOException, ServletException {
> > > +            req.getParameterMap();
> > > +        }
> > > +    }
> > > +}
> > >
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: [email protected]
> > > For additional commands, e-mail: [email protected]
> > >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [email protected]
> > For additional commands, e-mail: [email protected]
> >
> >

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

Reply via email to