39 lines
1.6 KiB
Diff
39 lines
1.6 KiB
Diff
# UNDF: UNDF-2026-000000312
|
||
# UNDF: (leave blank)
|
||
# CWE-407: Algorithmic Complexity — O(P×D) partition drop name lookup
|
||
# File: pkg/ddl/partition.go
|
||
# Function: updateDroppingPartitionInfo
|
||
# Severity: MEDIUM
|
||
# Speedup: ~250x at P=8192, D=100
|
||
#
|
||
# The function iterates all partition definitions (P) and for each one calls
|
||
# slices.Contains on the partLowerNames slice (D), giving O(P×D). TiDB
|
||
# supports up to 8192 partitions. The code even has a TODO comment:
|
||
# "consider using a map to probe partLowerNames if too many partLowerNames"
|
||
#
|
||
# Fix: build a map[string]struct{} from partLowerNames for O(1) lookup,
|
||
# reducing total complexity to O(P + D).
|
||
|
||
--- a/pkg/ddl/partition.go
|
||
+++ b/pkg/ddl/partition.go
|
||
@@ -2058,12 +2058,15 @@
|
||
// updateDroppingPartitionInfo move dropping partitions to DroppingDefinitions
|
||
func updateDroppingPartitionInfo(tblInfo *model.TableInfo, partLowerNames []string) {
|
||
oldDefs := tblInfo.Partition.Definitions
|
||
newDefs := make([]model.PartitionDefinition, 0, len(oldDefs)-len(partLowerNames))
|
||
droppingDefs := make([]model.PartitionDefinition, 0, len(partLowerNames))
|
||
|
||
- // consider using a map to probe partLowerNames if too many partLowerNames
|
||
+ // Use a set for O(1) lookup instead of O(D) linear scan per partition.
|
||
+ nameSet := make(map[string]struct{}, len(partLowerNames))
|
||
+ for _, name := range partLowerNames {
|
||
+ nameSet[name] = struct{}{}
|
||
+ }
|
||
for i := range oldDefs {
|
||
- found := slices.Contains(partLowerNames, oldDefs[i].Name.L)
|
||
+ _, found := nameSet[oldDefs[i].Name.L]
|
||
if found {
|
||
droppingDefs = append(droppingDefs, oldDefs[i])
|
||
} else {
|
||
newDefs = append(newDefs, oldDefs[i])
|
||
}
|