Closed CAD97 closed 6 months ago
This came up because I was about to claim that Weak::into_raw
cannot guarantee to return an aligned non-null pointer in the face of sentinel dangling weak references (Weak::new
) existing, but realized that -align
could potentially be a valid sentinel which is both aligned and non-null but can't ever point to a valid object.
Considering the fact you can take a reference to any allocation you own the base pointer to, and then slice-index that, I'd assume no, it's not a valid address.
I asked this recently and someone pointed out that you can put a ZST at that address, including a slice of ZST
That's a ZST though. Zero sized allocations can exist anywhere. If Box::new([0u8])
were placed at usize::MAX
, you could safely take &x[1..]
and get a null reference, which is UB. Same with static or let, which takes care of all the possible ways you can allocate at the AM level.
Correct, only a ZST could be put at the last byte.
https://github.com/rust-lang/rust/pull/116675 answers this: we have base + size <= usize::MAX
. So usize::MAX can never be inside an allocation but it can be one-past-the-end of an allocation. ZST are the only cases where the address the reference points to equals the one-past-the-end address, and therefore they are the only case where the reference can have address usize::MAX
.
Because if so, an
inbounds
pointer offset doesn't actually implynowrap
.We permit the use of non-wrapping pointer offsets where
isize
; andusize
).I believe this has the effect of forbidding an allocation of
n
bytes from ever (soundly) being addressed at0.wrapping_sub(n)
, as this would cause the one-past-the-end pointer to wrap around the address space and be null.I don't think this should ever practically cause an issue, but it seems relevant to note, and could be exploited by
unsafe
code; e.g. while the traditionalalign_of::<T>() as *mut T
aligned-dangling pointer can't be used as a sentinel, as it's a potentially valid address for a real allocatedT
,-(align_of::<T>() as isize) as *mut T
would not be, ifptr.add(1)
is guaranteed non-null for every (sound) allocated object.