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 f0a0021d65 Explicitly clean up after failed multi-part upload
f0a0021d65 is described below

commit f0a0021d65b3faf551d48cbe69d46b802f709a02
Author: Mark Thomas <[email protected]>
AuthorDate: Mon Sep 29 17:50:43 2025 +0100

    Explicitly clean up after failed multi-part upload
---
 .../catalina/connector/LocalStrings.properties     |  1 +
 java/org/apache/catalina/connector/Request.java    | 23 +++++++++++++++++++++-
 webapps/docs/changelog.xml                         |  4 ++++
 3 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/java/org/apache/catalina/connector/LocalStrings.properties 
b/java/org/apache/catalina/connector/LocalStrings.properties
index d91ca15ce3..85aa3e6d51 100644
--- a/java/org/apache/catalina/connector/LocalStrings.properties
+++ b/java/org/apache/catalina/connector/LocalStrings.properties
@@ -92,6 +92,7 @@ request.asyncNotSupported=A filter or servlet of the current 
chain does not supp
 request.fragmentInDispatchPath=The fragment in dispatch path [{0}] has been 
removed
 request.illegalWrap=The request wrapper must wrap the request obtained from 
getRequest()
 request.notAsync=It is illegal to call this method if the current request is 
not in asynchronous mode (i.e. isAsyncStarted() returns false)
+request.partCleanup.failed=Unable to delete temporary file for uploaded part 
after multi-part processing failed
 request.session.failed=Failed to load session [{0}] due to [{1}]
 
 requestFacade.nullRequest=The request object has been recycled and is no 
longer associated with this facade
diff --git a/java/org/apache/catalina/connector/Request.java 
b/java/org/apache/catalina/connector/Request.java
index 46c18ed5a3..e718452fb3 100644
--- a/java/org/apache/catalina/connector/Request.java
+++ b/java/org/apache/catalina/connector/Request.java
@@ -2462,8 +2462,10 @@ public class Request implements HttpServletRequest {
         upload.setFileCountMax(partLimit);
 
         parts = new ArrayList<>();
+        List<FileItem> items = null;
+        boolean success = false;
         try {
-            List<FileItem> items = upload.parseRequest(new 
ServletRequestContext(this));
+            items = upload.parseRequest(new ServletRequestContext(this));
             int maxPostSize = getConnector().getMaxPostSize();
             long postSize = 0;
             Charset charset = getCharset();
@@ -2499,6 +2501,7 @@ public class Request implements HttpServletRequest {
                 }
                 parts.add(part);
             }
+            success = true;
         } catch (InvalidContentTypeException e) {
             partsParseException = new ServletException(e);
         } catch (SizeException | FileCountLimitExceededException e) {
@@ -2509,6 +2512,24 @@ public class Request implements HttpServletRequest {
         } catch (IllegalStateException e) {
             checkSwallowInput();
             partsParseException = e;
+        } finally {
+            /*
+             * GC will delete any temporary copies of uploaded files left in 
the work directory but if we know that the
+             * upload has failed then explicitly clean up now.
+             */
+            if (!success) {
+                parts.clear();
+                if (items != null) {
+                    for (FileItem item : items) {
+                        try {
+                            item.delete();
+                        } catch (Throwable t) {
+                            ExceptionUtils.handleThrowable(t);
+                            
log.warn(sm.getString("request.partCleanup.failed"), t);
+                        }
+                    }
+                }
+            }
         }
     }
 
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 58661faffe..e9ca802bf9 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -196,6 +196,10 @@
       <fix>
         Fix a case-sensitivity issue in the trailer header allow list. (markt)
       </fix>
+      <fix>
+        Be proactive in cleaning up temporary files after a failed multi-part
+        upload rather than waiting for GC to do it. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">


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

Reply via email to