undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
180
tests/unit/ClosureComplexityTest.java
Normal file
180
tests/unit/ClosureComplexityTest.java
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
package unit;
|
||||
|
||||
import support.ClosureAlgorithm;
|
||||
import support.ClosureAlgorithm.Result;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Unit tests for DEFECT 0002b: InferenceGraph.Node.closure() uncached DFS.
|
||||
*
|
||||
* Proves:
|
||||
* 1. Both implementations produce identical closure sets (correctness).
|
||||
* 2. Defective version visits exactly K*V nodes for K calls on a V-node chain.
|
||||
* 3. Fixed version visits exactly V+(K-1) nodes for the same K calls.
|
||||
* 4. Doubling K doubles defective work; fixed is nearly constant.
|
||||
*
|
||||
* No build tool required. Compile and run:
|
||||
*
|
||||
* cd tests
|
||||
* java -m jdk.compiler/com.sun.tools.javac.Main -cp . \
|
||||
* support/ClosureAlgorithm.java unit/ClosureComplexityTest.java
|
||||
* java -cp . unit.ClosureComplexityTest
|
||||
*/
|
||||
public class ClosureComplexityTest {
|
||||
|
||||
private static int passed = 0;
|
||||
private static int failed = 0;
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("=== ClosureComplexityTest (DEFECT 0002b) ===\n");
|
||||
|
||||
System.out.println("-- Correctness: both versions return same closure set --");
|
||||
testCorrectnessSmall();
|
||||
testCorrectnessMedium();
|
||||
|
||||
System.out.println("\n-- Complexity: defective visits K*V nodes --");
|
||||
testDefectiveExactCounts();
|
||||
|
||||
System.out.println("\n-- Complexity: fixed visits V+(K-1) nodes --");
|
||||
testFixedExactCounts();
|
||||
|
||||
System.out.println("\n-- Complexity: growth ratio proves linear vs constant in K --");
|
||||
testGrowthRatioInK();
|
||||
|
||||
System.out.printf("\n%d passed, %d failed%n", passed, failed);
|
||||
if (failed > 0) System.exit(1);
|
||||
}
|
||||
|
||||
// ─── Correctness ─────────────────────────────────────────────────────────
|
||||
|
||||
static void testCorrectnessSmall() {
|
||||
int v = 5, k = 3;
|
||||
ClosureAlgorithm.Node startDef = ClosureAlgorithm.buildLinearChain(v);
|
||||
ClosureAlgorithm.Node startFix = ClosureAlgorithm.buildLinearChain(v);
|
||||
|
||||
Result def = ClosureAlgorithm.closureDefective(startDef, k);
|
||||
Result fix = ClosureAlgorithm.closureFixed(startFix, k);
|
||||
|
||||
assertEqual("small: defective closure size", v, def.closure.size());
|
||||
assertEqual("small: fixed closure size", v, fix.closure.size());
|
||||
}
|
||||
|
||||
static void testCorrectnessMedium() {
|
||||
int v = 20, k = 5;
|
||||
ClosureAlgorithm.Node startDef = ClosureAlgorithm.buildLinearChain(v);
|
||||
ClosureAlgorithm.Node startFix = ClosureAlgorithm.buildLinearChain(v);
|
||||
|
||||
Result def = ClosureAlgorithm.closureDefective(startDef, k);
|
||||
Result fix = ClosureAlgorithm.closureFixed(startFix, k);
|
||||
|
||||
assertEqual("medium: defective closure size", v, def.closure.size());
|
||||
assertEqual("medium: fixed closure size", v, fix.closure.size());
|
||||
}
|
||||
|
||||
// ─── Exact node-visit counts ──────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* PROVES DEFECT: K calls on a V-node chain visit exactly K*V nodes total.
|
||||
* Each call reruns the full DFS with no memory of previous calls.
|
||||
*/
|
||||
static void testDefectiveExactCounts() {
|
||||
System.out.println("[defective] closureDefective(chain(V), K) — expected K*V:");
|
||||
int[][] cases = {{10, 5}, {20, 5}, {10, 10}, {20, 10}, {50, 20}};
|
||||
for (int[] c : cases) {
|
||||
int v = c[0], k = c[1];
|
||||
ClosureAlgorithm.Node start = ClosureAlgorithm.buildLinearChain(v);
|
||||
Result r = ClosureAlgorithm.closureDefective(start, k);
|
||||
long expected = (long) k * v;
|
||||
System.out.printf(" V=%-4d K=%-4d actual=%-8d expected=%-8d %s%n",
|
||||
v, k, r.nodeVisits, expected,
|
||||
r.nodeVisits == expected ? "PASS" : "FAIL expected=" + expected);
|
||||
assertEqual("defective V=" + v + " K=" + k, expected, r.nodeVisits);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PROVES FIX: K calls on a V-node chain visit exactly V+(K-1) nodes total.
|
||||
* First call runs the DFS (V visits), each of the K-1 subsequent calls
|
||||
* finds the cached result (1 visit each).
|
||||
*/
|
||||
static void testFixedExactCounts() {
|
||||
System.out.println("[fixed] closureFixed(chain(V), K) — expected V+(K-1):");
|
||||
int[][] cases = {{10, 5}, {20, 5}, {10, 10}, {20, 10}, {50, 20}};
|
||||
for (int[] c : cases) {
|
||||
int v = c[0], k = c[1];
|
||||
ClosureAlgorithm.Node start = ClosureAlgorithm.buildLinearChain(v);
|
||||
Result r = ClosureAlgorithm.closureFixed(start, k);
|
||||
long expected = v + (k - 1);
|
||||
System.out.printf(" V=%-4d K=%-4d actual=%-8d expected=%-8d %s%n",
|
||||
v, k, r.nodeVisits, expected,
|
||||
r.nodeVisits == expected ? "PASS" : "FAIL expected=" + expected);
|
||||
assertEqual("fixed V=" + v + " K=" + k, expected, r.nodeVisits);
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Growth ratio (in K dimension) ────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* PROVES LINEAR GROWTH OF DEFECT IN K:
|
||||
* Doubling K → defective visits double (≈2x), fixed barely changes.
|
||||
*
|
||||
* Math (V=100 fixed):
|
||||
* defective(K) = K*V → doubles when K doubles
|
||||
* defective(2K) = 2K*V → ratio = 2.0 (exact)
|
||||
*
|
||||
* fixed(K) = V + (K-1)
|
||||
* fixed(2K) = V + (2K-1)
|
||||
* ratio = (V+2K-1)/(V+K-1) → 1 as V≫K (nearly constant)
|
||||
*/
|
||||
static void testGrowthRatioInK() {
|
||||
int v = 100;
|
||||
int[][] kPairs = {{5, 10}, {10, 20}, {20, 40}};
|
||||
for (int[] pair : kPairs) {
|
||||
int k1 = pair[0], k2 = pair[1];
|
||||
|
||||
ClosureAlgorithm.Node startDef1 = ClosureAlgorithm.buildLinearChain(v);
|
||||
ClosureAlgorithm.Node startDef2 = ClosureAlgorithm.buildLinearChain(v);
|
||||
ClosureAlgorithm.Node startFix1 = ClosureAlgorithm.buildLinearChain(v);
|
||||
ClosureAlgorithm.Node startFix2 = ClosureAlgorithm.buildLinearChain(v);
|
||||
|
||||
long def1 = ClosureAlgorithm.closureDefective(startDef1, k1).nodeVisits;
|
||||
long def2 = ClosureAlgorithm.closureDefective(startDef2, k2).nodeVisits;
|
||||
long fix1 = ClosureAlgorithm.closureFixed(startFix1, k1).nodeVisits;
|
||||
long fix2 = ClosureAlgorithm.closureFixed(startFix2, k2).nodeVisits;
|
||||
|
||||
double defRatio = (double) def2 / def1;
|
||||
double fixRatio = (double) fix2 / fix1;
|
||||
|
||||
System.out.printf(" V=%d K %d→%d: defective ratio=%.2f (expect 2.0) fixed ratio=%.2f (expect <1.2)%n",
|
||||
v, k1, k2, defRatio, fixRatio);
|
||||
|
||||
// Defective doubles exactly when K doubles (defective = K*V)
|
||||
assertTrue("defective K=" + k1 + "→" + k2 + " ratio = 2.0", defRatio == 2.0);
|
||||
// Fixed changes very little (V dominates K for V=100)
|
||||
assertTrue("fixed K=" + k1 + "→" + k2 + " ratio < 1.2", fixRatio < 1.2);
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Helpers ─────────────────────────────────────────────────────────────
|
||||
|
||||
static void assertEqual(String name, long expected, long actual) {
|
||||
if (expected == actual) {
|
||||
System.out.printf(" PASS %s%n", name);
|
||||
passed++;
|
||||
} else {
|
||||
System.out.printf(" FAIL %s expected=%d actual=%d%n", name, expected, actual);
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
|
||||
static void assertTrue(String name, boolean condition) {
|
||||
if (condition) {
|
||||
System.out.printf(" PASS %s%n", name);
|
||||
passed++;
|
||||
} else {
|
||||
System.out.printf(" FAIL %s%n", name);
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue