Re: C aggregate passing (Rust kernel policy)

From: Ralf Jung
Date: Wed Feb 26 2025 - 14:23:36 EST


Hi all,

But it is much more significant for Rust than for C, at least in
regards to C's "restrict", since "restrict" is rarely used in C, while
aliasing optimizations are pervasive in Rust. For C's "strict aliasing",
I think you have a good point, but "strict aliasing" is still easier to
reason about in my opinion than C's "restrict". Especially if you
never have any type casts of any kind nor union type punning.

Is it easier to reason about? At least GCC got it wrong, making no-aliasing
assumptions that are not justified by most people's interpretation of the model:
https://bugs.llvm.org/show_bug.cgi?id=21725
(But yes that does involve unions.)

Did you mean to say LLVM got this wrong? As far as I know,
the GCC TBBA code is more correct than LLVMs. It gets
type-changing stores correct that LLVM does not implement.

Oh sorry, yes that is an LLVM bug link. I mixed something up. I could have sworn there was a GCC bug, but I only found <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57359> which has been fixed.
There was some problem with strong updates, i.e. the standard permits writes through a `float*` pointer to memory that aliases an `int*`. The C aliasing model only says it is UB to read data at the wrong type, but does not talk about writes changing the type of memory.
Martin, maybe you remember better than me what that issue was / whether it is still a problem?

So, the situation for Rust here is a lot better than it is in C. Unfortunately,
running kernel code in Miri is not currently possible; figuring out how to
improve that could be an interesting collaboration.

I do not believe that you are correct when you write:

"Unlike sanitizers, Miri can actually catch everything."

Critically and very importantly, unless I am mistaken about MIRI, and
similar to sanitizers, MIRI only checks with runtime tests. That means
that MIRI will not catch any undefined behavior that a test does
not encounter. If a project's test coverage is poor, MIRI will not
check a lot of the code when run with those tests. Please do
correct me if I am mistaken about this. I am guessing that you
meant this as well, but I do not get the impression that it is
clear from your post.

Okay, I may have misunderstood what you mean by "catch everything". All
sanitizers miss some UB that actually occurs in the given execution. This is
because they are inserted in the pipeline after a bunch of compiler-specific
choices have already been made, potentially masking some UB. I'm not aware of a
sanitizer for sequence point violations. I am not aware of a sanitizer for
strict aliasing or restrict. I am not aware of a sanitizer that detects UB due
to out-of-bounds pointer arithmetic (I am not talking about OOB accesses; just
the arithmetic is already UB), or UB due to violations of "pointer lifetime end
zapping", or UB due to comparing pointers derived from different allocations. Is
there a sanitizer that correctly models what exactly happens when a struct with
padding gets copied? The padding must be reset to be considered "uninitialized",
even if the entire struct was zero-initialized before. Most compilers implement
such a copy as memcpy; a sanitizer would then miss this UB.

Note that reading padding bytes in C is not UB. Regarding
uninitialized variables, only automatic variables whose address
is not taken is UB in C.   Although I suspect that compilers
have compliance isues here.

Hm, now I am wondering how clang is compliant here. To my knowledge, padding is effectively reset to poison or undef on a copy (due to SROA), and clang marks most integer types as "noundef", thus making it UB to ever have undef/poison in such a value.

Kind regards,
Ralf


But yes, it sanitizers are still rather poor.




Martin


In contrast, Miri checks for all the UB that is used anywhere in the Rust
compiler -- everything else would be a critical bug in either Miri or the compiler.
But yes, it only does so on the code paths you are actually testing. And yes, it
is very slow.

Kind regards,
Ralf