This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/struts.git


The following commit(s) were added to refs/heads/main by this push:
     new 972fd8a02 WW-5751 Treat a negative maximumSize as no upload size limit 
(#1976)
972fd8a02 is described below

commit 972fd8a02320834ab73082b68cc7baef22f13595
Author: Lukasz Lenart <[email protected]>
AuthorDate: Thu Oct 1 20:45:16 2026 +0200

    WW-5751 Treat a negative maximumSize as no upload size limit (#1976)
    
    * WW-5751 fix(core): treat a negative maximumSize as no upload size limit
    
    Since 7.3.0 a maximumSize param that cannot be applied marks the upload
    policy unresolved and the upload is rejected. The literal "null" some
    configurations used to lift the limit only worked in 7.2.1 because its
    conversion error was silently ignored, so it now rejects every upload.
    
    A negative maximumSize, e.g. -1, is now the explicit way to disable the
    size check. Before this change -1 rejected every upload.
    
    Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
    
    * WW-5751 refactor(core): extract the upload size check into a protected 
method
    
    exceedsMaximumSize(UploadPolicy, UploadedFile) lets a subclass of the
    upload interceptor replace the per-file size check.
    
    Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
    
    * WW-5751 fix(core): format the too-large message without a maximum size
    
    An overridden exceedsMaximumSize can reject a file when no maximumSize is
    configured; formatting the null size then threw IllegalArgumentException
    instead of reporting the validation error.
    
    Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
    
    ---------
    
    Co-authored-by: Claude Opus 5.5 (1M context) <[email protected]>
---
 .../interceptor/AbstractFileUploadInterceptor.java | 17 ++++++-
 .../interceptor/ActionFileUploadInterceptor.java   |  2 +-
 .../apache/struts2/interceptor/UploadPolicy.java   |  2 +-
 .../ActionFileUploadInterceptorTest.java           | 56 ++++++++++++++++++++++
 4 files changed, 73 insertions(+), 4 deletions(-)

diff --git 
a/core/src/main/java/org/apache/struts2/interceptor/AbstractFileUploadInterceptor.java
 
b/core/src/main/java/org/apache/struts2/interceptor/AbstractFileUploadInterceptor.java
index dac450b45..4761d2c5b 100644
--- 
a/core/src/main/java/org/apache/struts2/interceptor/AbstractFileUploadInterceptor.java
+++ 
b/core/src/main/java/org/apache/struts2/interceptor/AbstractFileUploadInterceptor.java
@@ -98,7 +98,7 @@ public abstract class AbstractFileUploadInterceptor extends 
AbstractInterceptor
      * effective policy for an invocation is a copy, see
      * {@link ActionFileUploadInterceptor#newLazyParams()}.
      *
-     * @param maximumSize The maximum size in bytes
+     * @param maximumSize The maximum size in bytes, or a negative value for 
no limit
      */
     public void setMaximumSize(Long maximumSize) {
         configuredPolicy.setMaximumSize(maximumSize);
@@ -152,7 +152,7 @@ public abstract class AbstractFileUploadInterceptor extends 
AbstractInterceptor
             return false;
         }
 
-        if (policy.getMaximumSize() != null && policy.getMaximumSize() < 
file.length()) {
+        if (exceedsMaximumSize(policy, file)) {
             String errMsg = getTextMessage(action, 
STRUTS_MESSAGES_ERROR_FILE_TOO_LARGE_KEY, new String[]{
                 inputName, originalFilename, file.getName(), "" + 
file.length(), getMaximumSizeStr(action, policy.getMaximumSize())
             });
@@ -182,7 +182,20 @@ public abstract class AbstractFileUploadInterceptor 
extends AbstractInterceptor
         return errorMessages.isEmpty();
     }
 
+    /**
+     * @param policy - the effective upload policy for this invocation.
+     * @param file   - proposed upload file.
+     * @return true if the file is larger than the policy allows; a null or 
negative maximum size means no limit.
+     */
+    protected boolean exceedsMaximumSize(UploadPolicy policy, UploadedFile 
file) {
+        Long maximumSize = policy.getMaximumSize();
+        return maximumSize != null && maximumSize >= 0 && maximumSize < 
file.length();
+    }
+
     private String getMaximumSizeStr(Object action, Long maximumSize) {
+        if (maximumSize == null) {
+            return "";
+        }
         return 
NumberFormat.getNumberInstance(getLocaleProvider(action).getLocale()).format(maximumSize);
     }
 
diff --git 
a/core/src/main/java/org/apache/struts2/interceptor/ActionFileUploadInterceptor.java
 
b/core/src/main/java/org/apache/struts2/interceptor/ActionFileUploadInterceptor.java
index c898275f0..d08bb4173 100644
--- 
a/core/src/main/java/org/apache/struts2/interceptor/ActionFileUploadInterceptor.java
+++ 
b/core/src/main/java/org/apache/struts2/interceptor/ActionFileUploadInterceptor.java
@@ -64,7 +64,7 @@ import java.util.List;
  * <ul>
  * <li>maximumSize (optional) - the maximum size (in bytes) that the 
interceptor will allow a file reference to be set
  * on the action. Note, this is <b>not</b> related to the various properties 
found in struts.properties.
- * Default to approximately 2MB.</li>
+ * Default to approximately 2MB. A negative value, e.g. -1, means no 
limit.</li>
  * <li>allowedTypes (optional) - a comma separated list of content types (ie: 
text/html) that the interceptor will allow
  * a file reference to be set on the action. If none is specified allow all 
types to be uploaded.</li>
  * <li>allowedExtensions (optional) - a comma separated list of file 
extensions (ie: .html) that the interceptor will allow
diff --git 
a/core/src/main/java/org/apache/struts2/interceptor/UploadPolicy.java 
b/core/src/main/java/org/apache/struts2/interceptor/UploadPolicy.java
index 4d03f711a..f9f333dab 100644
--- a/core/src/main/java/org/apache/struts2/interceptor/UploadPolicy.java
+++ b/core/src/main/java/org/apache/struts2/interceptor/UploadPolicy.java
@@ -67,7 +67,7 @@ public class UploadPolicy extends DisableParams {
     }
 
     /**
-     * @param maximumSize the maximum size in bytes, or null for no limit
+     * @param maximumSize the maximum size in bytes, or null or a negative 
value for no limit
      */
     public void setMaximumSize(Long maximumSize) {
         this.maximumSize = maximumSize;
diff --git 
a/core/src/test/java/org/apache/struts2/interceptor/ActionFileUploadInterceptorTest.java
 
b/core/src/test/java/org/apache/struts2/interceptor/ActionFileUploadInterceptorTest.java
index 22f448408..2d6c4a87d 100644
--- 
a/core/src/test/java/org/apache/struts2/interceptor/ActionFileUploadInterceptorTest.java
+++ 
b/core/src/test/java/org/apache/struts2/interceptor/ActionFileUploadInterceptorTest.java
@@ -243,6 +243,62 @@ public class ActionFileUploadInterceptorTest extends 
StrutsInternalTestCase {
                 .contains("The file is too large to be uploaded", "inputName", 
"log4j2.xml", "allowed mx size is 10");
     }
 
+    public void testAcceptFileWithNegativeMaxSizeHasNoLimit() throws Exception 
{
+        interceptor.setMaximumSize(-1L);
+        ValidationAwareSupport validation = new ValidationAwareSupport();
+
+        URL url = ClassLoaderUtil.getResource("log4j2.xml", 
ActionFileUploadInterceptorTest.class);
+        File file = new File(new URI(url.toString()));
+        UploadedFile uploadedFile = 
StrutsUploadedFile.Builder.create(file).withContentType("text/html").withOriginalName("filename").build();
+        boolean ok = 
interceptor.acceptFile(interceptor.copyConfiguredPolicy(), validation, 
uploadedFile, "filename", "text/html", "inputName");
+
+        assertThat(ok).isTrue();
+        assertThat(validation.hasErrors()).isFalse();
+    }
+
+    public void testAcceptFileUsesOverriddenMaximumSizeCheck() throws 
Exception {
+        ActionFileUploadInterceptor lenient = new 
ActionFileUploadInterceptor() {
+            @Override
+            protected boolean exceedsMaximumSize(UploadPolicy policy, 
UploadedFile file) {
+                return false;
+            }
+        };
+        container.inject(lenient);
+        lenient.setMaximumSize(10L);
+        ValidationAwareSupport validation = new ValidationAwareSupport();
+
+        URL url = ClassLoaderUtil.getResource("log4j2.xml", 
ActionFileUploadInterceptorTest.class);
+        File file = new File(new URI(url.toString()));
+        UploadedFile uploadedFile = 
StrutsUploadedFile.Builder.create(file).withContentType("text/html").withOriginalName("filename").build();
+        boolean ok = lenient.acceptFile(lenient.copyConfiguredPolicy(), 
validation, uploadedFile, "filename", "text/html", "inputName");
+
+        assertThat(ok).isTrue();
+        assertThat(validation.hasErrors()).isFalse();
+    }
+
+    public void 
testAcceptFileRejectsWithoutMaximumSizeWhenOverrideSaysTooLarge() throws 
Exception {
+        ActionFileUploadInterceptor strict = new ActionFileUploadInterceptor() 
{
+            @Override
+            protected boolean exceedsMaximumSize(UploadPolicy policy, 
UploadedFile file) {
+                return true;
+            }
+        };
+        container.inject(strict);
+        ValidationAwareSupport validation = new ValidationAwareSupport();
+
+        URL url = ClassLoaderUtil.getResource("log4j2.xml", 
ActionFileUploadInterceptorTest.class);
+        File file = new File(new URI(url.toString()));
+        UploadedFile uploadedFile = 
StrutsUploadedFile.Builder.create(file).withContentType("text/html").withOriginalName("filename").build();
+        boolean ok = strict.acceptFile(strict.copyConfiguredPolicy(), 
validation, uploadedFile, "filename", "text/html", "inputName");
+
+        assertThat(ok).isFalse();
+        assertThat(validation.getFieldErrors().get("inputName"))
+                .hasSize(1)
+                .first()
+                .asString()
+                .contains("The file is too large to be uploaded");
+    }
+
     public void testNoMultipartRequest() throws Exception {
         MyFileUploadAction action = new MyFileUploadAction();
 

Reply via email to