This is an automated email from the ASF dual-hosted git repository.

jlfsdtc pushed a commit to branch kylin5
in repository https://gitbox.apache.org/repos/asf/kylin.git


The following commit(s) were added to refs/heads/kylin5 by this push:
     new f274934caf KYLIN-6089 Validate table name in TableService#refreshTable
f274934caf is described below

commit f274934caf1d071ccd226043f064a6e9016730d7
Author: jlf <[email protected]>
AuthorDate: Wed Apr 22 15:19:23 2026 +0800

    KYLIN-6089 Validate table name in TableService#refreshTable
---
 .../org/apache/kylin/common/msg/CnMessage.java     |  5 ++++
 .../java/org/apache/kylin/common/msg/Message.java  |  4 ++++
 .../apache/kylin/rest/service/TableService.java    | 27 ++++++++++++++++++++++
 .../kylin/rest/service/TableServiceTest.java       | 21 +++++++++++++++--
 4 files changed, 55 insertions(+), 2 deletions(-)

diff --git 
a/src/core-common/src/main/java/org/apache/kylin/common/msg/CnMessage.java 
b/src/core-common/src/main/java/org/apache/kylin/common/msg/CnMessage.java
index e457e5139f..29d524d043 100644
--- a/src/core-common/src/main/java/org/apache/kylin/common/msg/CnMessage.java
+++ b/src/core-common/src/main/java/org/apache/kylin/common/msg/CnMessage.java
@@ -731,6 +731,11 @@ public class CnMessage extends Message {
         return "请求中的 “tables” 字段无效。请检查后重试。";
     }
 
+    @Override
+    public String getInvalidTableName() {
+        return "表 \"%s\" 无效。请检查后重试。";
+    }
+
     @Override
     public String getTableRefreshParamMore() {
         return "请求中包含非 “tables“ 的多余字段。请检查后重试。";
diff --git 
a/src/core-common/src/main/java/org/apache/kylin/common/msg/Message.java 
b/src/core-common/src/main/java/org/apache/kylin/common/msg/Message.java
index ef13e429d3..1d39c92ad1 100644
--- a/src/core-common/src/main/java/org/apache/kylin/common/msg/Message.java
+++ b/src/core-common/src/main/java/org/apache/kylin/common/msg/Message.java
@@ -801,6 +801,10 @@ public class Message {
         return "The “table“ parameter is invalid. Please check and try again.";
     }
 
+    public String getInvalidTableName() {
+        return "The table name \"%s\" is invalid. Please check and try again.";
+    }
+
     public String getTableRefreshParamMore() {
         return "There exists invalid filed(s) other than the expected 
“tables“. Please check and try again.";
     }
diff --git 
a/src/datasource-service/src/main/java/org/apache/kylin/rest/service/TableService.java
 
b/src/datasource-service/src/main/java/org/apache/kylin/rest/service/TableService.java
index 54dc5ca639..b6cb447631 100644
--- 
a/src/datasource-service/src/main/java/org/apache/kylin/rest/service/TableService.java
+++ 
b/src/datasource-service/src/main/java/org/apache/kylin/rest/service/TableService.java
@@ -25,6 +25,7 @@ import static 
org.apache.kylin.common.exception.ServerErrorCode.FAILED_IMPORT_SS
 import static 
org.apache.kylin.common.exception.ServerErrorCode.FAILED_REFRESH_CATALOG_CACHE;
 import static org.apache.kylin.common.exception.ServerErrorCode.FILE_NOT_EXIST;
 import static 
org.apache.kylin.common.exception.ServerErrorCode.INVALID_COMPUTED_COLUMN_EXPRESSION;
+import static org.apache.kylin.common.exception.ServerErrorCode.INVALID_NAME;
 import static 
org.apache.kylin.common.exception.ServerErrorCode.INVALID_PARTITION_COLUMN;
 import static 
org.apache.kylin.common.exception.ServerErrorCode.TABLE_NOT_EXIST;
 import static 
org.apache.kylin.common.exception.code.ErrorCodeServer.MODEL_ID_NOT_EXIST;
@@ -55,6 +56,7 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.function.BiFunction;
 import java.util.function.Function;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
@@ -194,6 +196,11 @@ public class TableService extends BasicService {
 
     private static final String SSB_ERROR_MSG = "import ssb data error.";
 
+    /**
+     * refer to {@link 
org.apache.spark.sql.catalyst.catalog.SessionCatalog#validateName}
+     */
+    private static final Pattern VALID_NAME_PATTERN = 
Pattern.compile("([\\w_]+)");
+
     @Autowired
     private TableModelSupporter modelService;
 
@@ -1879,6 +1886,10 @@ public class TableService extends BasicService {
 
     public void refreshTable(String table, List<String> refreshed, 
List<String> failed) {
         try {
+            if (!isValidTableIdentifier(table)) {
+                throw new KylinException(INVALID_NAME,
+                        String.format(Locale.ROOT, 
MsgPicker.getMsg().getInvalidTableName(), table));
+            }
             PushDownUtil.trySimplyExecute("REFRESH TABLE " + table, null);
             refreshed.add(table);
         } catch (Exception e) {
@@ -1887,6 +1898,22 @@ public class TableService extends BasicService {
         }
     }
 
+    private static boolean isValidTableIdentifier(String table) {
+        if (StringUtils.isBlank(table)) {
+            return false;
+        }
+        String[] parts = table.split("\\.", -1);
+        if (parts.length > 2) {
+            return false;
+        }
+        for (String part : parts) {
+            if (!VALID_NAME_PATTERN.matcher(part).matches()) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     public TableRefreshAll refreshAllCatalogCache(final HttpServletRequest 
request) {
 
         val message = MsgPicker.getMsg();
diff --git 
a/src/modeling-service/src/test/java/org/apache/kylin/rest/service/TableServiceTest.java
 
b/src/modeling-service/src/test/java/org/apache/kylin/rest/service/TableServiceTest.java
index 1c3b6395fc..712de38f5a 100644
--- 
a/src/modeling-service/src/test/java/org/apache/kylin/rest/service/TableServiceTest.java
+++ 
b/src/modeling-service/src/test/java/org/apache/kylin/rest/service/TableServiceTest.java
@@ -477,8 +477,7 @@ public class TableServiceTest extends CSVSourceTestCase {
         tableService.filterSamplingRows("newten", tableDescResponse, false, 
aclTCRs);
 
         Assert.assertEquals(1, tableDescResponse.getSamplingRows().size());
-        Assert.assertEquals("country_a,11.11,name_%a",
-                String.join(",", tableDescResponse.getSamplingRows().get(0)));
+        Assert.assertEquals("country_a,11.11,name_%a", String.join(",", 
tableDescResponse.getSamplingRows().get(0)));
     }
 
     @Test
@@ -1090,6 +1089,24 @@ public class TableServiceTest extends CSVSourceTestCase {
         SparderEnv.getSparkSession().stop();
     }
 
+    @Test
+    public void testRefreshTableInvalidName() {
+        List<String> refreshed = Lists.newArrayList();
+        List<String> failed = Lists.newArrayList();
+        String[] invalidNames = { "", " ", "a-b", "a b", "a;DROP TABLE t", 
"`a`", "tbl; SELECT 1", "db.tbl.extra",
+                ".tbl", "tbl;", "tbl,", "db.", "db..tbl", "db.tbl;DROP", 
"db.a-b", "db.tbl;" };
+        for (String name : invalidNames) {
+            tableService.refreshTable(name, refreshed, failed);
+        }
+        tableService.refreshTable(null, refreshed, failed);
+
+        Assert.assertTrue(refreshed.isEmpty());
+        Assert.assertFalse(failed.isEmpty());
+        Assert.assertEquals(invalidNames.length + 1, failed.size());
+        Assert.assertTrue(failed.contains(null));
+        Assert.assertTrue(failed.containsAll(Arrays.asList(invalidNames)));
+    }
+
     private HashMap<String, List<String>> mockRefreshTable(String... tables) {
         Mockito.doAnswer(invocation -> {
             String table = invocation.getArgument(0);

Reply via email to