Skip to content

Fix msan false positive swl swr uninit read#2033

Draft
EngineersBox wants to merge 65 commits into
grumpycoders:mainfrom
EngineersBox:fix-msan-false-positive-swl-swr-uninit-read
Draft

Fix msan false positive swl swr uninit read#2033
EngineersBox wants to merge 65 commits into
grumpycoders:mainfrom
EngineersBox:fix-msan-false-positive-swl-swr-uninit-read

Conversation

@EngineersBox

@EngineersBox EngineersBox commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Overview

Addresses #1928 by fix MSAN false positives on swl/swr uninitialised read for non-32-bit read before write. Also fixes lsl/lsr not validating for sub-32-bit writes from swl/swr initialisation.

Masking

This adds masking variants of read32/write32 to allow for sub-32-bit masks. For the store instructions we have the following byte layouts (ri = register byte indexed by i from LSB, mi = same but for memory), with the matching byte mask for which bytes are modifying memory, the unset mask values are the bytes that were read from memory. The mask is used with the MSAN write check to mark which bytes have been initialised, and which have not.

swl:

Imm Value MSAN Write Mask
0 m3m2m1r3 0001
1 m3m2r3r2 0011
2 m3r3r2r1 0111
3 r3r2r1r0 1111

Mask expression: 0b1111 >> (3 - Imm)

swr:

Imm Value MSAN Write Mask
0 r3r2r1r0 1111
1 r2r1r0m0 1110
2 r1r0m1m0 1100
3 r0m2m1m0 1000

Mask expression: (0b1111 << Imm) & 0b1111

In the case of the load instructions, the byte mask is the same except that it is used with the read check instead. The mask indicates which bytes are being read from memory and need to validate usability and initialisation.

lwl:

Imm Value MSAN Read Mask
0 m0r2r1r0 0001
1 m1m0r1r0 0011
2 m2m1m0r0 0111
3 m3m2m1m0 1111

Mask expression: 0b1111 >> (3 - Imm)

lwr:

Imm Value MSAN Read Mask
0 m3m2m1m0 1111
1 r3m3m2m1 1110
2 r3r2m3m2 1100
3 r3r2r1m3 1000

Mask expression: (0b1111 << Imm) & 0b1111

MSAN Read Check

In the current MSAN check, we check whether the bytes being access in the read have been allocated and initialised via a bit mask. This is computed as follows:

uint32_t bitmapIndex = (addr - c_msanStart) / 8;
uint32_t bitmask = ((1 << length) - 1) << addr % 8;

To make this generic, we apply an additional mask to the bitmask value, provided as an argument.
By default his additional mask is UINT32_MAX which leaves it unchanged. For the swr/swl/lwr/lwl instructions, this will be their respective read mask calculated for the instruction immediate value. Hence, this becomes:

uint32_t bitmask = (((1 << length) - 1) << addr % 8) & sub_bitmask;

MSAN Write Check

Similar to the read check, the write check validates the bytes being accessed have been allocated and then updates the initialisation bitmap. The same logic applies here for modifying the bitmask to apply the write mask calculated using the isntruction immediate, the default mask is also UINT32_MAX here as well.

MSAN Partial Initialisation Status

Since the swl/swr instructions allow for partial initialisation of a 32-bit memory entry (i.e. 1-3 bytes only initialised), we should disambiguate this from a fully uninitialised read. Doing so will help users debug the write sizes that are candidates for the source of partial initialisation, or determine the read is too wide for the desired memory location.

This done by checking the initialised bitmask of the memory area being accessed and comparing it to a zero-value. If all bits are unset, then it is a fully uninitialised read, otherwise it is a partially initialised read. This relies on a prior assumption that we've already checked for a fully initialised read (i.e. all bits set).

Note

The MSAN viewer ImGUI widget already supports per-byte calculations for initialisation and usability.
Thus we don't need to support any additional infrastructure for those calculations with these MSAN changes.

TODO

  • Fix DynaRec implementation on aarch64 and x64
  • Port changes to interpreted CPU implementation
  • Add MSAN status for reads into uninitialised bytes of usable, partially initialized memory
  • Add tests

… msan check for sub-32 bit init

Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
…o constant compile-time optimised args

Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 10be9d5c-ef02-481c-ab77-1c4ff42c191e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
@pull-request-size pull-request-size Bot added size/L and removed size/M labels Jun 16, 2026
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
…wing for sub-32-bit MSAN triggers

Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
…mediate value instead of mask from LUT

Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
…s and inline duplications per-compilation unit

Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
… calls

Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
…ure consistent setup with event bus

Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
…ure consistent setup with event bus

Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Signed-off-by: EngineersBox <35655145+EngineersBox@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant