Skip to content

Commit 3d98ea5

Browse files
authored
Fix Windows path segment validation (#17868)
* Fix Windows reserved device name validation * Reject additional illegal Windows path segments * Reject empty directory path segments
1 parent ab887eb commit 3d98ea5

6 files changed

Lines changed: 61 additions & 11 deletions

File tree

iotdb-core/node-commons/src/main/i18n/en/org/apache/iotdb/commons/i18n/UtilMessages.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ public final class UtilMessages {
8787
"Renamed file {} to {} because it already exists in the target directory: {}";
8888
public static final String COPIED_FILE_ALREADY_EXISTS =
8989
"Copy file {} to {} because it already exists in the target directory: {}";
90+
public static final String ILLEGAL_EMPTY_PATH = "The path cannot be empty. ";
9091
public static final String ILLEGAL_PATH_DOTS_OR_SEPARATORS =
9192
"The path cannot be '.', '..', './' or '.\\'. ";
9293

iotdb-core/node-commons/src/main/i18n/zh/org/apache/iotdb/commons/i18n/UtilMessages.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ public final class UtilMessages {
8585
"已将文件 {} 重命名为 {},因为目标目录 {} 中已存在同名文件";
8686
public static final String COPIED_FILE_ALREADY_EXISTS =
8787
"已将文件 {} 复制为 {},因为目标目录 {} 中已存在同名文件";
88+
public static final String ILLEGAL_EMPTY_PATH = "路径不能为空。 ";
8889
public static final String ILLEGAL_PATH_DOTS_OR_SEPARATORS =
8990
"路径不能为 '.'、'..'、'./' 或 '.\\\\'. ";
9091

iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/FileUtils.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,9 @@ private static void copyFileRename(final File sourceFile, final File targetFile)
568568
}
569569

570570
public static String getIllegalError4Directory(final String path) {
571+
if (path == null || path.isEmpty()) {
572+
return UtilMessages.ILLEGAL_EMPTY_PATH;
573+
}
571574
if (path.equals(".") || path.equals("..") || path.contains("/") || path.contains("\\")) {
572575
return UtilMessages.ILLEGAL_PATH_DOTS_OR_SEPARATORS;
573576
}

iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/utils/WindowsOSUtils.java

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,42 +23,67 @@
2323

2424
import java.util.Arrays;
2525
import java.util.HashSet;
26+
import java.util.Locale;
2627
import java.util.Set;
2728

2829
public class WindowsOSUtils {
2930
private static final String ILLEGAL_WINDOWS_CHARS = "\\/:*?\"<>|";
3031
private static final Set<String> ILLEGAL_WINDOWS_NAMES =
31-
new HashSet<>(Arrays.asList("CON", "PRN", "AUX", "NUL", "COM1-COM9, LPT1-LPT9"));
32+
new HashSet<>(
33+
Arrays.asList(
34+
"CON",
35+
"PRN",
36+
"AUX",
37+
"NUL",
38+
"COM\u00B9",
39+
"COM\u00B2",
40+
"COM\u00B3",
41+
"LPT\u00B9",
42+
"LPT\u00B2",
43+
"LPT\u00B3"));
3244

3345
static {
34-
for (int i = 0; i < 10; ++i) {
46+
for (int i = 1; i < 10; ++i) {
3547
ILLEGAL_WINDOWS_NAMES.add("COM" + i);
3648
ILLEGAL_WINDOWS_NAMES.add("LPT" + i);
3749
}
3850
}
3951

4052
public static final String OS_SEGMENT_ERROR =
4153
String.format(
42-
"In Windows System, the path shall not contains %s, equals one of %s, or ends with '.' or ' '.",
54+
"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 ' '.",
4355
ILLEGAL_WINDOWS_CHARS, ILLEGAL_WINDOWS_NAMES);
4456

4557
public static boolean isLegalPathSegment4Windows(final String pathSegment) {
4658
if (!SystemUtils.IS_OS_WINDOWS) {
4759
return true;
4860
}
49-
for (final char illegalChar : ILLEGAL_WINDOWS_CHARS.toCharArray()) {
50-
if (pathSegment.indexOf(illegalChar) != -1) {
51-
return false;
52-
}
61+
if (containsIllegalWindowsChar(pathSegment)) {
62+
return false;
5363
}
5464
if (pathSegment.endsWith(".") || pathSegment.endsWith(" ")) {
5565
return false;
5666
}
57-
for (final String illegalName : ILLEGAL_WINDOWS_NAMES) {
58-
if (pathSegment.equalsIgnoreCase(illegalName)) {
59-
return false;
60-
}
67+
if (isIllegalWindowsName(pathSegment)) {
68+
return false;
6169
}
6270
return true;
6371
}
72+
73+
private static boolean containsIllegalWindowsChar(final String pathSegment) {
74+
for (int i = 0; i < pathSegment.length(); ++i) {
75+
final char ch = pathSegment.charAt(i);
76+
if (ch < ' ' || ILLEGAL_WINDOWS_CHARS.indexOf(ch) != -1) {
77+
return true;
78+
}
79+
}
80+
return false;
81+
}
82+
83+
private static boolean isIllegalWindowsName(final String pathSegment) {
84+
final int extensionStartIndex = pathSegment.indexOf('.');
85+
final String nameWithoutExtension =
86+
extensionStartIndex < 0 ? pathSegment : pathSegment.substring(0, extensionStartIndex);
87+
return ILLEGAL_WINDOWS_NAMES.contains(nameWithoutExtension.toUpperCase(Locale.ENGLISH));
88+
}
6489
}

iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/FileUtilsTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.apache.tsfile.write.record.Tablet;
2626
import org.apache.tsfile.write.schema.MeasurementSchema;
2727
import org.junit.After;
28+
import org.junit.Assert;
2829
import org.junit.Before;
2930
import org.junit.Test;
3031

@@ -60,6 +61,13 @@ public void testFileUtils() throws WriteProcessException, IOException {
6061
FileUtils.moveFileWithMD5Check(tstFile, targetDir);
6162
}
6263

64+
@Test
65+
public void testGetIllegalError4DirectoryRejectsEmptyPath() {
66+
Assert.assertNotNull(FileUtils.getIllegalError4Directory(null));
67+
Assert.assertNotNull(FileUtils.getIllegalError4Directory(""));
68+
Assert.assertNull(FileUtils.getIllegalError4Directory("valid_dir"));
69+
}
70+
6371
private void generateFile(File tsfile) throws WriteProcessException, IOException {
6472
try (TsFileWriter writer = new TsFileWriter(tsfile)) {
6573
writer.registerAlignedTimeseries(

iotdb-core/node-commons/src/test/java/org/apache/iotdb/commons/utils/WindowsOSUtilsTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,17 @@ public void testIllegalDetection() {
3737
Assert.assertFalse(isLegalPathSegment4Windows("C."));
3838
Assert.assertFalse(isLegalPathSegment4Windows("a:b<|"));
3939
Assert.assertFalse(isLegalPathSegment4Windows("COM1"));
40+
Assert.assertFalse(isLegalPathSegment4Windows("com1"));
41+
Assert.assertFalse(isLegalPathSegment4Windows("COM1.txt"));
42+
Assert.assertFalse(isLegalPathSegment4Windows("NUL.log"));
43+
Assert.assertFalse(isLegalPathSegment4Windows("LPT9.tmp"));
44+
Assert.assertFalse(isLegalPathSegment4Windows("COM\u00B9"));
45+
Assert.assertFalse(isLegalPathSegment4Windows("LPT\u00B2.log"));
46+
Assert.assertFalse(isLegalPathSegment4Windows("name\tpart"));
47+
Assert.assertFalse(isLegalPathSegment4Windows("name" + Character.toString((char) 0) + "part"));
48+
49+
Assert.assertTrue(isLegalPathSegment4Windows("COM0"));
50+
Assert.assertTrue(isLegalPathSegment4Windows("LPT0"));
51+
Assert.assertTrue(isLegalPathSegment4Windows("COM\u00B4"));
4052
}
4153
}

0 commit comments

Comments
 (0)