2.3 KiB
UNDF: UNDF-2026-000000453
lldb-0001 — SerializedBreakpointMatchesNames O(B×N²) vector scan
Severity: MEDIUM
CWE: CWE-407 (Inefficient Algorithmic Complexity)
File: lldb/source/Breakpoint/Breakpoint.cpp (line 222)
Caller: lldb/source/Target/Target.cpp:CreateBreakpointsFromFile (line 1266)
Repo: https://github.com/llvm/llvm-project
Defect
Breakpoint::SerializedBreakpointMatchesNames receives a std::vector<std::string> &names filter list and checks each serialized breakpoint's name array against it using llvm::is_contained, which performs a linear scan of the vector.
// lldb/source/Breakpoint/Breakpoint.cpp:242-248
size_t num_names = names_array->GetSize();
for (size_t i = 0; i < num_names; i++) { // O(N_bp) per breakpoint
std::optional<llvm::StringRef> maybe_name =
names_array->GetItemAtIndexAsString(i);
if (maybe_name && llvm::is_contained(names, *maybe_name)) // O(F) scan
return true;
}
Called from Target::CreateBreakpointsFromFile:
// lldb/source/Target/Target.cpp:1293-1307
for (size_t i = 0; i < num_bkpts; i++) { // O(B)
...
if (num_names &&
!Breakpoint::SerializedBreakpointMatchesNames(bkpt_data_sp, names))
continue;
...
}
Total complexity: O(B × N_bp × F) where:
- B = breakpoints in the JSON file
- N_bp = names on each serialized breakpoint
- F = size of the filter
namesvector
When restoring a large session (B=500 breakpoints, each with N_bp=20 names, F=50 filter names), this is 500 × 20 × 50 = 500,000 string comparisons instead of 500 × 20 = 10,000 with a hash set.
Fix
Convert the names parameter from std::vector<std::string> to llvm::StringSet<> (or std::unordered_set<std::string>) before calling SerializedBreakpointMatchesNames, or accept a set directly.
// Fixed: convert once before the loop in CreateBreakpointsFromFile
llvm::StringSet<> names_set(names.begin(), names.end());
// Then pass names_set to SerializedBreakpointMatchesNames
// Inside: names_set.count(*maybe_name) → O(1)
Complexity
| Scenario | Before | After |
|---|---|---|
| B=500, N_bp=20, F=50 | 500K string compares | 10K string compares |
| B=1000, N_bp=10, F=100 | 1M string compares | 10K string compares |
Speedup at B=500, N_bp=20, F=50: ~50x op-count reduction (ratio = F).