Description
Describe the bug
Allocating heap for an object of any size and then attempting to initialise any part of the memory using the swr <src reg>, <offset>(<dst addr reg>)
or swl <src reg>, <offset>(<dst addr reg>)
instructions causes MSAN to falsely report that an uninitialised read is occurring.
This is due to the emulator implementing swr
(DynaRecCPU::recSWR) and swl
(DynaRecCPU::recSWL) as several micro-ops starting with a read at the aligned address, modifying the lower (swr
) or upper (swl
) 1-4 bytes, then writing back to the aligned address.
The initial aligned read is performed via PCSX::Memory::read32 (maybe other method depending on the read size, 32, 16, 8 bits respectively) which issues a call to PCSX::Memory::msanGetStatus and thus detects an uninitialised read, invoking a breakpoint + console write.
Expected behavior
Ideally, this should either mask out the bytes being written to when checking initialisation of memory, but still attempt to validate the usability of the memory. Thus, no uninitialised read will be triggered for this circumstance.
Steps to reproduce the bug
Minimal reproducible example:
static __inline__ void* pcsx_msanAlloc(uint32_t size) {
register uint32_t a0 asm("a0") = size;
return *((void* volatile* const)0x1f80208c);
}
static __inline__ void pcsx_msanFree(void* ptr) {
*((void* volatile* const)0x1f80208c) = ptr;
}
int main() {
uint32_t* array = pcsx_msanAlloc(sizeof(uint32_t));
int byte_value = '\0';
asm ("swr %1, 0(%0)"
:
: "r" (array), "r" (byte_value));
pcsx_msanFree(array);
return 0;
}
Operating System
MacOS Sequoia
PCSX-Redux version
Version: dec9cd9
Build: 151
Changeset: dec9cd9
Date & time: 2025-04-18 08:19:57
CPU model
Apple M4 Pro
GPU model & Drivers
Apple M4 Pro, OpenGL 4.1, Metal 89.4
BIOS version
OpenBIOS
Options
- Dynarec CPU
- 8MB
- OpenGL GPU
- Fastboot
- Debugger
Iso checks
No response
Logs
Loaded BIOS: /Applications/PCSX-Redux.app/Contents/MacOS/../Resources/share/pcsx-redux/resources/openbios.bin
OpenBIOS detected (69be4aa4)
Loaded CD Image: /Users/jackkilrain/projects/C-CPP/PSX-Minecraft/build/PSXMC.bin[+cue].
Track 01 (DATA) - Start 00:02:00, Length 00:00:54
CD-ROM Label: PSXMC
CD-ROM ID:
CD-ROM EXE Name: PSXMC.exe
================
uC-sdk - booting
================
BIOS Trace1: 0x0f
BIOS Trace1: 0x0e
BIOS Trace1: 0x01
BIOS Trace1: 0x02
BIOS Trace1: 0x03
BIOS Trace1: 0x04
BIOS Trace1: 0x01
BIOS Trace1: 0x03
BIOS Trace1: 0x04
BIOS Trace1: 0x05
BIOS Trace1: 0x06
BIOS Trace1: 0x02
BIOS Trace1: 0x05
PS-X Realtime Kernel OpenBios - build id d9a6e07696256e0f7b0ac3e9b261e53cfc32e648.
Copyright (C) 2019-2025 PCSX-Redux authors.
BIOS Trace1: 0x06
KERNEL SETUP!
Configuration : EvCB 0x10 TCB 0x04
BIOS Trace1: 0x07
*** OpenBIOS tiny shell - starting ***
*** Data is acceptable, booting now. ***
BIOS Trace1: 0x08
BOOTSTRAP LOADER
BIOS Trace1: 0x09
setup file : cdrom:SYSTEM.CNF;1
TCB 00000004
EVENT 00000010
STACK 801ffff0
BOOT = cdrom:\PSXMC.exe
argument =
KERNEL SETUP!
Configuration : EvCB 0x10 TCB 0x04
boot file : cdrom:\PSXMC.exe
EXEC:PC0(80010118) T_ADDR(80010000) T_SIZE(00001800)
boot address : 80010118 801ffff0
Execute !
S_ADDR(801ffff0) S_SIZE(00000000)
c: Initialised TLSF allocator
32-bit read from usable but uninitialized msan memory: 20000400
Additional information
SDKs like PSn00bSDK, or just regular user implementation of inline ASM, optimisations by the compiler, etc will most likely run in to this. In this case, the memset
implementation in PSn00bSDK uses a modified Duff's machine to do batched writes over large address spaces, using swr
to fill the alignment correctly before issuing batched stores.
In one of the original PRs that implemented MSAN, it was noted that this might need to be handled: #1866 (comment) and that there was an approach that seems to line up with the masking idea presented here: #1866 (comment).