fix: bounds-check palette cache instead of relying on overflow
Browse filesSkip the cache write when cache_count >= 256 rather than overflowing
into the dirty field. The dirty field is set to 1 immediately after,
so the overflow had no observable effect.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
crates/openwa-core/src/render/palette.rs
CHANGED
|
@@ -56,8 +56,10 @@ pub unsafe fn palette_map_color(ctx: *mut PaletteContext, rgb: u32) -> u32 {
|
|
| 56 |
|
| 57 |
let cache_count = *(p.add(0x606) as *const i16);
|
| 58 |
|
| 59 |
-
// Search cache for matching RGB (24-bit compare)
|
| 60 |
-
|
|
|
|
|
|
|
| 61 |
let idx = *p.add(0x608 + i) as usize;
|
| 62 |
if idx != 0 && (*(p.add(0x04 + idx * 4) as *const u32) ^ rgb) & 0xFF_FFFF == 0 {
|
| 63 |
return idx as u32;
|
|
@@ -75,9 +77,12 @@ pub unsafe fn palette_map_color(ctx: *mut PaletteContext, rgb: u32) -> u32 {
|
|
| 75 |
let slot = *p.add(0x506 + new_free_count as usize);
|
| 76 |
let slot_idx = slot as usize;
|
| 77 |
|
| 78 |
-
// Add to cache
|
| 79 |
-
//
|
| 80 |
-
|
|
|
|
|
|
|
|
|
|
| 81 |
*(p.add(0x606) as *mut i16) = cache_count + 1;
|
| 82 |
|
| 83 |
// Store RGB and mark in-use
|
|
|
|
| 56 |
|
| 57 |
let cache_count = *(p.add(0x606) as *const i16);
|
| 58 |
|
| 59 |
+
// Search cache for matching RGB (24-bit compare).
|
| 60 |
+
// Clamp to 256 — WA doesn't bounds-check cache_count.
|
| 61 |
+
let search_len = (cache_count as usize).min(256);
|
| 62 |
+
for i in 0..search_len {
|
| 63 |
let idx = *p.add(0x608 + i) as usize;
|
| 64 |
if idx != 0 && (*(p.add(0x04 + idx * 4) as *const u32) ^ rgb) & 0xFF_FFFF == 0 {
|
| 65 |
return idx as u32;
|
|
|
|
| 77 |
let slot = *p.add(0x506 + new_free_count as usize);
|
| 78 |
let slot_idx = slot as usize;
|
| 79 |
|
| 80 |
+
// Add to cache. WA doesn't bounds-check: when cache_count == 256 it writes
|
| 81 |
+
// past cache[] into the dirty field, which is set to 1 immediately after.
|
| 82 |
+
// We just skip the write instead.
|
| 83 |
+
if (cache_count as usize) < 256 {
|
| 84 |
+
*p.add(0x608 + cache_count as usize) = slot;
|
| 85 |
+
}
|
| 86 |
*(p.add(0x606) as *mut i16) = cache_count + 1;
|
| 87 |
|
| 88 |
// Store RGB and mark in-use
|