java-topology/defects/vscode/unit/VscodeTest.java
russell@unturf.com 05e4902a9e vscode+zed: CWE-407 scan — 6 defects across 2 code editors
VS Code (4 defects):
- vscode-0001: extensionGalleryService uuid dedup O(N×M) MEDIUM 100x
- vscode-0002: abstractExtensionManagementService deps O(D²) MEDIUM 49x
- vscode-0003: userDataSync merge compare() O(N×M) across 8 files MEDIUM 250x
- vscode-0004: configurationModels override identifiers O(N×M) LOW-MEDIUM 18x

Zed (2 defects):
- zed-0001: lsp_store LSP edit dedup Vec::contains O(E²) MEDIUM 49x
- zed-0002: extension_builder manifest dedup Vec::contains O(N²) LOW 24x

6/6 unit tests PASS
2026-03-30 11:43:31 -04:00

226 lines
8.8 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import java.util.*;
/**
* CWE-407 unit tests for VS Code defects.
*
* vscode-0001: extensionGalleryService getExtensions uuid dedup O(N×M)
* vscode-0002: abstractExtensionManagementService getAllDepsAndPacks O(D²)
* vscode-0003: userDataSync merge compare() O(N×M) array includes (8 sites)
* vscode-0004: configurationModels override identifiers O(N×M)
*/
public class VscodeTest {
// ---------------------------------------------------------------
// vscode-0001: gallery uuid includes O(N×M)
// ---------------------------------------------------------------
/** BEFORE: uuids array with Array.includes() — O(N×M) */
static int galleryUuidBefore(List<String> extensionUuids, List<String> resultUuids) {
int ops = 0;
// const uuids = result.map(r => r.identifier.uuid); // array
for (String uuid : extensionUuids) {
// uuids.includes(e.uuid)
for (String r : resultUuids) {
ops++;
if (r.equals(uuid)) break;
}
}
return ops;
}
/** AFTER: uuids Set with Set.has() — O(N+M) */
static int galleryUuidAfter(List<String> extensionUuids, List<String> resultUuids) {
int ops = 0;
Set<String> uuidSet = new HashSet<>(resultUuids);
ops += resultUuids.size(); // set construction
for (String uuid : extensionUuids) {
ops++; // set lookup O(1)
uuidSet.contains(uuid);
}
return ops;
}
// ---------------------------------------------------------------
// vscode-0002: getAllDepsAndPacks includes O(D²)
// ---------------------------------------------------------------
/** BEFORE: allDepsOrPacks.includes() in recursive traversal — O(D²) */
static int depsScanBefore(List<String> depChain) {
int ops = 0;
List<String> allDeps = new ArrayList<>();
for (String id : depChain) {
// allDepsOrPacks.includes(id.toLowerCase())
boolean found = false;
for (String existing : allDeps) {
ops++;
if (existing.equals(id)) { found = true; break; }
}
if (!found) allDeps.add(id);
}
return ops;
}
/** AFTER: Set for seen-check — O(D) */
static int depsScanAfter(List<String> depChain) {
int ops = 0;
Set<String> seen = new HashSet<>();
List<String> allDeps = new ArrayList<>();
for (String id : depChain) {
ops++; // set lookup
if (!seen.contains(id)) {
seen.add(id);
allDeps.add(id);
}
}
return ops;
}
// ---------------------------------------------------------------
// vscode-0003: sync merge compare() — filter+includes O(N×M)
// ---------------------------------------------------------------
/** BEFORE: fromKeys.filter(key => !toKeys.includes(key)) — O(N×M) */
static int mergeCompareBefore(List<String> fromKeys, List<String> toKeys) {
int ops = 0;
// added = toKeys.filter(key => !fromKeys.includes(key))
for (String key : toKeys) {
for (String fk : fromKeys) {
ops++;
if (fk.equals(key)) break;
}
}
// removed = fromKeys.filter(key => !toKeys.includes(key))
for (String key : fromKeys) {
for (String tk : toKeys) {
ops++;
if (tk.equals(key)) break;
}
}
return ops;
}
/** AFTER: Set lookup — O(N+M) */
static int mergeCompareAfter(List<String> fromKeys, List<String> toKeys) {
int ops = 0;
Set<String> fromSet = new HashSet<>(fromKeys);
ops += fromKeys.size();
Set<String> toSet = new HashSet<>(toKeys);
ops += toKeys.size();
for (String key : toKeys) { ops++; fromSet.contains(key); }
for (String key : fromKeys) { ops++; toSet.contains(key); }
return ops;
}
// ---------------------------------------------------------------
// vscode-0004: config override identifiers — filter+includes O(N×M)
// ---------------------------------------------------------------
/** BEFORE: overrideIdentifiers.filter + includes — O(N²) */
static int configOverrideBefore(List<String> fromIds, List<String> toIds) {
int ops = 0;
// addedOverrideIdentifiers = toIds.filter(key => !fromIds.includes(key))
for (String key : toIds) {
for (String fk : fromIds) { ops++; if (fk.equals(key)) break; }
}
// removedOverrideIdentifiers = fromIds.filter(key => !toIds.includes(key))
for (String key : fromIds) {
for (String tk : toIds) { ops++; if (tk.equals(key)) break; }
}
// inner loop: toOverrideIdentifiers.includes(identifier)
for (String id : fromIds) {
for (String tk : toIds) { ops++; if (tk.equals(id)) break; }
}
return ops;
}
/** AFTER: Set lookups — O(N+M) */
static int configOverrideAfter(List<String> fromIds, List<String> toIds) {
int ops = 0;
Set<String> fromSet = new HashSet<>(fromIds);
ops += fromIds.size();
Set<String> toSet = new HashSet<>(toIds);
ops += toIds.size();
for (String key : toIds) { ops++; fromSet.contains(key); }
for (String key : fromIds) { ops++; toSet.contains(key); }
for (String id : fromIds) { ops++; toSet.contains(id); }
return ops;
}
// ---------------------------------------------------------------
// Main: run all tests
// ---------------------------------------------------------------
public static void main(String[] args) {
int pass = 0, fail = 0;
// --- vscode-0001: gallery uuid ---
{
int N = 200;
List<String> extUuids = new ArrayList<>();
List<String> resultUuids = new ArrayList<>();
for (int i = 0; i < N; i++) {
extUuids.add("ext-" + i);
resultUuids.add("res-" + i); // disjoint = worst case
}
int before = galleryUuidBefore(extUuids, resultUuids);
int after = galleryUuidAfter(extUuids, resultUuids);
double ratio = (double) before / after;
boolean ok = ratio > 10;
System.out.printf("vscode-0001 gallery-uuid N=%d before=%d after=%d ratio=%.1fx %s%n",
N, before, after, ratio, ok ? "PASS" : "FAIL");
if (ok) pass++; else fail++;
}
// --- vscode-0002: deps scan ---
{
int D = 100;
List<String> deps = new ArrayList<>();
for (int i = 0; i < D; i++) deps.add("dep-" + i);
int before = depsScanBefore(deps);
int after = depsScanAfter(deps);
double ratio = (double) before / after;
boolean ok = ratio > 10;
System.out.printf("vscode-0002 deps-scan D=%d before=%d after=%d ratio=%.1fx %s%n",
D, before, after, ratio, ok ? "PASS" : "FAIL");
if (ok) pass++; else fail++;
}
// --- vscode-0003: sync merge compare ---
{
int N = 500;
List<String> fromKeys = new ArrayList<>();
List<String> toKeys = new ArrayList<>();
for (int i = 0; i < N; i++) {
fromKeys.add("setting-" + i);
toKeys.add("setting-" + (i + N)); // disjoint = worst case
}
int before = mergeCompareBefore(fromKeys, toKeys);
int after = mergeCompareAfter(fromKeys, toKeys);
double ratio = (double) before / after;
boolean ok = ratio > 50;
System.out.printf("vscode-0003 sync-merge-compare N=%d before=%d after=%d ratio=%.1fx %s%n",
N, before, after, ratio, ok ? "PASS" : "FAIL");
if (ok) pass++; else fail++;
}
// --- vscode-0004: config override identifiers ---
{
int N = 30;
List<String> fromIds = new ArrayList<>();
List<String> toIds = new ArrayList<>();
for (int i = 0; i < N; i++) {
fromIds.add("[lang-" + i + "]");
toIds.add("[lang-" + (i + N) + "]"); // disjoint
}
int before = configOverrideBefore(fromIds, toIds);
int after = configOverrideAfter(fromIds, toIds);
double ratio = (double) before / after;
boolean ok = ratio > 5;
System.out.printf("vscode-0004 config-overrides N=%d before=%d after=%d ratio=%.1fx %s%n",
N, before, after, ratio, ok ? "PASS" : "FAIL");
if (ok) pass++; else fail++;
}
System.out.printf("%n%d/%d PASS%n", pass, pass + fail);
if (fail > 0) System.exit(1);
}
}