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

garydgregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-fileupload.git


The following commit(s) were added to refs/heads/master by this push:
     new e45f3831 Ignore invalid RFC 2231 extended value so it cannot erase a 
valid filename (#479)
e45f3831 is described below

commit e45f38315cb0234fe10a63f8562d5ce2f9c0e7a9
Author: alhuda <[email protected]>
AuthorDate: Sat Jul 18 19:47:35 2026 +0530

    Ignore invalid RFC 2231 extended value so it cannot erase a valid filename 
(#479)
---
 .../commons/fileupload2/core/ParameterParser.java  |  7 +++---
 .../fileupload2/core/ParameterParserTest.java      | 28 ++++++++++++++++++++++
 2 files changed, 32 insertions(+), 3 deletions(-)

diff --git 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/ParameterParser.java
 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/ParameterParser.java
index 419c4689..59e54893 100644
--- 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/ParameterParser.java
+++ 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/ParameterParser.java
@@ -169,6 +169,7 @@ public class ParameterParser {
         while (hasChar()) {
             paramName = parseToken(new char[] { '=', separator });
             paramValue = null;
+            var invalid = false;
             if (hasChar() && charArray[pos] == '=') {
                 pos++; // skip '='
                 paramValue = parseQuotedToken(new char[] { separator });
@@ -177,8 +178,8 @@ public class ParameterParser {
                     try {
                         paramValue = RFC2231Utils.hasEncodedValue(paramName) ? 
RFC2231Utils.decodeText(paramValue) : MimeUtils.decodeText(paramValue);
                     } catch (final IllegalArgumentException iae) {
-                        // Treat invalid values as if they were not provided
-                        paramValue = null;
+                        // Treat invalid values as if they were not provided, 
so a malformed filename* cannot override a valid filename.
+                        invalid = true;
                     } catch (final UnsupportedEncodingException ignored) {
                         // let's keep the original value in this case
                     }
@@ -187,7 +188,7 @@ public class ParameterParser {
             if (hasChar() && charArray[pos] == separator) {
                 pos++; // skip separator
             }
-            if (paramName != null && !paramName.isEmpty()) {
+            if (!invalid && paramName != null && !paramName.isEmpty()) {
                 paramName = RFC2231Utils.stripDelimiter(paramName);
                 if (this.lowerCaseNames) {
                     paramName = paramName.toLowerCase(Locale.ROOT);
diff --git 
a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/ParameterParserTest.java
 
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/ParameterParserTest.java
index df3d6c1a..123a10a1 100644
--- 
a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/ParameterParserTest.java
+++ 
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/ParameterParserTest.java
@@ -99,6 +99,34 @@ class ParameterParserTest {
         assertEquals("a'b'c", params.get("filename"));
     }
 
+    /**
+     * An invalid RFC 2231 / RFC 5987 extended value must be ignored rather 
than overwrite a valid plain value for the same parameter.
+     */
+    @Test
+    void testInvalidExtendedValueIgnored() {
+        final var parser = new ParameterParser();
+
+        // A truncated %nn escape in filename* must not erase the valid 
filename.
+        var s = "Content-Disposition: form-data; name=\"file\"; 
filename=\"safe.txt\"; filename*=UTF-8''bad%2\r\n";
+        var params = parser.parse(s, new char[] { ',', ';' });
+        assertEquals("safe.txt", params.get("filename"));
+
+        // Order independent: an invalid filename* before the valid filename 
is also ignored.
+        s = "Content-Disposition: form-data; name=\"file\"; 
filename*=UTF-8''bad%2; filename=\"safe.txt\"\r\n";
+        params = parser.parse(s, new char[] { ',', ';' });
+        assertEquals("safe.txt", params.get("filename"));
+
+        // An invalid filename* on its own is not reported as a (null) value.
+        s = "Content-Disposition: form-data; name=\"file\"; 
filename*=UTF-8''bad%2\r\n";
+        params = parser.parse(s, new char[] { ',', ';' });
+        assertNull(params.get("filename"));
+
+        // A valid filename* still decodes normally.
+        s = "Content-Disposition: form-data; name=\"file\"; 
filename=\"safe.txt\"; filename*=UTF-8''real.exe\r\n";
+        params = parser.parse(s, new char[] { ',', ';' });
+        assertEquals("real.exe", params.get("filename"));
+    }
+
     @Test
     void testParsing() {
         var s = "test; test1 =  stuff   ; test2 =  \"stuff; stuff\"; 
test3=\"stuff";

Reply via email to