This is an automated email from the ASF dual-hosted git repository.
jt2594838 pushed a commit to branch dev/1.3
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/dev/1.3 by this push:
new d906c6a496b Fix Windows path segment validation (#17868) (#17888)
d906c6a496b is described below
commit d906c6a496bdeb5bc45b178226126f27d0940d68
Author: Caideyipi <[email protected]>
AuthorDate: Wed Jun 10 12:28:18 2026 +0800
Fix Windows path segment validation (#17868) (#17888)
* Fix Windows reserved device name validation
* Reject additional illegal Windows path segments
* Reject empty directory path segments
(cherry picked from commit 3d98ea5fd7876c4f8f96033457824f10842100c8)
---
.../org/apache/iotdb/commons/utils/FileUtils.java | 4 ++
.../apache/iotdb/commons/utils/WindowsOSUtils.java | 47 ++++++++++++++-----
.../apache/iotdb/commons/utils/FileUtilsTest.java | 8 ++++
.../iotdb/commons/utils/WindowsOSUtilsTest.java | 53 ++++++++++++++++++++++
4 files changed, 101 insertions(+), 11 deletions(-)
diff --git
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/FileUtils.java
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/FileUtils.java
index fe413bf85ef..557adf43f62 100644
---
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/FileUtils.java
+++
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/FileUtils.java
@@ -54,6 +54,7 @@ public class FileUtils {
"Renamed file {} to {} because it already exists in the target
directory: {}";
private static final String COPY_FILE_MESSAGE =
"Copy file {} to {} because it already exists in the target directory:
{}";
+ private static final String ILLEGAL_EMPTY_PATH_MESSAGE = "The path cannot be
empty. ";
private static final String ILLEGAL_PATH_MESSAGE =
"The path cannot be '.', '..', './' or '.\\'. ";
@@ -556,6 +557,9 @@ public class FileUtils {
}
public static String getIllegalError4Directory(final String path) {
+ if (path == null || path.isEmpty()) {
+ return ILLEGAL_EMPTY_PATH_MESSAGE;
+ }
if (path.equals(".") || path.equals("..") || path.contains("/") ||
path.contains("\\")) {
return ILLEGAL_PATH_MESSAGE;
}
diff --git
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/WindowsOSUtils.java
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/WindowsOSUtils.java
index 3019c47cf0e..0be89f92747 100644
---
a/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/WindowsOSUtils.java
+++
b/iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/WindowsOSUtils.java
@@ -23,15 +23,27 @@ import org.apache.commons.lang3.SystemUtils;
import java.util.Arrays;
import java.util.HashSet;
+import java.util.Locale;
import java.util.Set;
public class WindowsOSUtils {
private static final String ILLEGAL_WINDOWS_CHARS = "\\/:*?\"<>|";
private static final Set<String> ILLEGAL_WINDOWS_NAMES =
- new HashSet<>(Arrays.asList("CON", "PRN", "AUX", "NUL", "COM1-COM9,
LPT1-LPT9"));
+ new HashSet<>(
+ Arrays.asList(
+ "CON",
+ "PRN",
+ "AUX",
+ "NUL",
+ "COM\u00B9",
+ "COM\u00B2",
+ "COM\u00B3",
+ "LPT\u00B9",
+ "LPT\u00B2",
+ "LPT\u00B3"));
static {
- for (int i = 0; i < 10; ++i) {
+ for (int i = 1; i < 10; ++i) {
ILLEGAL_WINDOWS_NAMES.add("COM" + i);
ILLEGAL_WINDOWS_NAMES.add("LPT" + i);
}
@@ -39,26 +51,39 @@ public class WindowsOSUtils {
public static final String OS_SEGMENT_ERROR =
String.format(
- "In Windows System, the path shall not contains %s, equals one of
%s, or ends with '.' or ' '.",
+ "In Windows System, the path shall not contain %s or ASCII control
characters, equals one of %s with or without an extension, or ends with '.' or
' '.",
ILLEGAL_WINDOWS_CHARS, ILLEGAL_WINDOWS_NAMES);
public static boolean isLegalPathSegment4Windows(final String pathSegment) {
if (!SystemUtils.IS_OS_WINDOWS) {
return true;
}
- for (final char illegalChar : ILLEGAL_WINDOWS_CHARS.toCharArray()) {
- if (pathSegment.indexOf(illegalChar) != -1) {
- return false;
- }
+ if (containsIllegalWindowsChar(pathSegment)) {
+ return false;
}
if (pathSegment.endsWith(".") || pathSegment.endsWith(" ")) {
return false;
}
- for (final String illegalName : ILLEGAL_WINDOWS_NAMES) {
- if (pathSegment.equalsIgnoreCase(illegalName)) {
- return false;
- }
+ if (isIllegalWindowsName(pathSegment)) {
+ return false;
}
return true;
}
+
+ private static boolean containsIllegalWindowsChar(final String pathSegment) {
+ for (int i = 0; i < pathSegment.length(); ++i) {
+ final char ch = pathSegment.charAt(i);
+ if (ch < ' ' || ILLEGAL_WINDOWS_CHARS.indexOf(ch) != -1) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean isIllegalWindowsName(final String pathSegment) {
+ final int extensionStartIndex = pathSegment.indexOf('.');
+ final String nameWithoutExtension =
+ extensionStartIndex < 0 ? pathSegment : pathSegment.substring(0,
extensionStartIndex);
+ return
ILLEGAL_WINDOWS_NAMES.contains(nameWithoutExtension.toUpperCase(Locale.ENGLISH));
+ }
}
diff --git
a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/FileUtilsTest.java
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/FileUtilsTest.java
index c5384e07fad..f4b1ed962bc 100644
---
a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/FileUtilsTest.java
+++
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/FileUtilsTest.java
@@ -26,6 +26,7 @@ import org.apache.tsfile.write.TsFileWriter;
import org.apache.tsfile.write.record.Tablet;
import org.apache.tsfile.write.schema.MeasurementSchema;
import org.junit.After;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -61,6 +62,13 @@ public class FileUtilsTest {
FileUtils.moveFileWithMD5Check(tstFile, targetDir);
}
+ @Test
+ public void testGetIllegalError4DirectoryRejectsEmptyPath() {
+ Assert.assertNotNull(FileUtils.getIllegalError4Directory(null));
+ Assert.assertNotNull(FileUtils.getIllegalError4Directory(""));
+ Assert.assertNull(FileUtils.getIllegalError4Directory("valid_dir"));
+ }
+
private void generateFile(File tsfile) throws WriteProcessException,
IOException {
try (TsFileWriter writer = new TsFileWriter(tsfile)) {
writer.registerAlignedTimeseries(
diff --git
a/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/WindowsOSUtilsTest.java
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/WindowsOSUtilsTest.java
new file mode 100644
index 00000000000..f088ba80730
--- /dev/null
+++
b/iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/WindowsOSUtilsTest.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.iotdb.commons.utils;
+
+import org.apache.commons.lang3.SystemUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+import static
org.apache.iotdb.commons.utils.WindowsOSUtils.isLegalPathSegment4Windows;
+
+public class WindowsOSUtilsTest {
+ @Test
+ public void testIllegalDetection() {
+ if (!SystemUtils.IS_OS_WINDOWS) {
+ return;
+ }
+ Assert.assertTrue(isLegalPathSegment4Windows("abc"));
+ Assert.assertTrue(isLegalPathSegment4Windows(".A!"));
+
+ Assert.assertFalse(isLegalPathSegment4Windows("C."));
+ Assert.assertFalse(isLegalPathSegment4Windows("a:b<|"));
+ Assert.assertFalse(isLegalPathSegment4Windows("COM1"));
+ Assert.assertFalse(isLegalPathSegment4Windows("com1"));
+ Assert.assertFalse(isLegalPathSegment4Windows("COM1.txt"));
+ Assert.assertFalse(isLegalPathSegment4Windows("NUL.log"));
+ Assert.assertFalse(isLegalPathSegment4Windows("LPT9.tmp"));
+ Assert.assertFalse(isLegalPathSegment4Windows("COM\u00B9"));
+ Assert.assertFalse(isLegalPathSegment4Windows("LPT\u00B2.log"));
+ Assert.assertFalse(isLegalPathSegment4Windows("name\tpart"));
+ Assert.assertFalse(isLegalPathSegment4Windows("name" +
Character.toString((char) 0) + "part"));
+
+ Assert.assertTrue(isLegalPathSegment4Windows("COM0"));
+ Assert.assertTrue(isLegalPathSegment4Windows("LPT0"));
+ Assert.assertTrue(isLegalPathSegment4Windows("COM\u00B4"));
+ }
+}