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

morrySnow 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 a8216b532fe [fix](fe) Fix Type.exceedsMaxNestingDepth skipping MAP 
keyType recursion (#63201)
a8216b532fe is described below

commit a8216b532febf3f0635b036a1b2ac6e562eede02
Author: morrySnow <[email protected]>
AuthorDate: Wed May 13 16:38:42 2026 +0800

    [fix](fe) Fix Type.exceedsMaxNestingDepth skipping MAP keyType recursion 
(#63201)
    
    ## Summary
    
    `Type.exceedsMaxNestingDepth` in the MAP branch only recursed into
    `valueType` and silently skipped `keyType`. A user could construct
    arbitrarily deep types via the MAP key path, bypassing the 9-layer
    nesting limit.
    
    ### What problem does this PR solve?
    
    Problem Summary:
    
    ```java
    // Before fix — MAP branch:
    } else if (isMapType()) {
        MapType mapType = (MapType) this;
        return mapType.getValueType().exceedsMaxNestingDepth(d + 1);  // 
keyType never checked
    }
    ```
    
    ARRAY and STRUCT branches recursed correctly; only MAP missed the
    keyType path.
    
    ### Fix
    
    ```java
    } else if (isMapType()) {
        MapType mapType = (MapType) this;
        if (mapType.getKeyType().exceedsMaxNestingDepth(d + 1)) {
            return true;
        }
        return mapType.getValueType().exceedsMaxNestingDepth(d + 1);
    }
    ```
    
    ### Tests
    
    Three new FE unit tests added to `TypeTest`:
    
    - `testMapKeyPathNestingWithinLimit` — `MAX_NESTING_DEPTH` levels via
    keyType → allowed (assertFalse)
    - `testMapKeyPathDeepNestingDetected` — `MAX_NESTING_DEPTH + 1` levels
    via keyType → rejected (assertTrue)
    - `testMapValuePathDeepNestingDetected` — regression guard: valueType
    path still detected (assertTrue)
    
    All 11 tests in `TypeTest` pass.
    
    ### Release note
    
    Fix MAP key-type nesting-depth check bypass: deeply-nested MAP key types
    are now correctly rejected with "Type exceeds the maximum nesting
    depth".
    
    Co-authored-by: Copilot <[email protected]>
---
 .../java/org/apache/doris/catalog/TypeTest.java    | 40 ++++++++++++++++++++++
 .../main/java/org/apache/doris/catalog/Type.java   |  3 ++
 2 files changed, 43 insertions(+)

diff --git a/fe/fe-core/src/test/java/org/apache/doris/catalog/TypeTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/catalog/TypeTest.java
index 29353ae6c50..cb544d3d01c 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/catalog/TypeTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/catalog/TypeTest.java
@@ -185,6 +185,46 @@ public class TypeTest {
         Assert.assertFalse(Type.matchExactType(d20s1, d38s1, false));
     }
 
+    // ===================== exceedsMaxNestingDepth =====================
+
+    /**
+     * Builds a MAP<MAP<...<MAP<STRING, STRING>>...>, STRING> with the given 
number of outer MAP wrappers.
+     * This tests the keyType recursion path of exceedsMaxNestingDepth().
+     */
+    private static Type buildMapKeyNestedType(int depth) {
+        // innermost: MAP<STRING, STRING> counts as depth 1 (from the caller's 
perspective we start at d=0)
+        Type current = new MapType(Type.STRING, Type.STRING, true, true);
+        for (int i = 1; i < depth; i++) {
+            current = new MapType(current, Type.STRING, true, true);
+        }
+        return current;
+    }
+
+    @Test
+    public void testMapKeyPathNestingWithinLimit() {
+        // MAP < MAP < ... STRING ...>, STRING > with total nesting == 
MAX_NESTING_DEPTH should be allowed
+        Type t = buildMapKeyNestedType(Type.MAX_NESTING_DEPTH);
+        Assert.assertFalse(t.exceedsMaxNestingDepth());
+    }
+
+    @Test
+    public void testMapKeyPathDeepNestingDetected() {
+        // Nesting depth of MAX_NESTING_DEPTH + 1 via keyType path must be 
rejected
+        Type t = buildMapKeyNestedType(Type.MAX_NESTING_DEPTH + 1);
+        Assert.assertTrue(t.exceedsMaxNestingDepth());
+    }
+
+    @Test
+    public void testMapValuePathDeepNestingDetected() {
+        // Existing valueType path should still be detected (regression guard).
+        // Need MAX_NESTING_DEPTH + 1 wraps so the innermost reaches d = 
MAX_NESTING_DEPTH + 1.
+        Type current = Type.STRING;
+        for (int i = 0; i <= Type.MAX_NESTING_DEPTH; i++) {
+            current = new MapType(Type.STRING, current, true, true);
+        }
+        Assert.assertTrue(current.exceedsMaxNestingDepth());
+    }
+
     @Test
     public void testDatetimeV2ScaleMatching() {
         ScalarType dtv2s3 = ScalarType.createDatetimeV2Type(3);
diff --git a/fe/fe-type/src/main/java/org/apache/doris/catalog/Type.java 
b/fe/fe-type/src/main/java/org/apache/doris/catalog/Type.java
index 6af6a174766..8a544cade38 100644
--- a/fe/fe-type/src/main/java/org/apache/doris/catalog/Type.java
+++ b/fe/fe-type/src/main/java/org/apache/doris/catalog/Type.java
@@ -797,6 +797,9 @@ public abstract class Type {
             return itemType.exceedsMaxNestingDepth(d + 1);
         } else if (isMapType()) {
             MapType mapType = (MapType) this;
+            if (mapType.getKeyType().exceedsMaxNestingDepth(d + 1)) {
+                return true;
+            }
             return mapType.getValueType().exceedsMaxNestingDepth(d + 1);
         } else {
             Preconditions.checkState(isScalarType() || isAggStateType());


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to