Change:
In , we document more precisely the rules for the various methods that can be used to access memory through raw pointers. In particular, we clarify that the pointer must be non-NULL and aligned even when the access has size 0. This issue is about helping people find bugs in libstd by adding a to all these methods testing that condition, similar to what I did . I suggest to add a helper method to raw pointers to test this, and also use that for and . This may uncover issues in libstd, uncovering misuses of these methods. Those should then be fixed.
I might be interested in working on that. Could you help me with a starting point for that?
You might want to start with It could get a check similar to To avoid code duplication, consider adding a (private) helper method in for this purpose, and using it in both the old places () and . Other candidates besides are and . We could also go further, but maybe we should involve the libs team there... so let's get started with these 3.
Sorry for the delay, it took me a while to free up some time. Quick questions: I found in However, one is just a delegation to the intrinsic, and the other one is for , which is just a call to the previous one. Should I hunt the intrinsic in the C code, or provide a rust wrapper that will check the assumptions and call the intrinsic? I couldn't find a in The only ones I could find were for , , and in . Am I missing something?
Ah, intrinsics are still written in Rust, but as code generation functions. Well, I guess adding debug assertions everywhere in the intrinsics would be counter-productive, so we're going for the wrapper? Although, I'm not sure how to cleanly hijack the interface: I have to keep using the same function name for the callers, so that I don't have to change their code, but unless I don't understand how it works, I also need to have the same signature including the function name for the code generation. How should I proceed?
Ah good point, I forgot about these reexports. I think the right way forward is to replace by a wrapper function that just calls the intrinsic. The docs should be moved from to . That move should be a total NOP. The, in the 2nd step, you can add the in the delegating wrapper you just . Sorry, I meant the one in . It already has a , but that does not test as much as it could (i.e., it accepts NULL).
Congrats, your patch landed. :) So with the preparation out of the way, let me know if you need any help with adding the debug assertions.
Thanks! I should be okay, I just need to find the time :) I'll ping you when it's ready for review.
Cc

Discussion:
#[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn write<T>(dst: *mut T, src: T) { <del> // FIXME: the debug assertion here causes codegen test failures on some architectures. // See <https://github.com/rust-lang/rust/pull/69208#issuecomment-591326757>. // debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer"); </del> <ins> debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer"); </ins> intrinsics::move_val_init(&mut *dst, src) }

use std::iter; <del> // CHECK: @helper([[USIZE:i[0-9]+]] %_1) #[no_mangle] pub fn helper(_: usize) { } </del> // CHECK-LABEL: @repeat_take_collect #[no_mangle] pub fn repeat_take_collect() -> Vec<u8> { <del> // CHECK: call void @llvm.memset.p0i8.[[USIZE]](i8* {{(nonnull )?}}align 1{{.*}} %{{[0-9]+}}, i8 42, [[USIZE]] 100000, i1 false) </del> <ins> // CHECK: call void @llvm.memset.p0i8.i{{[0-9]+}}(i8* {{(nonnull )?}}align 1{{.*}} %{{[0-9]+}}, i8 42, i{{[0-9]+}} 100000, i1 false) </ins> iter::repeat(42).take(100000).collect() }

#[inline(never)] fn verify_stack_usage(before_ptr: *mut Vec<Big>) { <del> // to check stack usage, create locals before and after </del> <ins> // To check stack usage, create locals before and after </ins> // and check the difference in addresses between them. let mut stack_var: Vec<Big> = vec![]; test::black_box(&mut stack_var); let stack_usage = isize::abs( (&mut stack_var as *mut _ as isize) - (before_ptr as isize)) as usize; <del> // give space for 2 copies of `Big` + 128 "misc" bytes. if stack_usage > mem::size_of::<Big>() * 2 + 128 { </del> <ins> // Give space for 2 copies of `Big` + 272 "misc" bytes // (value observed on x86_64-pc-windows-gnu). if stack_usage > mem::size_of::<Big>() * 2 + 272 { </ins> panic!("used {} bytes of stack, but `struct Big` is only {} bytes", stack_usage, mem::size_of::<Big>()); }