firefox: 2 CWE-407 defects — Sanitizer ListSet O(N×E) HIGH, DOMTokenList O(T²) MEDIUM; chromium SKIPPED (clone unavailable)
This commit is contained in:
parent
558f0d30c2
commit
026859bc00
5 changed files with 395 additions and 0 deletions
130
defects/firefox/test/Firefox0002DOMTokenListTest.java
Normal file
130
defects/firefox/test/Firefox0002DOMTokenListTest.java
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
/**
|
||||
* CWE-407 simulation: Firefox nsDOMTokenList O(T²) classList add/remove.
|
||||
*
|
||||
* Simulates AddInternal() and RemoveInternal() from dom/base/nsDOMTokenList.cpp.
|
||||
* The defective version uses ArrayList.contains() for dedup (O(T²)),
|
||||
* the fixed version uses HashSet (O(T)).
|
||||
*/
|
||||
import java.util.*;
|
||||
|
||||
public class Firefox0002DOMTokenListTest {
|
||||
|
||||
// --- Defective AddInternal: addedClasses is ArrayList ---
|
||||
static int addInternalDefective(List<String> existingClasses, List<String> tokens) {
|
||||
List<String> addedClasses = new ArrayList<>();
|
||||
int ops = 0;
|
||||
for (String token : tokens) {
|
||||
// Check if already in existing classes (linear)
|
||||
ops++;
|
||||
if (existingClasses.contains(token)) continue;
|
||||
// Check if already added (linear in addedClasses)
|
||||
ops++;
|
||||
if (addedClasses.contains(token)) continue;
|
||||
addedClasses.add(token);
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
// --- Fixed AddInternal: addedClasses is HashSet ---
|
||||
static int addInternalFixed(List<String> existingClasses, List<String> tokens) {
|
||||
Set<String> existingSet = new HashSet<>(existingClasses);
|
||||
Set<String> addedClasses = new HashSet<>();
|
||||
int ops = 0;
|
||||
for (String token : tokens) {
|
||||
ops++;
|
||||
if (existingSet.contains(token)) continue;
|
||||
ops++;
|
||||
if (addedClasses.contains(token)) continue;
|
||||
addedClasses.add(token);
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
// --- Defective RemoveInternal: aTokens.Contains() linear ---
|
||||
static int removeInternalDefective(List<String> existingAtoms, List<String> tokens) {
|
||||
int ops = 0;
|
||||
for (String atom : existingAtoms) {
|
||||
ops++;
|
||||
if (tokens.contains(atom)) continue; // O(T) per atom
|
||||
// would append to result
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
// --- Fixed RemoveInternal: tokenSet is HashSet ---
|
||||
static int removeInternalFixed(List<String> existingAtoms, List<String> tokens) {
|
||||
Set<String> tokenSet = new HashSet<>(tokens);
|
||||
int ops = 0;
|
||||
for (String atom : existingAtoms) {
|
||||
ops++;
|
||||
if (tokenSet.contains(atom)) continue; // O(1)
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("=== Firefox-0002: nsDOMTokenList O(T²) classList add/remove ===\n");
|
||||
|
||||
int[] tokenCounts = {50, 200, 500, 1000};
|
||||
int pass = 0, fail = 0;
|
||||
|
||||
// Test AddInternal
|
||||
System.out.println("--- AddInternal ---");
|
||||
for (int T : tokenCounts) {
|
||||
List<String> existing = new ArrayList<>();
|
||||
for (int i = 0; i < 20; i++) existing.add("existing-" + i);
|
||||
|
||||
List<String> tokens = new ArrayList<>();
|
||||
for (int i = 0; i < T; i++) tokens.add("new-token-" + i);
|
||||
|
||||
// Warmup
|
||||
addInternalDefective(existing, tokens);
|
||||
addInternalFixed(existing, tokens);
|
||||
|
||||
long t0 = System.nanoTime();
|
||||
for (int r = 0; r < 200; r++) addInternalDefective(existing, tokens);
|
||||
long defectiveNs = System.nanoTime() - t0;
|
||||
|
||||
t0 = System.nanoTime();
|
||||
for (int r = 0; r < 200; r++) addInternalFixed(existing, tokens);
|
||||
long fixedNs = System.nanoTime() - t0;
|
||||
|
||||
double ratio = (double) defectiveNs / fixedNs;
|
||||
boolean ok = ratio > 1.5;
|
||||
System.out.printf("T=%4d | defective=%8.3fms fixed=%8.3fms ratio=%.1fx %s%n",
|
||||
T, defectiveNs / 1e6, fixedNs / 1e6, ratio, ok ? "PASS" : "FAIL");
|
||||
if (ok) pass++; else fail++;
|
||||
}
|
||||
|
||||
// Test RemoveInternal
|
||||
System.out.println("\n--- RemoveInternal ---");
|
||||
for (int T : tokenCounts) {
|
||||
List<String> atoms = new ArrayList<>();
|
||||
for (int i = 0; i < T; i++) atoms.add("class-" + i);
|
||||
|
||||
List<String> tokensToRemove = new ArrayList<>();
|
||||
for (int i = 0; i < T / 2; i++) tokensToRemove.add("class-" + (i * 2));
|
||||
|
||||
// Warmup
|
||||
removeInternalDefective(atoms, tokensToRemove);
|
||||
removeInternalFixed(atoms, tokensToRemove);
|
||||
|
||||
long t0 = System.nanoTime();
|
||||
for (int r = 0; r < 200; r++) removeInternalDefective(atoms, tokensToRemove);
|
||||
long defectiveNs = System.nanoTime() - t0;
|
||||
|
||||
t0 = System.nanoTime();
|
||||
for (int r = 0; r < 200; r++) removeInternalFixed(atoms, tokensToRemove);
|
||||
long fixedNs = System.nanoTime() - t0;
|
||||
|
||||
double ratio = (double) defectiveNs / fixedNs;
|
||||
boolean ok = ratio > 1.5;
|
||||
System.out.printf("T=%4d | defective=%8.3fms fixed=%8.3fms ratio=%.1fx %s%n",
|
||||
T, defectiveNs / 1e6, fixedNs / 1e6, ratio, ok ? "PASS" : "FAIL");
|
||||
if (ok) pass++; else fail++;
|
||||
}
|
||||
|
||||
System.out.printf("%nResults: %d PASS, %d FAIL%n", pass, fail);
|
||||
if (fail > 0) System.exit(1);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue