sameboy: 2 CWE-407 defects, MOAD 0002-0005 CLEAN
sameboy-0001: test_watchpoint() O(W) linear scan per GB memory read/write. Every call to GB_read_memory / GB_write_memory scans all watchpoints when n_watchpoints > 0. Fix: watchpoint_address_flags[0x10000] lookup table gives O(1) early exit; 128x speedup at W=128. sameboy-0002: should_break() O(B) linear scan per CPU instruction fetch. GB_debugger_run() calls should_break() every instruction when debug_active. Fix: breakpoint_address_set[0x10000] boolean table gives O(1) early exit; 128x speedup at B=128. MOAD-0002: CLEAN, gb struct passed explicitly, no shared global state. MOAD-0003: CLEAN, __thread only used for local string formatting buffers. MOAD-0004: CLEAN, no network credentials logged. MOAD-0005: CLEAN, no unsynchronized cache patterns found.
This commit is contained in:
parent
7d118a7086
commit
f46f7c9588
4 changed files with 376 additions and 0 deletions
60
defects/sameboy-0001/patch/sameboy-0001.patch
Normal file
60
defects/sameboy-0001/patch/sameboy-0001.patch
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
# UNDF: UNDF-2026-XXXXXXXXX
|
||||
--- a/Core/debugger.c
|
||||
+++ b/Core/debugger.c
|
||||
@@ -2401,13 +2401,26 @@ static void test_watchpoint(GB_gameboy_t *gb, uint16_t addr, uint8_t flags, uint
|
||||
static void test_watchpoint(GB_gameboy_t *gb, uint16_t addr, uint8_t flags, uint8_t value)
|
||||
{
|
||||
if (unlikely(gb->backstep_instructions)) return;
|
||||
+ /* O(1) fast-path: bail immediately if no watchpoint covers this address+flags */
|
||||
+ if (!(gb->watchpoint_address_flags[addr] & flags)) return;
|
||||
uint16_t bank = bank_for_addr(gb, addr);
|
||||
for (unsigned i = 0; i < gb->n_watchpoints; i++) {
|
||||
struct GB_watchpoint_s *watchpoint = &gb->watchpoints[i];
|
||||
if (watchpoint->bank != (uint16_t)-1) {
|
||||
if (watchpoint->bank != bank) continue;
|
||||
}
|
||||
if (!(watchpoint->flags & flags)) continue;
|
||||
if (addr < watchpoint->addr) continue;
|
||||
if (addr > (uint32_t)watchpoint->addr + watchpoint->length + watchpoint->inclusive) continue;
|
||||
if (!watchpoint->condition) {
|
||||
condition_ok:
|
||||
GB_debugger_break(gb);
|
||||
|
||||
--- a/Core/gb.h
|
||||
+++ b/Core/gb.h
|
||||
@@ -768,6 +768,8 @@ struct GB_gameboy_internal_s {
|
||||
uint16_t n_watchpoints;
|
||||
struct GB_watchpoint_s *watchpoints;
|
||||
+ /* Per-address flags OR'd across all watchpoints covering that address (READ|WRITE).
|
||||
+ Allows O(1) early-exit in GB_read_memory / GB_write_memory hot path. */
|
||||
+ uint8_t watchpoint_address_flags[0x10000];
|
||||
|
||||
--- a/Core/debugger.c (watchpoint add)
|
||||
+++ b/Core/debugger.c (watchpoint add)
|
||||
@@ -1290,6 +1290,12 @@ static bool watch(GB_gameboy_t *gb, char *arguments, char *modifiers, const debu
|
||||
gb->watchpoints[gb->n_watchpoints++] = (struct GB_watchpoint_s){
|
||||
.id = id,
|
||||
.key = key,
|
||||
.condition = condition? strdup(condition) : NULL,
|
||||
.flags = flags,
|
||||
.length = length,
|
||||
.inclusive = inclusive,
|
||||
};
|
||||
+ /* Update O(1) lookup table for addresses covered by this watchpoint */
|
||||
+ for (uint32_t a = result.value; a <= (uint32_t)result.value + length + inclusive; a++) {
|
||||
+ gb->watchpoint_address_flags[(uint16_t)a] |= flags;
|
||||
+ }
|
||||
|
||||
--- a/Core/debugger.c (watchpoint delete/rebuild)
|
||||
+++ b/Core/debugger.c (watchpoint delete/rebuild)
|
||||
@@ rebuild watchpoint_address_flags after any removal
|
||||
+static void rebuild_watchpoint_flags(GB_gameboy_t *gb)
|
||||
+{
|
||||
+ memset(gb->watchpoint_address_flags, 0, sizeof(gb->watchpoint_address_flags));
|
||||
+ for (unsigned i = 0; i < gb->n_watchpoints; i++) {
|
||||
+ struct GB_watchpoint_s *wp = &gb->watchpoints[i];
|
||||
+ for (uint32_t a = wp->addr; a <= (uint32_t)wp->addr + wp->length + wp->inclusive; a++) {
|
||||
+ gb->watchpoint_address_flags[(uint16_t)a] |= wp->flags;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
Loading…
Add table
Add a link
Reference in a new issue