This is an automated email from the ASF dual-hosted git repository.
jt2594838 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new 50a2e83eb65 fix: validate internal tsfile paths for files only (#18417)
50a2e83eb65 is described below
commit 50a2e83eb6512fa5635664efa125a19f6cab9623
Author: Zhenyu Luo <[email protected]>
AuthorDate: Mon Aug 10 18:24:05 2026 +0800
fix: validate internal tsfile paths for files only (#18417)
* fix: validate internal tsfile paths for files only
* test: cover loading internal data directories
* test: cover empty and non-empty internal data directories
* fix: reject empty load tsfile paths
* Revert "test: cover loading internal data directories"
This reverts commit c7557a762854ec890c760c07e6979b66f38e3fff.
* Revert "fix: validate internal tsfile paths for files only"
This reverts commit 509b40ed0106f617163be8ac91b62a310ee327b9.
* fix: validate empty load tsfile paths for both models
* fixed
---
.../en/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java | 2 ++
.../zh/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java | 2 ++
.../db/queryengine/plan/relational/sql/ast/LoadTsFile.java | 1 +
.../queryengine/plan/statement/crud/LoadTsFileStatement.java | 8 ++++++++
.../plan/analyze/load/LoadTsFileAnalyzerTest.java | 10 ++++++++++
.../plan/statement/crud/LoadTsFileStatementTest.java | 12 ++++++++++++
6 files changed, 35 insertions(+)
diff --git
a/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java
b/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java
index ade27d85d09..3feefd72a6f 100644
---
a/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java
+++
b/iotdb-core/datanode/src/main/i18n/en/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java
@@ -3681,6 +3681,8 @@ public final class DataNodeQueryMessages {
public static final String EXCEPTION_UDFNAME_IS_NULL_83E9039B = "udfName is
null";
public static final String EXCEPTION_URISTRING_IS_NULL_E7458C6A = "uriString
is null";
public static final String EXCEPTION_FILEPATH_IS_NULL_84CE8A66 = "filePath
is null";
+ public static final String
EXCEPTION_LOAD_TSFILE_PATH_CANNOT_BE_EMPTY_2B106181 =
+ "The LOAD TSFILE path cannot be empty.";
public static final String EXCEPTION_DETAILS_IS_NULL_8EDEEA03 = "details is
null";
public static final String EXCEPTION_COLUMNCATEGORY_IS_NULL_0075924B =
"columnCategory is null";
public static final String EXCEPTION_ARGUMENTNAME_IS_NULL_7F8F665F =
"argumentName is null";
diff --git
a/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java
b/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java
index 31278e1e48e..0d4e7cc0071 100644
---
a/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java
+++
b/iotdb-core/datanode/src/main/i18n/zh/org/apache/iotdb/db/i18n/DataNodeQueryMessages.java
@@ -4424,6 +4424,8 @@ public final class DataNodeQueryMessages {
public static final String EXCEPTION_UDFNAME_IS_NULL_83E9039B = "udfName
不能为空";
public static final String EXCEPTION_URISTRING_IS_NULL_E7458C6A = "uriString
不能为空";
public static final String EXCEPTION_FILEPATH_IS_NULL_84CE8A66 = "filePath
不能为空";
+ public static final String
EXCEPTION_LOAD_TSFILE_PATH_CANNOT_BE_EMPTY_2B106181 =
+ "LOAD TSFILE 路径不能为空。";
public static final String EXCEPTION_DETAILS_IS_NULL_8EDEEA03 = "details
不能为空";
public static final String EXCEPTION_COLUMNCATEGORY_IS_NULL_0075924B =
"columnCategory 不能为空";
public static final String EXCEPTION_ARGUMENTNAME_IS_NULL_7F8F665F =
"argumentName 不能为空";
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/LoadTsFile.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/LoadTsFile.java
index 8e46f7cd72a..2e9adadb576 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/LoadTsFile.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/relational/sql/ast/LoadTsFile.java
@@ -111,6 +111,7 @@ public class LoadTsFile extends Statement {
initAttributes();
try {
+ LoadTsFileStatement.validateLoadTsFilePath(filePath);
this.tsFiles =
validateInternalDataDir
? LoadTsFileStatement.processTsFile(new File(filePath),
validateSourcePath)
diff --git
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/crud/LoadTsFileStatement.java
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/crud/LoadTsFileStatement.java
index 0b0dea76311..ca0a0a3e2bf 100644
---
a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/crud/LoadTsFileStatement.java
+++
b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/statement/crud/LoadTsFileStatement.java
@@ -94,6 +94,7 @@ public class LoadTsFileStatement extends Statement {
private LoadTsFileStatement(
String filePath, boolean validateSourcePath, boolean
validateInternalDataDir)
throws FileNotFoundException {
+ validateLoadTsFilePath(filePath);
this.file = new File(filePath).getAbsoluteFile();
this.databaseLevel =
IoTDBDescriptor.getInstance().getConfig().getDefaultDatabaseLevel();
this.verifySchema = true;
@@ -111,6 +112,13 @@ public class LoadTsFileStatement extends Statement {
this.statementType = StatementType.MULTI_BATCH_INSERT;
}
+ public static void validateLoadTsFilePath(final String filePath) throws
FileNotFoundException {
+ if (filePath == null || filePath.isEmpty()) {
+ throw new FileNotFoundException(
+
DataNodeQueryMessages.EXCEPTION_LOAD_TSFILE_PATH_CANNOT_BE_EMPTY_2B106181);
+ }
+ }
+
public static List<File> processTsFile(final File file) throws
FileNotFoundException {
return processTsFile(file, true, true);
}
diff --git
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/analyze/load/LoadTsFileAnalyzerTest.java
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/analyze/load/LoadTsFileAnalyzerTest.java
index 68503f3d794..bf248d7a600 100644
---
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/analyze/load/LoadTsFileAnalyzerTest.java
+++
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/analyze/load/LoadTsFileAnalyzerTest.java
@@ -120,6 +120,16 @@ public class LoadTsFileAnalyzerTest {
Assert.assertEquals(2, schemaCache.getVerifiedDeviceCount());
}
+ @Test
+ public void testTableLoadEmptyPathIsRejected() {
+ try {
+ new LoadTsFile(null, "", Collections.emptyMap());
+ Assert.fail("Expected empty LOAD TSFILE path to be rejected.");
+ } catch (final RuntimeException e) {
+ Assert.assertTrue(e.getMessage().contains("The LOAD TSFILE path cannot
be empty."));
+ }
+ }
+
@Test
public void testTableSchemaCacheShouldThrowMismatchWhenVerifyingDataType()
throws Exception {
final LoadTsFileTableSchemaCache schemaCache =
createTableSchemaCache(true);
diff --git
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/statement/crud/LoadTsFileStatementTest.java
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/statement/crud/LoadTsFileStatementTest.java
index fac3227f4b5..98b54ea5303 100644
---
a/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/statement/crud/LoadTsFileStatementTest.java
+++
b/iotdb-core/datanode/src/test/java/org/apache/iotdb/db/queryengine/plan/statement/crud/LoadTsFileStatementTest.java
@@ -21,6 +21,7 @@ package org.apache.iotdb.db.queryengine.plan.statement.crud;
import org.apache.iotdb.db.conf.IoTDBConfig;
import org.apache.iotdb.db.conf.IoTDBDescriptor;
+import org.apache.iotdb.db.queryengine.plan.parser.StatementGenerator;
import org.junit.Assert;
import org.junit.Test;
@@ -29,6 +30,7 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.time.ZoneId;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Stream;
@@ -144,6 +146,16 @@ public class LoadTsFileStatementTest {
}
}
+ @Test
+ public void testTreeLoadEmptyPathIsRejected() {
+ try {
+ StatementGenerator.createStatement("LOAD ''", ZoneId.systemDefault());
+ Assert.fail("Expected empty LOAD TSFILE path to be rejected.");
+ } catch (final RuntimeException e) {
+ Assert.assertTrue(e.getMessage().contains("The LOAD TSFILE path cannot
be empty."));
+ }
+ }
+
@Test
public void testLoadPipeReceiverTsFileOutsideDataDirIsAllowed() throws
Exception {
final IoTDBConfig config = IoTDBDescriptor.getInstance().getConfig();