dosbox-x-0001/0002, rpcs3-0001/0002/0003, ppsspp-0001/0002/0003: 8 CWE-407 defects across 3 emulators
DOSBox-X: overlay drive DOSnames_cache + deleted_files_in_base vector dedup (devs commented "set is probably better") RPCS3: SPU recompiler predecessor/call vector dedup + cellSaveData blist sort comparator PPSSPP: kernel thread/semaphore waitingThreads dedup + IR JIT byPage block removal 16/16 unit tests PASS, ratios 5-93x
This commit is contained in:
parent
87a11e22f9
commit
50c1301928
11 changed files with 678 additions and 0 deletions
153
defects/dosbox-x/test/DosboxXOverlayCacheTest.java
Normal file
153
defects/dosbox-x/test/DosboxXOverlayCacheTest.java
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Unit tests for DOSBox-X CWE-407 defects in overlay drive caching.
|
||||
*
|
||||
* dosbox-x-0001: add_DOSname_to_cache linear vector dedup O(N^2)
|
||||
* dosbox-x-0002: is_deleted_file linear vector scan O(N) per call
|
||||
*
|
||||
* Models the C++ std::vector<std::string> with strcasecmp dedup pattern
|
||||
* and demonstrates the fix using HashSet with case-insensitive semantics.
|
||||
*/
|
||||
public class DosboxXOverlayCacheTest {
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// dosbox-x-0001: DOSnames_cache vector dedup
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
/** DEFECTIVE: O(N) linear scan per insertion → O(N^2) total */
|
||||
static List<String> addDOSname_defective(List<String> cache, String name) {
|
||||
for (String entry : cache) {
|
||||
if (entry.equalsIgnoreCase(name)) return cache;
|
||||
}
|
||||
cache.add(name);
|
||||
return cache;
|
||||
}
|
||||
|
||||
/** FIXED: O(1) amortized insertion with case-insensitive HashSet */
|
||||
static Set<String> addDOSname_fixed(Set<String> cache, String name) {
|
||||
cache.add(name.toUpperCase());
|
||||
return cache;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// dosbox-x-0002: is_deleted_file linear vector scan
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
/** DEFECTIVE: O(N) linear scan through deleted_files_in_base */
|
||||
static boolean isDeletedFile_defective(List<String> deletedFiles, String name) {
|
||||
for (String f : deletedFiles) {
|
||||
if (f.equalsIgnoreCase(name)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** FIXED: O(1) hash lookup */
|
||||
static boolean isDeletedFile_fixed(Set<String> deletedFiles, String name) {
|
||||
return deletedFiles.contains(name.toUpperCase());
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int N = 5000;
|
||||
int passed = 0;
|
||||
int failed = 0;
|
||||
|
||||
// --- Test 1: dosbox-x-0001 correctness ---
|
||||
{
|
||||
List<String> defectCache = new ArrayList<>();
|
||||
Set<String> fixedCache = new HashSet<>();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
String name = "FILE" + i + ".TXT";
|
||||
addDOSname_defective(defectCache, name);
|
||||
addDOSname_defective(defectCache, name.toLowerCase()); // case-insensitive dedup
|
||||
addDOSname_fixed(fixedCache, name);
|
||||
addDOSname_fixed(fixedCache, name.toLowerCase());
|
||||
}
|
||||
boolean ok = defectCache.size() == 100 && fixedCache.size() == 100;
|
||||
System.out.println((ok ? "PASS" : "FAIL") + " dosbox-x-0001 correctness: dedup 100 names (case-insensitive)");
|
||||
if (ok) passed++; else failed++;
|
||||
}
|
||||
|
||||
// --- Test 2: dosbox-x-0001 performance ---
|
||||
{
|
||||
List<String> defectCache = new ArrayList<>();
|
||||
Set<String> fixedCache = new HashSet<>();
|
||||
|
||||
long t0 = System.nanoTime();
|
||||
for (int i = 0; i < N; i++) {
|
||||
addDOSname_defective(defectCache, "NAME" + i + ".DOS");
|
||||
}
|
||||
long defectNs = System.nanoTime() - t0;
|
||||
|
||||
t0 = System.nanoTime();
|
||||
for (int i = 0; i < N; i++) {
|
||||
addDOSname_fixed(fixedCache, "NAME" + i + ".DOS");
|
||||
}
|
||||
long fixedNs = System.nanoTime() - t0;
|
||||
|
||||
double ratio = (double) defectNs / Math.max(fixedNs, 1);
|
||||
boolean ok = ratio > 5.0;
|
||||
System.out.printf("%s dosbox-x-0001 performance: N=%d defect=%.1fms fixed=%.1fms ratio=%.1fx%n",
|
||||
ok ? "PASS" : "FAIL", N,
|
||||
defectNs / 1e6, fixedNs / 1e6, ratio);
|
||||
if (ok) passed++; else failed++;
|
||||
}
|
||||
|
||||
// --- Test 3: dosbox-x-0002 correctness ---
|
||||
{
|
||||
List<String> defectList = new ArrayList<>();
|
||||
Set<String> fixedSet = new HashSet<>();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
String name = "DELETED" + i + ".TMP";
|
||||
defectList.add(name);
|
||||
fixedSet.add(name.toUpperCase());
|
||||
}
|
||||
boolean allMatch = true;
|
||||
for (int i = 0; i < 100; i++) {
|
||||
String query = "deleted" + i + ".tmp"; // lowercase query
|
||||
boolean d = isDeletedFile_defective(defectList, query);
|
||||
boolean f = isDeletedFile_fixed(fixedSet, query);
|
||||
if (d != f) { allMatch = false; break; }
|
||||
}
|
||||
// Also check non-existent
|
||||
boolean dNeg = isDeletedFile_defective(defectList, "NOTHERE.TXT");
|
||||
boolean fNeg = isDeletedFile_fixed(fixedSet, "NOTHERE.TXT");
|
||||
boolean ok = allMatch && !dNeg && !fNeg;
|
||||
System.out.println((ok ? "PASS" : "FAIL") + " dosbox-x-0002 correctness: deleted file lookup");
|
||||
if (ok) passed++; else failed++;
|
||||
}
|
||||
|
||||
// --- Test 4: dosbox-x-0002 performance ---
|
||||
{
|
||||
List<String> defectList = new ArrayList<>();
|
||||
Set<String> fixedSet = new HashSet<>();
|
||||
for (int i = 0; i < N; i++) {
|
||||
String name = "BASE\\OVERLAY\\FILE" + i + ".DAT";
|
||||
defectList.add(name);
|
||||
fixedSet.add(name.toUpperCase());
|
||||
}
|
||||
|
||||
long t0 = System.nanoTime();
|
||||
for (int i = 0; i < N; i++) {
|
||||
isDeletedFile_defective(defectList, "BASE\\OVERLAY\\FILE" + (N - 1 - i) + ".DAT");
|
||||
}
|
||||
long defectNs = System.nanoTime() - t0;
|
||||
|
||||
t0 = System.nanoTime();
|
||||
for (int i = 0; i < N; i++) {
|
||||
isDeletedFile_fixed(fixedSet, "BASE\\OVERLAY\\FILE" + (N - 1 - i) + ".DAT");
|
||||
}
|
||||
long fixedNs = System.nanoTime() - t0;
|
||||
|
||||
double ratio = (double) defectNs / Math.max(fixedNs, 1);
|
||||
boolean ok = ratio > 5.0;
|
||||
System.out.printf("%s dosbox-x-0002 performance: N=%d defect=%.1fms fixed=%.1fms ratio=%.1fx%n",
|
||||
ok ? "PASS" : "FAIL", N,
|
||||
defectNs / 1e6, fixedNs / 1e6, ratio);
|
||||
if (ok) passed++; else failed++;
|
||||
}
|
||||
|
||||
System.out.printf("%n%d/%d tests passed%n", passed, passed + failed);
|
||||
if (failed > 0) System.exit(1);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue