wave17 complete: systemd/emacs/vim/qemu/tcl/kafka-0007/spark-0004 + 559/240
This commit is contained in:
parent
4221966e66
commit
cce7ec653a
32 changed files with 3007 additions and 5 deletions
134
defects/emacs/unit/BytecompCodeStringsAlgorithm.java
Normal file
134
defects/emacs/unit/BytecompCodeStringsAlgorithm.java
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
package unit;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* CWE-407 unit test: emacs-0002
|
||||
* Models bytecomp--code-strings member-based deduplication in Emacs byte-compiler.
|
||||
*
|
||||
* SLOW path: List<String> + .contains() — O(F²) over all lambdas in a file
|
||||
* FAST path: HashMap<String,String> — O(F) total
|
||||
*
|
||||
* The pattern in bytecomp.el:
|
||||
* (let* ((code (cadr compiled))
|
||||
* (prev (member code bytecomp--code-strings))) ; ← O(L), L grows
|
||||
* (if prev (car prev)
|
||||
* (push code bytecomp--code-strings) ; list grows
|
||||
* code))
|
||||
*
|
||||
* For F lambdas per file, work is: 0 + 1 + 2 + … + (F-1) = O(F²/2).
|
||||
*/
|
||||
public class BytecompCodeStringsAlgorithm {
|
||||
|
||||
// ---- SLOW path ---------------------------------------------------------
|
||||
|
||||
static long slowOps;
|
||||
|
||||
/**
|
||||
* Simulate compiling F lambdas with list-based dedup.
|
||||
* Each code string is unique (worst case for list growth).
|
||||
*/
|
||||
static void slowCompileFile(int F) {
|
||||
slowOps = 0;
|
||||
List<String> codeStrings = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < F; i++) {
|
||||
String code = "bytecode-" + i; // all unique — worst case
|
||||
|
||||
// (member code bytecomp--code-strings)
|
||||
boolean found = false;
|
||||
for (String existing : codeStrings) {
|
||||
slowOps++;
|
||||
if (existing.equals(code)) { found = true; break; }
|
||||
}
|
||||
if (!found) {
|
||||
codeStrings.add(code); // (push code bytecomp--code-strings)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---- FAST path ---------------------------------------------------------
|
||||
|
||||
static long fastOps;
|
||||
|
||||
/**
|
||||
* Same simulation using HashMap<String,String> for O(1) dedup.
|
||||
*/
|
||||
static void fastCompileFile(int F) {
|
||||
fastOps = 0;
|
||||
Map<String, String> codeStringsHt = new HashMap<>();
|
||||
|
||||
for (int i = 0; i < F; i++) {
|
||||
String code = "bytecode-" + i;
|
||||
|
||||
fastOps++; // one hash lookup
|
||||
codeStringsHt.putIfAbsent(code, code);
|
||||
}
|
||||
}
|
||||
|
||||
// ---- main --------------------------------------------------------------
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("=== emacs-0002: BytecompCodeStringsAlgorithm (member dedup) ===");
|
||||
|
||||
int[] sizes = {50, 100, 200, 500, 1000};
|
||||
|
||||
System.out.printf("%-12s %-15s %-15s %-10s%n",
|
||||
"F (fns)", "slow_ops", "fast_ops", "ratio");
|
||||
System.out.println("-".repeat(55));
|
||||
|
||||
for (int F : sizes) {
|
||||
slowCompileFile(F);
|
||||
long s = slowOps;
|
||||
fastCompileFile(F);
|
||||
long f = fastOps;
|
||||
double ratio = f == 0 ? 1.0 : (double) s / f;
|
||||
System.out.printf("%-12d %-15d %-15d %-10.1f%n", F, s, f, ratio);
|
||||
}
|
||||
|
||||
// Correctness: both paths should produce same deduplicated set
|
||||
{
|
||||
int F = 100;
|
||||
// collect slow results
|
||||
List<String> slowResult = new ArrayList<>();
|
||||
long dummy = 0;
|
||||
List<String> codeStrings = new ArrayList<>();
|
||||
for (int i = 0; i < F; i++) {
|
||||
String code = "bytecode-" + (i % 60); // introduce duplicates
|
||||
boolean found = false;
|
||||
for (String e : codeStrings) { dummy++; if (e.equals(code)) { found=true; break; } }
|
||||
if (!found) codeStrings.add(code);
|
||||
}
|
||||
slowResult.addAll(codeStrings);
|
||||
|
||||
Map<String,String> fastResult = new LinkedHashMap<>();
|
||||
for (int i = 0; i < F; i++) {
|
||||
String code = "bytecode-" + (i % 60);
|
||||
fastResult.putIfAbsent(code, code);
|
||||
}
|
||||
|
||||
Set<String> s = new HashSet<>(slowResult);
|
||||
Set<String> f2 = new HashSet<>(fastResult.keySet());
|
||||
if (!s.equals(f2)) {
|
||||
System.err.println("FAIL: dedup sets differ");
|
||||
System.exit(1);
|
||||
}
|
||||
System.out.println("\nCORRECTNESS: PASS");
|
||||
}
|
||||
|
||||
// Ratio assertion at F=500
|
||||
{
|
||||
slowCompileFile(500);
|
||||
long s = slowOps;
|
||||
fastCompileFile(500);
|
||||
long f = fastOps;
|
||||
double r = (double) s / f;
|
||||
System.out.printf("Ratio at F=500: %.1fx%n", r);
|
||||
if (r < 100.0) {
|
||||
System.err.println("FAIL: expected ratio >= 100x at F=500");
|
||||
System.exit(1);
|
||||
}
|
||||
System.out.println("RATIO ASSERTION: PASS");
|
||||
}
|
||||
}
|
||||
}
|
||||
147
defects/emacs/unit/FontsetInfoAlgorithm.java
Normal file
147
defects/emacs/unit/FontsetInfoAlgorithm.java
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
package unit;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* CWE-407 unit test: emacs-0001
|
||||
* Models Ffontset_info's Fmember-based font-name deduplication inside a loop.
|
||||
*
|
||||
* SLOW path: ArrayList.contains() — O(R × F × N), N grows during loop
|
||||
* FAST path: HashSet for dedup — O(R × F)
|
||||
*
|
||||
* Mimics the C pattern:
|
||||
* for i over realized fontsets R:
|
||||
* for j over font entries F:
|
||||
* slot = assq(spec, alist) // find slot by spec
|
||||
* if (!names.contains(name)) // ← O(N) Fmember
|
||||
* names.add(name) // N grows
|
||||
*/
|
||||
public class FontsetInfoAlgorithm {
|
||||
|
||||
// ---- data types --------------------------------------------------------
|
||||
|
||||
static class Slot {
|
||||
String spec;
|
||||
List<String> names = new ArrayList<>(); // SLOW: linear dedup
|
||||
Set<String> nameSet = new HashSet<>(); // FAST: O(1) dedup
|
||||
|
||||
Slot(String spec) { this.spec = spec; }
|
||||
}
|
||||
|
||||
// ---- SLOW: list membership for dedup -----------------------------------
|
||||
|
||||
static long slowOps;
|
||||
|
||||
static void slowFontsetInfo(int R, int F, List<Slot> alist) {
|
||||
slowOps = 0;
|
||||
for (int i = 0; i < R; i++) {
|
||||
for (int j = 0; j < F; j++) {
|
||||
// pick spec deterministically
|
||||
Slot slot = alist.get(j % alist.size());
|
||||
String name = "font-" + i + "-" + j;
|
||||
|
||||
// Fmember equivalent: O(N) scan, N grows
|
||||
boolean found = false;
|
||||
for (String n : slot.names) {
|
||||
slowOps++;
|
||||
if (n.equals(name)) { found = true; break; }
|
||||
}
|
||||
if (!found) {
|
||||
slot.names.add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---- FAST: hash set for dedup ------------------------------------------
|
||||
|
||||
static long fastOps;
|
||||
|
||||
static void fastFontsetInfo(int R, int F, List<Slot> alist) {
|
||||
fastOps = 0;
|
||||
for (int i = 0; i < R; i++) {
|
||||
for (int j = 0; j < F; j++) {
|
||||
Slot slot = alist.get(j % alist.size());
|
||||
String name = "font-" + i + "-" + j;
|
||||
|
||||
fastOps++; // one hash lookup
|
||||
if (slot.nameSet.add(name)) {
|
||||
// name was absent — successfully added
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---- helpers -----------------------------------------------------------
|
||||
|
||||
static List<Slot> makeAlist(int A) {
|
||||
List<Slot> alist = new ArrayList<>();
|
||||
for (int a = 0; a < A; a++) alist.add(new Slot("spec-" + a));
|
||||
return alist;
|
||||
}
|
||||
|
||||
static void reset(List<Slot> alist) {
|
||||
for (Slot s : alist) { s.names.clear(); s.nameSet.clear(); }
|
||||
}
|
||||
|
||||
// ---- main --------------------------------------------------------------
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("=== emacs-0001: FontsetInfoAlgorithm (Fmember dedup) ===");
|
||||
|
||||
int[] sizes = {10, 50, 100, 200};
|
||||
int F = 5; // font entries per char-range slot
|
||||
int A = 10; // alist entries (distinct font-specs)
|
||||
|
||||
System.out.printf("%-10s %-15s %-15s %-10s%n",
|
||||
"R (real.)", "slow_ops", "fast_ops", "ratio");
|
||||
System.out.println("-".repeat(55));
|
||||
|
||||
for (int R : sizes) {
|
||||
List<Slot> alistSlow = makeAlist(A);
|
||||
List<Slot> alistFast = makeAlist(A);
|
||||
|
||||
slowFontsetInfo(R, F, alistSlow);
|
||||
fastFontsetInfo(R, F, alistFast);
|
||||
|
||||
double ratio = slowOps == 0 ? 1.0 : (double) slowOps / fastOps;
|
||||
System.out.printf("%-10d %-15d %-15d %-10.1f%n",
|
||||
R, slowOps, fastOps, ratio);
|
||||
}
|
||||
|
||||
// Correctness check
|
||||
{
|
||||
int R = 20, testA = 4;
|
||||
List<Slot> s = makeAlist(testA);
|
||||
List<Slot> f = makeAlist(testA);
|
||||
slowFontsetInfo(R, F, s);
|
||||
fastFontsetInfo(R, F, f);
|
||||
// Both should produce same unique name sets
|
||||
for (int i = 0; i < testA; i++) {
|
||||
Set<String> slowSet = new HashSet<>(s.get(i).names);
|
||||
Set<String> fastSet = f.get(i).nameSet;
|
||||
if (!slowSet.equals(fastSet)) {
|
||||
System.err.println("FAIL: mismatch at slot " + i);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
System.out.println("\nCORRECTNESS: PASS");
|
||||
}
|
||||
|
||||
// Assertion: slow must be significantly more ops than fast for large R
|
||||
{
|
||||
int bigR = 200;
|
||||
List<Slot> s = makeAlist(A);
|
||||
List<Slot> f = makeAlist(A);
|
||||
slowFontsetInfo(bigR, F, s);
|
||||
fastFontsetInfo(bigR, F, f);
|
||||
double r = (double) slowOps / fastOps;
|
||||
System.out.printf("Ratio at R=%d: %.1fx%n", bigR, r);
|
||||
if (r < 5.0) {
|
||||
System.err.println("FAIL: expected ratio >= 5x at R=" + bigR);
|
||||
System.exit(1);
|
||||
}
|
||||
System.out.println("RATIO ASSERTION: PASS");
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue