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

morningman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new 0993bd5723e [fix](auth)Fixed the issue of not adding escape characters 
in the regular code, which allowed usernames to use colons (#49459)
0993bd5723e is described below

commit 0993bd5723e86849654f04730df94bf0d5f62281
Author: zhangdong <zhangd...@selectdb.com>
AuthorDate: Wed Apr 2 17:29:01 2025 +0800

    [fix](auth)Fixed the issue of not adding escape characters in the regular 
code, which allowed usernames to use colons (#49459)
    
    ### What problem does this PR solve?
    
    Due to incorrect regularization, users are able to create a user named
    default_cluster: xxx. When replaying logs, compatibility operations will
    automatically remove the default_cluster prefix, which may cause users
    to duplicate
    
    It doesn't affect whether escape characters are added or not, except for
    USER_NAME_REGEX, because in other regularization, the position of -
    doesn't have a special meaning. But for better understanding, all
    regular - characters are uniformly prefixed with escape characters,
    
    Issue Number: close #xxx
    
    Related PR: #xxx
    
    Problem Summary:
    Fixed the issue of not adding escape characters in the regular code,
    which allowed usernames to use colons
    ### Release note
    
    Fixed the issue of not adding escape characters in the regular code,
    which allowed usernames to use colons
---
 .../java/org/apache/doris/common/FeNameFormat.java |  30 +-
 .../org/apache/doris/common/FeNameFormatTest.java  | 330 ++++++++++++++++++---
 2 files changed, 307 insertions(+), 53 deletions(-)

diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/FeNameFormat.java 
b/fe/fe-core/src/main/java/org/apache/doris/common/FeNameFormat.java
index 854ec73eabe..4a174913a72 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/common/FeNameFormat.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/common/FeNameFormat.java
@@ -29,24 +29,24 @@ import org.apache.doris.qe.VariableMgr;
 import com.google.common.base.Strings;
 
 public class FeNameFormat {
-    private static final String LABEL_REGEX = "^[-_A-Za-z0-9:]{1," + 
Config.label_regex_length + "}$";
+    private static final String LABEL_REGEX = "^[\\-_A-Za-z0-9:]{1," + 
Config.label_regex_length + "}$";
     // if modify the matching length of a regular expression,
     // please modify error msg when FeNameFormat.checkCommonName throw 
exception in CreateRoutineLoadStmt
-    private static final String COMMON_NAME_REGEX = 
"^[a-zA-Z][a-zA-Z0-9-_]{0,63}$";
-    private static final String UNDERSCORE_COMMON_NAME_REGEX = 
"^[_a-zA-Z][a-zA-Z0-9-_]{0,63}$";
-    private static final String TABLE_NAME_REGEX = "^[a-zA-Z][a-zA-Z0-9-_]*$";
-    private static final String USER_NAME_REGEX = "^[a-zA-Z][a-zA-Z0-9.-_]*$";
-    private static final String REPOSITORY_NAME_REGEX = 
"^[a-zA-Z][a-zA-Z0-9-_]{0,255}$";
-    private static final String COLUMN_NAME_REGEX = 
"^[.a-zA-Z0-9_+-/?@#$%^&*\"\\s,:]{1,256}$";
-
-    private static final String UNICODE_LABEL_REGEX = 
"^[-_A-Za-z0-9:\\p{L}]{1," + Config.label_regex_length + "}$";
-    private static final String UNICODE_COMMON_NAME_REGEX = 
"^[a-zA-Z\\p{L}][a-zA-Z0-9-_\\p{L}]{0,63}$";
-    private static final String UNICODE_UNDERSCORE_COMMON_NAME_REGEX = 
"^[_a-zA-Z\\p{L}][a-zA-Z0-9-_\\p{L}]{0,63}$";
-    private static final String UNICODE_TABLE_NAME_REGEX = 
"^[a-zA-Z\\p{L}][a-zA-Z0-9-_\\p{L}]*$";
-    private static final String UNICODE_USER_NAME_REGEX = 
"^[a-zA-Z\\p{L}][a-zA-Z0-9.-_\\p{L}]*$";
+    private static final String COMMON_NAME_REGEX = 
"^[a-zA-Z][a-zA-Z0-9\\-_]{0,63}$";
+    private static final String UNDERSCORE_COMMON_NAME_REGEX = 
"^[_a-zA-Z][a-zA-Z0-9\\-_]{0,63}$";
+    private static final String TABLE_NAME_REGEX = 
"^[a-zA-Z][a-zA-Z0-9\\-_]*$";
+    private static final String USER_NAME_REGEX = 
"^[a-zA-Z][a-zA-Z0-9.\\-_]*$";
+    private static final String REPOSITORY_NAME_REGEX = 
"^[a-zA-Z][a-zA-Z0-9\\-_]{0,255}$";
+    private static final String COLUMN_NAME_REGEX = 
"^[.a-zA-Z0-9_+\\-/?@#$%^&*\"\\s,:]{1,256}$";
+
+    private static final String UNICODE_LABEL_REGEX = 
"^[\\-_A-Za-z0-9:\\p{L}]{1," + Config.label_regex_length + "}$";
+    private static final String UNICODE_COMMON_NAME_REGEX = 
"^[a-zA-Z\\p{L}][a-zA-Z0-9\\-_\\p{L}]{0,63}$";
+    private static final String UNICODE_UNDERSCORE_COMMON_NAME_REGEX = 
"^[_a-zA-Z\\p{L}][a-zA-Z0-9\\-_\\p{L}]{0,63}$";
+    private static final String UNICODE_TABLE_NAME_REGEX = 
"^[a-zA-Z\\p{L}][a-zA-Z0-9\\-_\\p{L}]*$";
+    private static final String UNICODE_USER_NAME_REGEX = 
"^[a-zA-Z\\p{L}][a-zA-Z0-9.\\-_\\p{L}]*$";
     private static final String UNICODE_COLUMN_NAME_REGEX
-            = "^[.a-zA-Z0-9_+-/?@#$%^&*\"\\s,:\\p{L}]{1,256}$";
-    private static final String UNICODE_REPOSITORY_NAME_REGEX = 
"^[a-zA-Z\\p{L}][a-zA-Z0-9-_\\p{L}]{0,255}$";
+            = "^[.a-zA-Z0-9_+\\-/?@#$%^&*\"\\s,:\\p{L}]{1,256}$";
+    private static final String UNICODE_REPOSITORY_NAME_REGEX = 
"^[a-zA-Z\\p{L}][a-zA-Z0-9\\-_\\p{L}]{0,255}$";
 
     public static final String FORBIDDEN_PARTITION_NAME = "placeholder_";
 
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/common/FeNameFormatTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/common/FeNameFormatTest.java
index 32e2a553b94..e4a3b9c9f3c 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/common/FeNameFormatTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/common/FeNameFormatTest.java
@@ -23,26 +23,103 @@ import com.google.common.collect.Lists;
 import org.apache.ivy.util.StringUtils;
 import org.junit.jupiter.api.Test;
 
+import java.util.Arrays;
 import java.util.List;
 
 public class FeNameFormatTest {
 
     @Test
     void testLabelName() {
-        // check label use correct regex, begin with '-' is different from 
others
-        ExceptionChecker.expectThrowsNoException(() -> 
FeNameFormat.checkLabel("-lable"));
+        List<String> alwaysValid = Lists.newArrayList(
+                "abc123",        // alphanumeric
+                "A-B_C:D",       // contains all allowed special chars
+                "0-1_2:3",       // starts with number, contains special chars
+                "a",             // single character
+                "X-Y-Z",         // hyphens and uppercase
+                "test_123:456",  // mixed with underscore and colon
+                "-valid",        // starts with hyphen
+                "_valid",        // starts with underscore
+                ":valid",        // starts with colon
+                StringUtils.repeat("a", Config.label_regex_length)  // maximum 
length
+        );
+
+        List<String> alwaysInvalid = Lists.newArrayList(
+                "",              // empty string
+                " ",             // space character
+                "a b",           // contains space
+                "a.b",           // contains dot
+                "a@b",           // contains @
+                "a\nb",          // contains newline
+                "a$b",           // contains $
+                "a*b",           // contains *
+                "a#b",           // contains #
+                StringUtils.repeat("a", Config.label_regex_length + 1) // 
maximum length
+        );
+
+        List<String> unicodeValid = Lists.newArrayList(
+                "äöü",          // German umlauts
+                "北京",         // Chinese characters
+                "東京123",      // Japanese with numbers
+                "München",      // German city name
+                "Beyoncé",      // French name
+                "αβγ",          // Greek letters
+                "русский",      // Russian letters
+                "naïve",        // French word
+                "Ḥello",        // special diacritic
+                "øre",          // Nordic word
+                "café",         // French word
+                "ẞig"           // German sharp S
+        );
+
+        test(FeNameFormat::checkLabel, alwaysValid, alwaysInvalid, 
unicodeValid);
     }
 
     @Test
     void testTableName() {
-        // length 64
-        String tblName = 
"test_sys_partition_list_basic_test_list_partition_bigint_tb-uniq";
-        ExceptionChecker.expectThrowsNoException(() -> 
FeNameFormat.checkTableName(tblName));
-        // length 70
-        String largeTblName = 
"test_sys_partition_list_basic_test_list_partition_bigint_tb_uniq_large";
-        ExceptionChecker.expectThrows(AnalysisException.class, () -> 
FeNameFormat.checkTableName(largeTblName));
-        // check table name use correct regex, not begin with '-'
-        ExceptionChecker.expectThrows(AnalysisException.class, () -> 
FeNameFormat.checkTableName("-" + tblName));
+        List<String> alwaysValid = Lists.newArrayList(
+                "abc123",    // Starts with ASCII letter, contains 
alphanumerics + underscores
+                "A_1_b",     // Contains allowed symbols (underscore)
+                "Z",         // Single ASCII letter
+                "a1b2c3",    // Alphanumeric combination
+                "x_y_z",     // Contains underscores
+                "test",      // Letters only
+                "a_b_c",     // Multiple underscores
+                "a_1",       // Underscore + number
+                "B2"         // Uppercase letter + number
+        );
+
+        List<String> alwaysInvalid = Lists.newArrayList(
+                "1abc",      // Starts with digit
+                "@test",     // Contains invalid symbol @
+                "",          // Empty string
+                "a b",       // Contains space
+                "abc!",      // Contains invalid symbol !
+                "a\nb",      // Contains newline
+                "abc$",      // Contains invalid symbol $
+                "-abc",      // Starts with hyphen
+                "_abc",      // Starts with underscore
+                "a*b",       // Contains asterisk
+                "a.b",       // Contains dot
+                "a#b"        // Contains hash
+        );
+
+        List<String> unicodeValid = Lists.newArrayList(
+                "éclair",    // Contains French letter
+                "über",      // Contains German umlaut
+                "北京",      // Chinese characters
+                "東京123",   // Japanese characters + numbers
+                "München",   // Contains umlaut
+                "Beyoncé",   // Contains French accent
+                "αβγ",       // Greek letters
+                "русский",   // Cyrillic letters
+                "øre",       // Nordic letter
+                "ção",       // Portuguese letter
+                "naïve",     // Contains diacritic
+                "Ḥello",     // Contains special diacritic
+                "ẞig"        // German sharp S
+        );
+
+        test(FeNameFormat::checkTableName, alwaysValid, alwaysInvalid, 
unicodeValid);
     }
 
     @Test
@@ -92,22 +169,223 @@ public class FeNameFormatTest {
                 "げんご"
         );
 
+        test(FeNameFormat::checkColumnName, alwaysValid, alwaysInvalid, 
unicodeValid);
+    }
+
+    @Test
+    void testUserName() {
+        List<String> alwaysValid = Arrays.asList(
+                "a",
+                "abc123",
+                "A-1_b.c",
+                "x.y-z_123",
+                "test",
+                "a.b-c_d",
+                "Z",
+                "a-",
+                "a_",
+                "a."
+        );
+        List<String> alwaysInvalid = Arrays.asList(
+                "1abc",      // starts with digit
+                "@test",     // contains invalid character @
+                "a b",       // contains space
+                "",          // empty string
+                "-abc",      // starts with hyphen
+                ".abc",      // starts with dot
+                "_abc",      // starts with underscore
+                "abc!",      // contains invalid character !
+                "abc\n",     // contains newline
+                "9",         // digit only
+                " ",         // whitespace only
+                "a\tb",      // contains tab
+                "a\nb",      // contains newline
+                "a*",        // contains asterisk
+                "a(",         // contains parenthesis
+                "a:b",        // contains colon
+                " ab"         // contains space
+        );
+        List<String> unicodeValid = Lists.newArrayList(
+                "éclair",       // starts with accented letter
+                "über",         // starts with umlaut
+                "北京abc",       // starts with Chinese characters
+                "東京123",       // starts with Japanese kanji
+                "русский",      // starts with Cyrillic letters
+                "αβγ.123",      // starts with Greek letters
+                "München",      // contains umlaut
+                "Beyoncé",      // contains accented letter
+                "naïve"       // contains diacritic
+        );
+        test(FeNameFormat::checkUserName, alwaysValid, alwaysInvalid, 
unicodeValid);
+    }
+
+    @Test
+    void testCommonName() {
+        List<String> alwaysValid = Arrays.asList(
+                "abc123",    // ASCII letters + numbers
+                "A-1_b",     // with allowed symbols (-_)
+                "Z",         // single ASCII letter
+                "a1b2c3",    // alphanumeric
+                "x_y-z",     // underscore and hyphen
+                "test",      // letters only
+                "a-b-c",     // multiple hyphens
+                "a_b",       // underscore
+                "a-1",       // hyphen + number
+                "B2"         // uppercase + number
+        );
+        List<String> alwaysInvalid = Arrays.asList(
+                "1abc",      // starts with number
+                "@test",     // contains invalid symbol @
+                "",          // empty string
+                "a b",       // contains space
+                "abc!",      // contains invalid symbol !
+                "a\nb",      // contains newline
+                "abc$",      // contains invalid symbol $
+                "-abc",      // starts with hyphen
+                "_abc",      // starts with underscore
+                StringUtils.repeat("a", 65), // exceeds length limit (64)
+                "a*b",       // contains asterisk
+                "a.b",       // contains dot (if not allowed)
+                "a#b"        // contains hash symbol
+        );
+        List<String> unicodeValid = Lists.newArrayList(
+                "éclair",    // French letters
+                "über",      // German umlaut
+                "北京",      // Chinese characters
+                "東京123",   // Japanese + numbers
+                "München",   // German umlaut
+                "Beyoncé",   // French accent
+                "αβγ",       // Greek letters
+                "русский",   // Cyrillic letters
+                "øre",       // Nordic letter
+                "ção",       // Portuguese letter
+                "naïve",     // French diacritic
+                "Ḥello",     // special diacritic
+                "ẞig"        // German sharp S
+        );
+        test(FeNameFormatTest::checkCommonName, alwaysValid, alwaysInvalid, 
unicodeValid);
+    }
+
+    @Test
+    void testOutfileName() {
+        List<String> alwaysValid = Arrays.asList(
+                "_valid",      // starts with underscore
+                "a1_b-c",      // letters, numbers, hyphens, underscores
+                "ValidName",   // standard camel case
+                "x_123",       // underscore + numbers
+                "A_B_C",       // multiple underscores
+                "z",           // single letter
+                "_9value",     // starts with _, contains number
+                "a-b",         // simple hyphenated
+                "MAX_LENGTH"   // uppercase with underscores
+        );
+        List<String> alwaysInvalid = Arrays.asList(
+                "1invalid",    // starts with number
+                "@test",       // invalid starting character
+                "",            // empty string
+                "has space",   // contains space
+                "a.b",         // contains dot
+                "a*b",         // contains asterisk
+                "a\nb",        // contains newline
+                "-invalid",     // starts with hyphen
+                "a#b",         // contains hash
+                StringUtils.repeat("a", 65), // exceeds length limit (64)
+                "a>b",         // contains angle bracket
+                "a$b"          // contains dollar sign
+        );
+        List<String> unicodeValid = Lists.newArrayList(
+                "_éclair",     // starts with _, contains French letter
+                "über",        // German umlaut
+                "_北京",       // starts with _, Chinese characters
+                "東京123",     // Japanese + numbers
+                "München",     // German umlaut
+                "Beyoncé",     // French accent
+                "αβγ",         // Greek letters
+                "_русский",    // starts with _, Cyrillic letters
+                "naïve",       // French diacritic
+                "Ḥello",       // special diacritic
+                "ẞig",         // German sharp S
+                "øre",         // Nordic letter
+                "_ção"         // starts with _, Portuguese letter
+        );
+        test(FeNameFormatTest::checkOutfileSuccessFileName, alwaysValid, 
alwaysInvalid, unicodeValid);
+    }
+
+    @Test
+    void checkRepositoryName() {
+        List<String> alwaysValid = Arrays.asList(
+                "validName",      // Standard ASCII letters
+                "A1_b2",         // Letters, numbers, underscore
+                "Product123",     // CamelCase with numbers
+                "x_y_z",         // Multiple underscores
+                "test",          // Lowercase only
+                "MAX_LENGTH",    // Uppercase with underscores
+                "a1-b2",         // Hyphen included
+                "Z",             // Single character
+                StringUtils.repeat("a", 256)  // Maximum length (255 chars)
+        );
+        List<String> alwaysInvalid = Arrays.asList(
+                "",               // Empty string
+                " ",              // Space character
+                "1stInvalid",     // Starts with number
+                "@username",      // Invalid starting character
+                "name with space", // Contains space
+                "a.b",            // Contains dot
+                "a*b",            // Contains asterisk
+                "a\nb",           // Contains newline
+                "a$b",            // Contains dollar sign
+                "a#b",            // Contains hash
+                StringUtils.repeat("a", 257),  // Exceeds length limit (255)
+                "-invalid"        // Starts with hyphen
+        );
+        List<String> unicodeValid = Lists.newArrayList(
+                "München",       // German umlaut
+                "Beyoncé",       // French accent
+                "東京太郎",      // Japanese characters
+                "北京123",       // Chinese with numbers
+                "αβγ",           // Greek letters
+                "русский",       // Cyrillic letters
+                "naïve",         // French diacritic
+                "øre",           // Nordic letter
+                "café",          // French word
+                "Ḥello",         // Special diacritic
+                "ẞig",           // German sharp S
+                "SãoPaulo"       // Portuguese
+        );
+        test(FeNameFormat::checkRepositoryName, alwaysValid, alwaysInvalid, 
unicodeValid);
+    }
+
+    private static void checkOutfileSuccessFileName(String name) throws 
AnalysisException {
+        FeNameFormat.checkOutfileSuccessFileName("fakeType", name);
+    }
+
+    private static void checkCommonName(String name) throws AnalysisException {
+        FeNameFormat.checkCommonName("fakeType", name);
+    }
+
+    @FunctionalInterface
+    public interface NameValidator {
+        void accept(String name) throws AnalysisException;
+    }
+
+    private void test(NameValidator validator, List<String> alwaysValid, 
List<String> alwaysInvalid,
+            List<String> unicodeValid) {
         boolean defaultUnicode = 
VariableMgr.getDefaultSessionVariable().enableUnicodeNameSupport;
         List<Boolean> enableUnicode = Lists.newArrayList(false, true);
         try {
             for (Boolean unicode : enableUnicode) {
                 
VariableMgr.getDefaultSessionVariable().setEnableUnicodeNameSupport(unicode);
                 for (String s : alwaysValid) {
-                    ExceptionChecker.expectThrowsNoException(() -> 
FeNameFormat.checkColumnName(s));
+                    ExceptionChecker.expectThrowsNoException(() -> 
validator.accept(s));
                 }
                 for (String s : alwaysInvalid) {
-                    ExceptionChecker.expectThrows(AnalysisException.class, () 
-> FeNameFormat.checkColumnName(s));
+                    ExceptionChecker.expectThrows(AnalysisException.class, () 
-> validator.accept(s));
                 }
                 for (String s : unicodeValid) {
                     if (unicode) {
-                        ExceptionChecker.expectThrowsNoException(() -> 
FeNameFormat.checkColumnName(s));
+                        ExceptionChecker.expectThrowsNoException(() -> 
validator.accept(s));
                     } else {
-                        ExceptionChecker.expectThrows(AnalysisException.class, 
() -> FeNameFormat.checkColumnName(s));
+                        ExceptionChecker.expectThrows(AnalysisException.class, 
() -> validator.accept(s));
                     }
                 }
             }
@@ -115,28 +393,4 @@ public class FeNameFormatTest {
             
VariableMgr.getDefaultSessionVariable().setEnableUnicodeNameSupport(defaultUnicode);
         }
     }
-
-    @Test
-    void testUserName() {
-        ExceptionChecker.expectThrowsNoException(() -> 
FeNameFormat.checkUserName("a.b"));
-        // check user name use correct regex, not begin with '.'
-        ExceptionChecker.expectThrows(AnalysisException.class, () -> 
FeNameFormat.checkUserName(".a.b"));
-    }
-
-    @Test
-    void testCommonName() {
-        String commonName = 
"test_sys_partition_list_basic_test_list_partition_bigint_tb-uniq";
-
-        // check common name use correct regex, length 65
-        ExceptionChecker.expectThrows(AnalysisException.class, () -> 
FeNameFormat.checkCommonName("fakeType", commonName + "t"));
-        ExceptionChecker.expectThrows(AnalysisException.class, () -> 
FeNameFormat.checkCommonName("fakeType", "_commonName"));
-        ExceptionChecker.expectThrowsNoException(() -> 
FeNameFormat.checkCommonName("fakeType", "common-Name"));
-        ExceptionChecker.expectThrowsNoException(() -> 
FeNameFormat.checkCommonName("fakeType", "commonName-"));
-    }
-
-    @Test
-    void testOutfileName() {
-        // check success file name prefix
-        ExceptionChecker.expectThrowsNoException(() -> 
FeNameFormat.checkOutfileSuccessFileName("fakeType", "_success"));
-    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to