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

commit 5cfa56ae76e445340e9b8c90504037d58c0eab22
Author: Gary Gregory <[email protected]>
AuthorDate: Sat Jul 18 07:23:17 2026 -0700

    Ignore invalid RFC 2231 extended value so it cannot erase a valid
    filename (#479).
---
 .../fileupload2/core/ParameterParserTest.java      | 30 ++++++++++++----------
 src/changes/changes.xml                            |  1 +
 2 files changed, 18 insertions(+), 13 deletions(-)

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 123a10a1..c14784a6 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
@@ -28,6 +28,10 @@ import org.junit.jupiter.api.Test;
  */
 class ParameterParserTest {
 
+    private char[] newSeparatorArray() {
+        return new char[] { ',', ';' };
+    }
+
     @Test
     void testContentTypeParsing() {
         final var s = "text/plain; Charset=UTF-8";
@@ -42,7 +46,7 @@ class ParameterParserTest {
     void testFileUpload139() {
         final var parser = new ParameterParser();
         var s = "Content-type: multipart/form-data , boundary=AaB03x";
-        var params = parser.parse(s, new char[] { ',', ';' });
+        var params = parser.parse(s, newSeparatorArray());
         assertEquals("AaB03x", params.get("boundary"));
 
         s = "Content-type: multipart/form-data, boundary=AaB03x";
@@ -50,7 +54,7 @@ class ParameterParserTest {
         assertEquals("AaB03x", params.get("boundary"));
 
         s = "Content-type: multipart/mixed, boundary=BbC04y";
-        params = parser.parse(s, new char[] { ',', ';' });
+        params = parser.parse(s, newSeparatorArray());
         assertEquals("BbC04y", params.get("boundary"));
     }
 
@@ -62,7 +66,7 @@ class ParameterParserTest {
         final var parser = new ParameterParser();
         final var s = "Content-Disposition: form-data; name=\"file\"; 
filename=\"=?ISO-8859-"
                 + "1?B?SWYgeW91IGNhbiByZWFkIHRoaXMgeW8=?= 
=?ISO-8859-2?B?dSB1bmRlcnN0YW5kIHRoZSBleGFtcGxlLg==?=\"\r\n";
-        final var params = parser.parse(s, new char[] { ',', ';' });
+        final var params = parser.parse(s, newSeparatorArray());
         assertEquals("If you can read this you understand the example.", 
params.get("filename"));
     }
 
@@ -75,27 +79,27 @@ class ParameterParserTest {
 
         // Should parse a UTF-8 charset
         var s = "Content-Disposition: form-data; " + "name=\"file\"; 
filename*=UTF-8''%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF\r\n";
-        var params = parser.parse(s, new char[] { ',', ';' });
+        var params = parser.parse(s, newSeparatorArray());
         assertEquals("\u3053\u3093\u306B\u3061\u306F", 
params.get("filename")); // filename = "こんにちは" in japanese
 
         // Should parse ISO-8859-1 charset
         s = "Content-Disposition: form-data; name=\"file\"; 
filename*=UTF-8''%70%C3%A2%74%C3%A9\r\n";
-        params = parser.parse(s, new char[] { ',', ';' });
+        params = parser.parse(s, newSeparatorArray());
         assertEquals("\u0070\u00e2\u0074\u00e9", params.get("filename")); // 
filename = "pâté" in french
 
         // Should not decode if '*' is not at the end of param-name
         s = "Content-Disposition: form-data; name=\"file\"; 
file*name=UTF-8''%61%62%63\r\n";
-        params = parser.parse(s, new char[] { ',', ';' });
+        params = parser.parse(s, newSeparatorArray());
         assertEquals("UTF-8''%61%62%63", params.get("file*name"));
 
         // Should not decode if param-value does not follow 
<charset>'<lang>'<encoded>
         s = "Content-Disposition: form-data; name=\"file\"; 
filename*=a'bc\r\n";
-        params = parser.parse(s, new char[] { ',', ';' });
+        params = parser.parse(s, newSeparatorArray());
         assertEquals("a'bc", params.get("filename"));
 
         // Should not decode if param-name doesn't have '*' at end
         s = "Content-Disposition: form-data; name=\"file\"; 
filename=a'b'c\r\n";
-        params = parser.parse(s, new char[] { ',', ';' });
+        params = parser.parse(s, newSeparatorArray());
         assertEquals("a'b'c", params.get("filename"));
     }
 
@@ -108,22 +112,22 @@ class ParameterParserTest {
 
         // 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[] { ',', ';' });
+        var params = parser.parse(s, newSeparatorArray());
         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[] { ',', ';' });
+        params = parser.parse(s, newSeparatorArray());
         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[] { ',', ';' });
+        params = parser.parse(s, newSeparatorArray());
         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[] { ',', ';' });
+        params = parser.parse(s, newSeparatorArray());
         assertEquals("real.exe", params.get("filename"));
     }
 
@@ -137,7 +141,7 @@ class ParameterParserTest {
         assertEquals("stuff; stuff", params.get("test2"));
         assertEquals("\"stuff", params.get("test3"));
 
-        params = parser.parse(s, new char[] { ',', ';' });
+        params = parser.parse(s, newSeparatorArray());
         assertNull(params.get("test"));
         assertEquals("stuff", params.get("test1"));
         assertEquals("stuff; stuff", params.get("test2"));
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 8a90e196..ed3f2edc 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -50,6 +50,7 @@ The <action> type attribute can be add,update,fix,remove.
       <action                        type="fix" dev="ggregory" due-to="alhuda, 
Gary Gregory">Create temporary upload file with owner-only permissions 
(#473).</action>
       <action                        type="fix" dev="ggregory" due-to="alhuda, 
Gary Gregory">Match RFC 2047 encoding token case-insensitively in decodeWord 
(#476).</action>
       <action                        type="fix" dev="ggregory" due-to="alhuda, 
Gary Gregory">Reject malformed base64 payload in RFC 2047 decodeWord 
(#478).</action>
+      <action                        type="fix" dev="ggregory" due-to="alhuda, 
Gary Gregory">Ignore invalid RFC 2231 extended value so it cannot erase a valid 
filename (#479).</action>
       <!-- ADD -->
       <!-- UPDATE -->
       <action type="update" dev="ggregory" due-to="Gary Gregory">Bump 
org.apache.commons:commons-parent from 96 to 102.</action>

Reply via email to