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:
russell@unturf.com 2026-03-31 07:33:28 -04:00
parent 87a11e22f9
commit 50c1301928
11 changed files with 678 additions and 0 deletions

View file

@ -0,0 +1,19 @@
--- a/Core/HLE/sceKernelThread.cpp
+++ b/Core/HLE/sceKernelThread.cpp
@@ -2544 +2544 @@
- if (std::find(t->waitingThreads.begin(), t->waitingThreads.end(), currentThread) == t->waitingThreads.end())
+ if (t->waitingThreadSet.insert(currentThread).second)
t->waitingThreads.push_back(currentThread);
@@ -2571 +2571 @@
- if (std::find(t->waitingThreads.begin(), t->waitingThreads.end(), currentThread) == t->waitingThreads.end())
+ if (t->waitingThreadSet.insert(currentThread).second)
t->waitingThreads.push_back(currentThread);
#
# CWE-407: sceKernelWaitThreadEnd and sceKernelWaitThreadEndCB scan
# t->waitingThreads vector with std::find before push_back — O(W) per
# wait where W = number of waiting threads. In pathological cases where
# many threads wait on the same target (e.g., barrier-like patterns in
# homebrew), this degrades to O(W^2).
# Fix: maintain parallel unordered_set for O(1) dedup.
# Severity: MEDIUM — kernel thread wait is a hot HLE path; homebrew
# using thread synchronization patterns can trigger this.

View file

@ -0,0 +1,16 @@
--- a/Core/HLE/sceKernelSemaphore.cpp
+++ b/Core/HLE/sceKernelSemaphore.cpp
@@ -370 +370 @@
- if (std::find(s->waitingThreads.begin(), s->waitingThreads.end(), threadID) == s->waitingThreads.end())
+ if (s->waitingThreadSet.insert(threadID).second)
s->waitingThreads.push_back(threadID);
#
# CWE-407: sceKernelWaitSemaCB / sceKernelWaitSema scan
# s->waitingThreads vector with std::find before push_back — O(W)
# per sema wait. Comment in code says "May be in a tight loop timing
# out (where we don't remove from waitingThreads yet), don't want to
# add duplicates." — the tight-loop scenario is exactly where O(W)
# dedup costs compound.
# Fix: maintain parallel unordered_set for O(1) dedup.
# Severity: MEDIUM — semaphore wait is a critical HLE synchronization
# primitive; games using producer-consumer patterns hit this frequently.

View file

@ -0,0 +1,20 @@
--- a/Core/MIPS/IR/IRJit.cpp
+++ b/Core/MIPS/IR/IRJit.cpp
@@ -363,4 +363,5 @@
for (u32 page = startPage; page <= endPage; ++page) {
- auto iter = std::find(byPage_[page].begin(), byPage_[page].end(), blockIndex);
+ auto& pageBlocks = byPage_[page];
+ auto iter = std::find(pageBlocks.begin(), pageBlocks.end(), blockIndex);
+ // TODO: Replace vector with unordered_set for O(1) removal
if (iter != byPage_[page].end()) {
byPage_[page].erase(iter);
#
# CWE-407: IRBlockCache::RemoveBlockFromPageLookup scans byPage_[page]
# vector with std::find for block removal — O(B) per page where B =
# blocks in that page. Called for every page spanned by the block being
# removed. When self-modifying code or icache flushes trigger frequent
# block invalidation, pages with many compiled blocks degrade.
# Fix: replace the vector<int> per page with an unordered_set<int> for
# O(1) membership test and removal.
# Severity: MEDIUM — JIT block invalidation is triggered by
# sceKernelIcacheClearAll and self-modifying code patterns.