From 099ed5633061b5ccd98925979e1ecdb090a8c84a Mon Sep 17 00:00:00 2001 From: Caideyipi <87789683+Caideyipi@users.noreply.github.com> Date: Sat, 25 Jul 2026 19:50:55 +0800 Subject: [PATCH 1/2] Reject illegal device paths during LOAD --- .../persistence/schema/ConfigMTree.java | 5 +++ .../persistence/schema/ConfigMTreeTest.java | 7 ++++ .../TreeSchemaAutoCreatorAndVerifier.java | 6 ++++ .../analyze/load/LoadTsFileAnalyzerTest.java | 36 +++++++++++++++++++ 4 files changed, 54 insertions(+) diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTree.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTree.java index 7456f339af7bd..b3160e9e76184 100644 --- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTree.java +++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTree.java @@ -142,6 +142,11 @@ public void clear() { */ public void setStorageGroup(final PartialPath path) throws MetadataException { final String[] nodeNames = path.getNodes(); + for (final String nodeName : nodeNames) { + if (nodeName == null || nodeName.isEmpty()) { + throw new IllegalPathException(path.getFullPath()); + } + } MetaFormatUtils.checkDatabase(path.getFullPath()); if (nodeNames.length <= 1 || !nodeNames[0].equals(root.getName())) { throw new IllegalPathException(path.getFullPath()); diff --git a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTreeTest.java b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTreeTest.java index c2519dcbfae11..45b55e123e611 100644 --- a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTreeTest.java +++ b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTreeTest.java @@ -102,6 +102,13 @@ public void testSetStorageGroupExceptionMessage() { } } + @Test + public void testSetStorageGroupShouldRejectEmptyPathNode() { + Assert.assertThrows( + IllegalPathException.class, + () -> root.setStorageGroup(new PartialPath(new String[] {"root", ""}))); + } + @Test public void testAddAndPathExist() throws MetadataException { final String path1 = "root"; diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/load/TreeSchemaAutoCreatorAndVerifier.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/load/TreeSchemaAutoCreatorAndVerifier.java index 6d1704c0cfd0a..2e50a88f5d13c 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/load/TreeSchemaAutoCreatorAndVerifier.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/plan/analyze/load/TreeSchemaAutoCreatorAndVerifier.java @@ -359,6 +359,12 @@ private void autoCreateDatabase() final PartialPath devicePath = new PartialPath(device); final String[] devicePrefixNodes = devicePath.getNodes(); + for (final String node : devicePrefixNodes) { + if (node == null || node.isEmpty()) { + throw new LoadAnalyzeException( + new IllegalPathException(devicePath.getFullPath()).getMessage()); + } + } if (devicePrefixNodes.length < databasePrefixNodesLength) { throw new LoadAnalyzeException( String.format( 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 68f4bde29e6a6..0b6e5350882a6 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 @@ -200,6 +200,35 @@ public void testTreeSchemaVerifierShouldThrowMismatchWhenVerifyingDataType() thr } } + @Test + public void testTreeSchemaVerifierShouldRejectDeviceWithEmptyPathNode() throws Exception { + final File tsFile = File.createTempFile("load-tree-illegal-device", ".tsfile"); + + try (final LoadTsFileAnalyzer analyzer = + new LoadTsFileAnalyzer( + LoadTsFileStatement.createUnchecked(tsFile.getAbsolutePath()), + false, + new MPPQueryContext(new QueryId("load_tree_illegal_device_test")))) { + final TreeSchemaAutoCreatorAndVerifier verifier = + new TreeSchemaAutoCreatorAndVerifier(analyzer); + try { + final IDeviceID device = new StringArrayDeviceID(new String[] {"root", ""}); + getTreeSchemaCache(verifier) + .addTimeSeries(device, new MeasurementSchema("s1", TSDataType.INT32)); + + final InvocationTargetException exception = + Assert.assertThrows( + InvocationTargetException.class, + () -> getAutoCreateDatabaseMethod().invoke(verifier)); + Assert.assertTrue(exception.getCause() instanceof LoadAnalyzeException); + } finally { + verifier.close(); + } + } finally { + Assert.assertTrue(tsFile.delete()); + } + } + @Test public void testPipeGeneratedLoadMissingSchemaShouldBeTemporaryWhenAutoCreateDisabled() throws Exception { @@ -316,6 +345,13 @@ private Method getVerifyTreeSchemaMethod() throws NoSuchMethodException { return method; } + private Method getAutoCreateDatabaseMethod() throws NoSuchMethodException { + final Method method = + TreeSchemaAutoCreatorAndVerifier.class.getDeclaredMethod("autoCreateDatabase"); + method.setAccessible(true); + return method; + } + private org.apache.iotdb.commons.queryengine.plan.relational.metadata.TableSchema createTableSchema(final TSDataType fieldType) { return new org.apache.iotdb.commons.queryengine.plan.relational.metadata.TableSchema( From e5d8c2661c0460fcfb64b5bb85fb57ca42c9687d Mon Sep 17 00:00:00 2001 From: Caideyipi <87789683+Caideyipi@users.noreply.github.com> Date: Sat, 25 Jul 2026 20:41:15 +0800 Subject: [PATCH 2/2] Remove duplicate ConfigNode validation --- .../iotdb/confignode/persistence/schema/ConfigMTree.java | 5 ----- .../confignode/persistence/schema/ConfigMTreeTest.java | 7 ------- 2 files changed, 12 deletions(-) diff --git a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTree.java b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTree.java index b3160e9e76184..7456f339af7bd 100644 --- a/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTree.java +++ b/iotdb-core/confignode/src/main/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTree.java @@ -142,11 +142,6 @@ public void clear() { */ public void setStorageGroup(final PartialPath path) throws MetadataException { final String[] nodeNames = path.getNodes(); - for (final String nodeName : nodeNames) { - if (nodeName == null || nodeName.isEmpty()) { - throw new IllegalPathException(path.getFullPath()); - } - } MetaFormatUtils.checkDatabase(path.getFullPath()); if (nodeNames.length <= 1 || !nodeNames[0].equals(root.getName())) { throw new IllegalPathException(path.getFullPath()); diff --git a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTreeTest.java b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTreeTest.java index 45b55e123e611..c2519dcbfae11 100644 --- a/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTreeTest.java +++ b/iotdb-core/confignode/src/test/java/org/apache/iotdb/confignode/persistence/schema/ConfigMTreeTest.java @@ -102,13 +102,6 @@ public void testSetStorageGroupExceptionMessage() { } } - @Test - public void testSetStorageGroupShouldRejectEmptyPathNode() { - Assert.assertThrows( - IllegalPathException.class, - () -> root.setStorageGroup(new PartialPath(new String[] {"root", ""}))); - } - @Test public void testAddAndPathExist() throws MetadataException { final String path1 = "root";