This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-fileupload.git
commit 3ad0adbbafee0b4ac765751784abf5e8628ce39a Author: Gary Gregory <[email protected]> AuthorDate: Sun Mar 22 15:44:04 2026 -0700 [FILEUPLOAD-362] Unable to parse requests for file uploads with special characters in filename on Windows --- .../commons/fileupload2/core/DiskFileItem.java | 28 ++++++++++------------ .../fileupload2/core/AbstractStreamingTest.java | 8 +++---- .../core/DiskFileItemSerializeTest.java | 2 +- src/changes/changes.xml | 1 + 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/DiskFileItem.java b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/DiskFileItem.java index 3d9ba96a..5ef7db66 100644 --- a/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/DiskFileItem.java +++ b/commons-fileupload2-core/src/main/java/org/apache/commons/fileupload2/core/DiskFileItem.java @@ -29,7 +29,6 @@ import java.nio.file.CopyOption; import java.nio.file.Files; import java.nio.file.InvalidPathException; import java.nio.file.Path; -import java.nio.file.Paths; import java.nio.file.StandardCopyOption; import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; @@ -224,22 +223,21 @@ public final class DiskFileItem implements FileItem<DiskFileItem> { */ public static String checkFileName(final String fileName) { if (fileName != null) { - // Specific NUL check to build a better exception message. - final var indexOf0 = fileName.indexOf(0); - if (indexOf0 != -1) { - final var sb = new StringBuilder(); - for (var i = 0; i < fileName.length(); i++) { - final var c = fileName.charAt(i); - if (c == 0) { - sb.append("\\0"); - } else { - sb.append(c); - } + var indexOfCtrl = -1; + final var sb = new StringBuilder(); + for (var i = 0; i < fileName.length(); i++) { + final var c = fileName.charAt(i); + if (Character.isISOControl(c)) { + indexOfCtrl = i; + sb.append("\\"); + sb.append(String.format("%04x", (int) c)); + } else { + sb.append(c); } - throw new InvalidPathException(fileName, sb.toString(), indexOf0); } - // Throws InvalidPathException on invalid file names - Paths.get(fileName); + if (indexOfCtrl != -1) { + throw new InvalidPathException(fileName, sb.toString(), indexOfCtrl); + } } return fileName; } diff --git a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractStreamingTest.java b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractStreamingTest.java index 158e32b8..4e88ad5f 100644 --- a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractStreamingTest.java +++ b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/AbstractStreamingTest.java @@ -233,9 +233,9 @@ public abstract class AbstractStreamingTest<AFU extends AbstractFileUpload<R, I, fail("Expected exception"); } catch (final InvalidPathException e) { assertEquals(fileName, e.getInput()); - assertEquals(26, e.getMessage().indexOf(fileName)); + assertEquals(29, e.getMessage().indexOf(fileName)); assertEquals(7, e.getIndex()); - assertTrue(e.getMessage().contains("foo.exe\\0.png")); + assertTrue(e.getMessage().contains("foo.exe\\0000.png")); } try { @@ -243,9 +243,9 @@ public abstract class AbstractStreamingTest<AFU extends AbstractFileUpload<R, I, fail("Expected exception"); } catch (final InvalidPathException e) { assertEquals(fileName, e.getInput()); - assertEquals(26, e.getMessage().indexOf(fileName)); + assertEquals(29, e.getMessage().indexOf(fileName)); assertEquals(7, e.getIndex()); - assertTrue(e.getMessage().contains("foo.exe\\0.png")); + assertTrue(e.getMessage().contains("foo.exe\\0000.png")); } } diff --git a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/DiskFileItemSerializeTest.java b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/DiskFileItemSerializeTest.java index 40e2da09..19caa0ff 100644 --- a/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/DiskFileItemSerializeTest.java +++ b/commons-fileupload2-core/src/test/java/org/apache/commons/fileupload2/core/DiskFileItemSerializeTest.java @@ -196,7 +196,7 @@ class DiskFileItemSerializeTest { } @ParameterizedTest - @ValueSource(strings = { "\0", "file\0name" }) + @ValueSource(strings = { "\0", "file\0name", "file\1name" }) void testCheckFileNameInvalid(final String fileName) { assertThrows(InvalidPathException.class, () -> DiskFileItem.checkFileName(fileName)); } diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 08e0e530..5ec463f9 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -44,6 +44,7 @@ The <action> type attribute can be add,update,fix,remove. <release version="2.0.0-M6" date="YYYY-MM-DD" description="This is a milestone release. Java 11 or later is required."> <!-- 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> <!-- ADD --> <!-- UPDATE --> <action type="update" dev="ggregory" due-to="Gary Gregory">Bump org.apache.commons:commons-parent from 96 to 97.</action>
