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:
russell@unturf.com 2026-03-26 17:11:57 -04:00
commit 0a580b313d
70422 changed files with 17213626 additions and 0 deletions

View file

@ -0,0 +1,224 @@
package support;
import java.util.*;
/**
* PostgresqlExprMembershipAlgorithm — models equivclass.c site postgresql-0003.
*
* DEFECT (CWE-407): list_member() is called inside a nested loop to check
* whether each Var pulled from an equivalence-class member expression is
* present in a pre-built list (exprvars). The outer list (exprvars) is fixed
* for the duration of the scan, but rebuilt from scratch via list_member()
* on every inner-loop iteration — O(|exprvars|) per emvar, O(|exprvars| ×
* sum(|emvars|)) total.
*
* Site in PostgreSQL source:
* equivclass.c:1041 — find_em_expr_for_rel(), inner membership check
*
* Defective C pattern:
*
* exprvars = pull_var_clause(some_expr, ...); // fixed for this call
* foreach(lc, ec->ec_members) {
* EquivalenceMember *em = ...;
* emvars = pull_var_clause(em->em_expr, ...); // varies per member
* foreach(lc2, emvars) {
* if (!list_member(exprvars, lfirst(lc2))) // O(|exprvars|) — DEFECT
* break;
* }
* }
*
* Fix: Convert exprvars to a HashSet<Expr> once before the outer loop.
* Each list_member() call becomes O(1). Total cost drops from
* O(|exprvars| × sum(|emvars|)) to O(|exprvars| + sum(|emvars|)).
*
* C equivalent: If emvars are pure Var nodes (common case), use a
* Bitmapset keyed on (varno * 3200 + varattno + 1600) — no nodeHash()
* needed. For non-Var nodes, fall back to list_member().
*
* Comparison counts (M ec_members, each with K emvars, exprvars size E):
* defective: M × K × E (K checks per member, each scanning E exprvars)
* fixed: E + M × K (E to build HashSet, then 1 per emvar check)
*
* Growth when E doubles: defective scales linearly with E, fixed does not.
*/
public class PostgresqlExprMembershipAlgorithm {
// ── Expr: models a PostgreSQL expression node ─────────────────────────────
//
// In real PostgreSQL, expressions are tree nodes compared via equal().
// We model them as integer IDs for clarity; equals()/hashCode() are
// based on the ID, analogous to structural equal() on two Var nodes
// with the same (varno, varattno, varlevelsup).
public static final class Expr {
public final int id; // unique expression identity (encodes Var fields)
public Expr(int id) { this.id = id; }
/** Structural equality — models PostgreSQL equal() for Var nodes. */
@Override
public boolean equals(Object o) {
return o instanceof Expr e && id == e.id;
}
@Override
public int hashCode() { return Integer.hashCode(id); }
@Override
public String toString() { return "Expr(" + id + ")"; }
}
// ── EquivalenceMember: models EquivalenceMember with em_expr ─────────────
public static final class EquivalenceMember {
public final Expr emExpr;
public final List<Expr> emVars; // pull_var_clause(em_expr) result
public EquivalenceMember(Expr emExpr, List<Expr> emVars) {
this.emExpr = emExpr;
this.emVars = emVars;
}
}
// ── Result ────────────────────────────────────────────────────────────────
public static final class Result {
/** The first EquivalenceMember whose emvars are all present in exprvars. */
public final EquivalenceMember found;
/** Total element-level equality checks performed. */
public final long comparisons;
public Result(EquivalenceMember found, long comparisons) {
this.found = found;
this.comparisons = comparisons;
}
}
// ── Defective: list_member scan — O(|exprvars|) per emvar ────────────────
public static Result defectiveFindEm(
List<Expr> exprvars,
List<EquivalenceMember> ecMembers) {
long comparisons = 0;
for (EquivalenceMember em : ecMembers) {
boolean allPresent = true;
for (Expr emvar : em.emVars) {
// list_member: scan exprvars calling equal() on each element
boolean found = false;
for (Expr ev : exprvars) {
comparisons++;
if (ev.equals(emvar)) {
found = true;
break;
}
}
if (!found) {
allPresent = false;
break;
}
}
if (allPresent)
return new Result(em, comparisons);
}
return new Result(null, comparisons);
}
// ── Fixed: HashSet<Expr> from exprvars — O(1) per emvar ─────────────────
//
// Build a HashSet from exprvars once before the outer loop.
// C equivalent: Bitmapset for Var nodes; fall back to list_member for
// non-Var nodes (PlaceHolderVar, Aggref, etc.).
public static Result fixedFindEm(
List<Expr> exprvars,
List<EquivalenceMember> ecMembers) {
// Build HashSet once — O(|exprvars|)
Set<Expr> exprSet = new HashSet<>(exprvars);
long comparisons = exprvars.size(); // cost of building the set
for (EquivalenceMember em : ecMembers) {
boolean allPresent = true;
for (Expr emvar : em.emVars) {
comparisons++; // O(1) hash lookup
if (!exprSet.contains(emvar)) {
allPresent = false;
break;
}
}
if (allPresent)
return new Result(em, comparisons);
}
return new Result(null, comparisons);
}
// ── Self-test ─────────────────────────────────────────────────────────────
public static void main(String[] args) {
System.out.println("PostgresqlExprMembershipAlgorithm — postgresql-0003 (equivclass.c:1041)");
System.out.println("Defect: list_member O(n) scan inside nested EC member loop");
System.out.println("Fix: HashSet<Expr> built once from exprvars — O(1) per check");
System.out.println();
int[] exprvarSizes = {10, 50, 100, 500, 1000};
int emMembers = 20, emVarsPerMember = 5;
System.out.printf("%-12s %-16s %-12s %s%n",
"|exprvars|", "Defective ops", "Fixed ops", "Speedup");
System.out.println("─".repeat(56));
Random rng = new Random(42);
for (int exprSize : exprvarSizes) {
List<Expr> exprvars = buildExprList(exprSize, 0);
List<EquivalenceMember> members = buildEcMembers(
emMembers, emVarsPerMember, exprSize, rng);
Result def = defectiveFindEm(exprvars, members);
Result fix = fixedFindEm(exprvars, members);
assert Objects.equals(
def.found != null ? def.found.emExpr : null,
fix.found != null ? fix.found.emExpr : null)
: "result mismatch at |exprvars|=" + exprSize;
System.out.printf("%-12d %-16d %-12d %.1fx%n",
exprSize,
def.comparisons,
fix.comparisons,
(double) def.comparisons / Math.max(1, fix.comparisons));
}
System.out.println();
System.out.println("Defective: O(|exprvars| × M × K) — scales with exprvars size.");
System.out.println("Fixed: O(|exprvars| + M × K) — exprvars built once.");
}
public static List<Expr> buildExprList(int size, int offset) {
List<Expr> list = new ArrayList<>(size);
for (int i = 0; i < size; i++) list.add(new Expr(offset + i));
return list;
}
public static List<EquivalenceMember> buildEcMembers(
int count, int emVarsEach, int exprSize, Random rng) {
List<EquivalenceMember> members = new ArrayList<>();
for (int i = 0; i < count; i++) {
List<Expr> emVars = new ArrayList<>();
for (int j = 0; j < emVarsEach; j++) {
// Half the time pick from exprvars (found), half outside (not found)
int id = rng.nextBoolean() ? rng.nextInt(exprSize) : exprSize + rng.nextInt(10);
emVars.add(new Expr(id));
}
members.add(new EquivalenceMember(new Expr(exprSize + 100 + i), emVars));
}
return members;
}
}