All projects with patches now have outreach docs. 276 new docs covering CWE-407, CWE-312, CWE-362 across C, C++, Java, Python, Go, Rust, C#, PHP, Ruby, JavaScript, Dart, Erlang, R, and more. Outreach gap: 276 -> 0.
2.7 KiB
Neovim — CWE-407 Disclosure Brief (neovim-0001)
2026-04-13 · Patch available — awaiting upstream merge
Finding
One O(n²) defect in Neovim's completion candidate deduplication. Patched. ins_compl_add() in insexpand.c linearly scans the entire completion match list to detect duplicates every time a new candidate is added.
The Defect
neovim-0001 (PATCHED — MEDIUM): src/nvim/insexpand.c:942
// In ins_compl_add() — fires per completion candidate:
if (compl_first_match != NULL && !adup) {
match = compl_first_match;
do {
if (!match_at_original_text(match)
&& strncmp(match->cp_str.data, str, (size_t)len) == 0
&& ((int)match->cp_str.size <= len || match->cp_str.data[len] == NUL)) {
// duplicate found
return NOTDONE;
}
match = match->cp_next;
} while (match != NULL && !is_first_match(match));
}
compl_first_match is a circular linked list. Every new candidate walks the entire list (O(M) per insertion) for string comparison dedup. With M candidates, total cost: O(M²). Inherited from Vim.
Complexity Proof
At M=1,000 completion candidates:
- Defective: 1,000 × 500 avg = 500,000 string comparisons
- Fixed: 1,000 × O(1) hash lookups = 1,000 operations
- 250× op reduction at 1,000 candidates. Stalls the UI during completion.
Impact
Neovim is a modern fork of Vim, used by millions of developers. Completion sources (tags, buffer words, LSP, dictionary) can produce thousands of candidates. The quadratic dedup causes visible UI stalls when completing from large tag files or many open buffers.
The Fix
Use Neovim's existing hash map infrastructure (map_defs.h) for O(1) dedup:
// Before: O(M) linked-list walk per candidate
match = compl_first_match;
do { strncmp(...); match = match->cp_next; } while (...);
// After: O(1) hash lookup
String key = { .data = (char *)str, .size = (size_t)len };
compl_T **existing = (compl_T **)map_ref(String, ptr_t)(&compl_ht, key, NULL);
if (existing && *existing) { return NOTDONE; }
Patch
Fix available: defects/neovim/patch/
Touches src/nvim/insexpand.c. Uses Neovim's built-in map infrastructure. 250× speedup at 1,000 completion candidates.
What We Ask
A patch is ready for review.
- Confirm receipt and assign a GitHub issue reference (neovim/neovim).
- Assess severity — fires during completion with large candidate sets.
- Coordinate a disclosure date — we are targeting 90 days from first contact.
- We will credit the Neovim team in the public disclosure. Preferred acknowledgment format welcome.
Contact: see cover email. This brief is confidential until coordinated disclosure.