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);