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

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

commit e3506cade2c1eed0f3f63f42a575ea166fedd75b
Author: Mark Thomas <[email protected]>
AuthorDate: Mon May 11 14:25:16 2026 +0100

    Implement stricter checks for fields using RFC 2231 / RFC 5987
    
    Values where invalid characters appear in the extended value will now be
    ignored.
---
 .../commons/fileupload2/core/ParameterParser.java  |  3 ++
 .../commons/fileupload2/core/RFC2231Utils.java     | 32 ++++++++++++++++++++--
 .../fileupload2/core/RFC2231UtilityTestCase.java   | 13 +++++++++
 src/changes/changes.xml                            |  1 +
 4 files changed, 47 insertions(+), 2 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 513b9376..0daf413a 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
@@ -176,6 +176,9 @@ public class ParameterParser {
                 if (paramValue != null) {
                     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;
                     } catch (final UnsupportedEncodingException ignored) {
                         // let's keep the original value in this case
                     }
diff --git 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/RFC2231Utils.java
 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/RFC2231Utils.java
index 11c8c749..d3bc9625 100644
--- 
a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/RFC2231Utils.java
+++ 
b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/RFC2231Utils.java
@@ -52,14 +52,38 @@ final class RFC2231Utils {
      */
     private static final byte[] HEX_DECODE = new byte[MASK_128];
 
+    private static final boolean[] ATTR_CHAR = new boolean[128];
+
     // create a ASCII decoded array of Hexadecimal values
     static {
         for (var i = 0; i < HEX_DIGITS.length; i++) {
             HEX_DECODE[HEX_DIGITS[i]] = (byte) i;
             HEX_DECODE[Character.toLowerCase(HEX_DIGITS[i])] = (byte) i;
         }
+
+        for (var i = 0; i < 128; i++) {
+            if (i < 32 || i == ' ' || i == '\"' || i == '%' || i == '\'' || i 
== '(' || i == ')' || i == '*' ||
+                    i == ',' || i == '/' || i == ':' || i == ';' || i == '<' 
|| i == '=' || i == '>' || i == '?' ||
+                    i == '@' || i == '[' || i == '\\' || i == ']' || i == '{' 
|| i == '}' || i == 127) {
+                // Not valid attr-char
+                ATTR_CHAR[i] = false;
+            } else {
+                ATTR_CHAR[i] = true;
+            }
+        }
     }
 
+
+    static boolean isAttrChar(char c) {
+        // Fast for valid values. Slow for some invalid ones.
+        try {
+            return ATTR_CHAR[c];
+        } catch (ArrayIndexOutOfBoundsException e) {
+            return false;
+        }
+    }
+
+
     /**
      * Decodes a string of text obtained from a HTTP header as per RFC 2231
      *
@@ -71,9 +95,10 @@ final class RFC2231Utils {
      *
      * @param encodedText   Text to be decoded has a format of {@code 
<charset>'<language>'<encoded_value>} and ASCII only
      * @return Decoded text based on charset encoding
+     * @throws IllegalArgumentException The encoded text contained characters 
not permitted by RFC 2231
      * @throws UnsupportedEncodingException The requested character set wasn't 
found.
      */
-    static String decodeText(final String encodedText) throws 
UnsupportedEncodingException {
+    static String decodeText(final String encodedText) throws 
IllegalArgumentException, UnsupportedEncodingException {
         final var langDelimitStart = encodedText.indexOf('\'');
         if (langDelimitStart == -1) {
             // missing charset
@@ -89,6 +114,7 @@ final class RFC2231Utils {
         return new String(bytes, getJavaCharset(mimeCharset));
     }
 
+
     /**
      * Converts {@code text} to their corresponding Hex value.
      *
@@ -107,8 +133,10 @@ final class RFC2231Utils {
                 final var b1 = HEX_DECODE[text.charAt(i++) & MASK];
                 final var b2 = HEX_DECODE[text.charAt(i++) & MASK];
                 out.write(b1 << shift | b2);
-            } else {
+            } else if (isAttrChar(c)) {
                 out.write((byte) c);
+            } else {
+                throw new IllegalArgumentException();
             }
         }
         return out.toByteArray();
diff --git 
a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/RFC2231UtilityTestCase.java
 
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/RFC2231UtilityTestCase.java
index a2ec817d..e937bd28 100644
--- 
a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/RFC2231UtilityTestCase.java
+++ 
b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/RFC2231UtilityTestCase.java
@@ -82,4 +82,17 @@ public final class RFC2231UtilityTestCase {
         final var nameWithoutAsterisk = "paramname";
         assertEquals("paramname", 
RFC2231Utils.stripDelimiter(nameWithoutAsterisk));
     }
+
+
+    @Test
+    void testDecodeNonTokenChracters() throws Exception {
+        assertThrows(IllegalArgumentException.class, () -> 
RFC2231Utils.decodeText("ISO-8859-1''Not*allowed"));
+    }
+
+
+    @Test
+    void testDecodeUTF8Chracters() throws Exception {
+        assertThrows(IllegalArgumentException.class, () -> 
RFC2231Utils.decodeText("UTF-8''\\u8a2e"));
+    }
+
 }
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 68947466..5856784f 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -45,6 +45,7 @@ The <action> type attribute can be add,update,fix,remove.
       <!-- FIX -->
       <action                        type="fix" dev="ggregory" due-to="Henri 
Biestro, Gary Gregory">Fix migration documentation to mention Java 11.</action>
       <action issue="FILEUPLOAD-362" type="fix" dev="ggregory" due-to="Kusal 
Kithul-Godage, Gary Gregory">Unable to parse requests for file uploads with 
special characters in filename on Windows.</action>
+      <action                        type="fix" dev="markt"    due-to="Mark 
Thomas">Implement stricter checks for fields using RFC 2231 / RFC 5987 and 
ignore values where invalid characters appear in the extended value.</action>
       <!-- ADD -->
       <!-- UPDATE -->
       <action type="update" dev="ggregory" due-to="Gary Gregory">Bump 
org.apache.commons:commons-parent from 96 to 99.</action>

Reply via email to