java-topology/defects/swift/unit/SwiftTest.java
russell@unturf.com b37db35655 rustc/swift: CWE-407 scan — rustc CLEAN, swift 1 defect
rustc: Exemplary use of FxHashSet/BitSet/IntervalSet throughout;
no linear membership tests on hot paths.

swift-0001: LoadableByAddress.cpp StructLoweringState uses SmallVector
with std::find for largeLoadableArgs/applies membership — O(I×A)
per function, 322x overhead at A=500. Fix: SmallPtrSet shadow.
2026-03-30 10:26:11 -04:00

143 lines
5.6 KiB
Java

import java.util.*;
/**
* CWE-407 simulation: Swift LoadableByAddress pass linear membership tests.
*
* The StructLoweringState in LoadableByAddress.cpp uses SmallVector with
* std::find for membership tests on largeLoadableArgs, applies, and other
* instruction vectors. For each instruction in the function, std::find
* performs O(A) linear scan where A = number of large loadable args.
*
* Defect: O(I x A) where I = instructions, A = large loadable args
* Fix: SmallPtrSet shadow for O(1) membership tests -> O(I + A)
*
* swift-0001: LoadableByAddress largeLoadableArgs/applies linear membership
*/
public class SwiftTest {
// --- Defective: SmallVector + std::find pattern ---
static long visitApplyDefective(List<Object> largeLoadableArgs,
List<Object> funcSigArgs,
List<Object> applies,
List<Object[]> applyOperands) {
long ops = 0;
for (Object[] operands : applyOperands) {
for (Object operand : operands) {
ops++;
// std::find(largeLoadableArgs.begin(), ..., currOperand)
boolean found = false;
for (Object arg : largeLoadableArgs) {
ops++;
if (arg == operand) { found = true; break; }
}
if (!found) {
// std::find(funcSigArgs.begin(), ..., currOperand)
for (Object arg : funcSigArgs) {
ops++;
if (arg == operand) { found = true; break; }
}
}
if (found) {
// Dedup check: std::find(applies.begin(), ..., instr)
Object instr = operands; // proxy for instruction
for (Object a : applies) {
ops++;
if (a == instr) { found = false; break; }
}
if (found) applies.add(instr);
}
}
}
return ops;
}
// --- Fixed: SmallPtrSet shadow for O(1) lookup ---
static long visitApplyFixed(Set<Object> largeLoadableArgsSet,
Set<Object> funcSigArgsSet,
Set<Object> appliesSet,
List<Object[]> applyOperands) {
long ops = 0;
for (Object[] operands : applyOperands) {
for (Object operand : operands) {
ops++;
boolean found = largeLoadableArgsSet.contains(operand);
ops++;
if (!found) {
found = funcSigArgsSet.contains(operand);
ops++;
}
if (found) {
Object instr = operands;
if (appliesSet.add(instr)) {
ops++;
}
}
}
}
return ops;
}
public static void main(String[] args) {
// Simulate a function with A large loadable args and I apply instructions
int[] sizes = {10, 50, 100, 200, 500};
System.out.println("swift-0001: LoadableByAddress largeLoadableArgs linear membership");
System.out.println("=================================================================");
System.out.printf("%-8s %-14s %-14s %-10s %-6s%n",
"A(args)", "Defective ops", "Fixed ops", "Ratio", "Status");
boolean allPass = true;
for (int A : sizes) {
// Create A large loadable args
List<Object> largeLoadableArgs = new ArrayList<>();
Set<Object> largeLoadableArgsSet = new HashSet<>();
List<Object> funcSigArgs = new ArrayList<>();
Set<Object> funcSigArgsSet = new HashSet<>();
List<Object> applies = new ArrayList<>();
Set<Object> appliesSet = new HashSet<>();
Object[] argPool = new Object[A];
for (int i = 0; i < A; i++) {
argPool[i] = new Object();
largeLoadableArgs.add(argPool[i]);
largeLoadableArgsSet.add(argPool[i]);
funcSigArgs.add(argPool[i]);
funcSigArgsSet.add(argPool[i]);
}
// Create I apply instructions, each with 3 operands from the arg pool
int I = A * 2; // instructions proportional to args
List<Object[]> applyOperands = new ArrayList<>();
Random rng = new Random(42);
for (int i = 0; i < I; i++) {
Object[] ops = new Object[3];
for (int j = 0; j < 3; j++) {
ops[j] = argPool[rng.nextInt(A)];
}
applyOperands.add(ops);
}
long defectOps = visitApplyDefective(
new ArrayList<>(largeLoadableArgs),
new ArrayList<>(funcSigArgs),
new ArrayList<>(applies),
applyOperands);
long fixedOps = visitApplyFixed(
new HashSet<>(largeLoadableArgsSet),
new HashSet<>(funcSigArgsSet),
new HashSet<>(appliesSet),
applyOperands);
double ratio = (double) defectOps / fixedOps;
boolean pass = ratio > 2.0;
allPass &= pass;
System.out.printf("%-8d %-14d %-14d %-10.1f %-6s%n",
A, defectOps, fixedOps, ratio, pass ? "PASS" : "FAIL");
}
System.out.println();
System.out.println(allPass ? "ALL PASS" : "SOME FAIL");
System.exit(allPass ? 0 : 1);
}
}