java-topology/defects/neovim/unit/NeovimTest.java
russell@unturf.com 178d9c03db scan: HandBrake + Emacs CWE-407 — both CLEAN
HandBrake: libhb uses array-backed lists bounded by media metadata
sizes (tracks, subtitles, chapters, presets). No user-controlled
quadratic growth path found.

Emacs: C core uses Fmemq/Fmember on small bounded lists (property
lists, error conditions, flags). Larger lists (features ~1000,
charsets ~200) only scanned in non-hot-path code. Elisp delete-dups
already has hash optimization for >100 elements.
2026-03-30 11:45:36 -04:00

91 lines
3.1 KiB
Java

import java.util.*;
/**
* CWE-407 simulation tests for Neovim defects.
*
* neovim-0001: ins_compl_add() O(N^2) duplicate completion check
* (inherited from Vim — same defect pattern as vim-0001)
*/
public class NeovimTest {
// ========================================================================
// neovim-0001: ins_compl_add duplicate check — linked-list scan vs hash set
// ========================================================================
/**
* DEFECTIVE: O(N^2) — each insertion scans the full list for duplicates.
* Mirrors Neovim's do { strncmp } while loop in insexpand.c line 943-958.
*/
static int complAddDefective(String[] candidates) {
List<String> matches = new ArrayList<>();
int ops = 0;
for (String candidate : candidates) {
// Linear scan for duplicate
boolean found = false;
for (String existing : matches) {
ops++;
if (existing.equals(candidate)) {
found = true;
break;
}
}
if (!found) {
matches.add(candidate);
}
}
return ops;
}
/**
* PATCHED: O(N) — hash set for O(1) amortised duplicate detection.
* Uses Neovim's map infrastructure (map_defs.h) for O(1) lookup.
*/
static int complAddPatched(String[] candidates) {
Set<String> seen = new HashSet<>();
List<String> matches = new ArrayList<>();
int ops = 0;
for (String candidate : candidates) {
ops++; // hash lookup
if (seen.add(candidate)) {
matches.add(candidate);
}
}
return ops;
}
static void testNeovim0001() {
System.out.println("=== neovim-0001: ins_compl_add duplicate check ===");
int N = 1000;
// All unique candidates — worst case for duplicate scan
String[] candidates = new String[N];
for (int i = 0; i < N; i++) {
candidates[i] = "nvim_completion_" + i;
}
int opsDefective = complAddDefective(candidates);
int opsPatched = complAddPatched(candidates);
double ratio = (double) opsDefective / opsPatched;
System.out.printf(" N=%d candidates (all unique)%n", N);
System.out.printf(" Defective ops: %,d%n", opsDefective);
System.out.printf(" Patched ops: %,d%n", opsPatched);
System.out.printf(" Ratio: %.1fx%n", ratio);
// Defective: sum(0..N-1) = N*(N-1)/2 = 499,500
// Patched: N = 1,000
assert opsDefective >= N * (N - 1) / 2 : "Defective should be O(N^2)";
assert opsPatched == N : "Patched should be O(N)";
assert ratio > 100 : "Ratio should exceed 100x, got " + ratio;
System.out.println(" PASS");
}
// ========================================================================
// Main
// ========================================================================
public static void main(String[] args) {
testNeovim0001();
System.out.println("\nAll Neovim tests PASSED.");
}
}