You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Make sure memcpy/memmove/memset with size 0 behave correctly #516
Zero-sized memory accesses are now always permitted, even if the pointer is NULL or dangling (but it must be aligned still). For codegen this means in particular that memcpy/memmove/memset must be lowered to operations that are never UB when the size is 0 (and the pointer is sufficiently aligned). In LLVM that's easy as LLVM's corresponding intrinsics explicitly allow size 0. However, in C, memcpy/memmove/memset with size 0 is UB on NULL (and dangling pointers are impossible to even mention in C), so GCC may use a different semantics for its builtins. For Rust's GCC backend, it's crucial that we use GCC builtins that allow size 0 with any pointer.
#include<string.h>intdo_thing1();
intdo_thing2();
voidtest(char*dest, constchar*src, size_tlen) {
memcpy(dest, src, len);
if (dest==NULL) {
// This branch will be removed by GCC due to undefined behavior.do_thing1();
} else {
do_thing2();
}
}
Here, the memory copy of dest allows GCC to assume that the pointer is not null, optimizing the branch check away. This is enabled with -O2(more specifically, with -fdelete-null-pointer-checks).
This does not seem to break Rust code today, at least on x86_64(is cg_gcc disabling -fdelete-null-pointer-checks), but there is a slight chance that the ARM bootstrap crashes are caused by zero-sized copies(the debug info is a bit muddy, and it is hard to tell what is going on, exactly).
From what I heard, C26 will also permit memcpy on NULL (when the size is 0), so it might be best for GCC to just entirely stop doing this optimization.
Activity
hhamud commentedon May 24, 2024
@antoyo Can I try this one?
Also any pointers on how to solve this issue will be helpful
antoyo commentedon May 25, 2024
@hhamud: I assigned the issue to you.
You would need to check if the GCC builtins follow the right semantics and if not, adjust the code here so that we follow the right semantics.
GrigorenkoPV commentedon Aug 5, 2024
There are proposals in progress to allow that: https://www.open-std.org/JTC1/SC22/WG14/www/docs/n3261.pdf
Fingers crossed it gets accepted
FractalFir commentedon Jun 14, 2025
After a bit of research, I have found an example where GCC optimizes things based on the assumption that the arguments to memcpy are not null.
Here is a sample I found on the internet:
https://godbolt.org/z/aPcr1bfPe
Here, the memory copy of
destallows GCC to assume that the pointer is not null, optimizing the branch check away. This is enabled with-O2(more specifically, with-fdelete-null-pointer-checks).This does not seem to break Rust code today, at least on x86_64(is
cg_gccdisabling-fdelete-null-pointer-checks), but there is a slight chance that the ARM bootstrap crashes are caused by zero-sized copies(the debug info is a bit muddy, and it is hard to tell what is going on, exactly).antoyo commentedon Jun 14, 2025
I don't think we disable that.
Btw, I remember having to fix some issue in the past where GCC would remove null pointer checks.
RalfJung commentedon Jun 14, 2025
From what I heard, C26 will also permit
memcpyon NULL (when the size is 0), so it might be best for GCC to just entirely stop doing this optimization.mizoz commentedon Apr 28, 2026
Hi! I'd love to contribute. Could you assign this issue to me?
antoyo commentedon Apr 28, 2026
Done.