3

Re-enable `copy[_nonoverlapping]()` debug-checks by jfrimmel · Pull Request #900...

 2 years ago
source link: https://github.com/rust-lang/rust/pull/90041
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Copy link

Contributor

oli-obk commented on Oct 19

blocked on lang team sign off in the issue

}

#[cfg(all(not(bootstrap), debug_assertions))]

const fn compiletime_check<T>(_src: *const T, _dst: *mut T, _count: usize) {

// check is done implicitly by the CTFE-engine

Does this imply that miri checks the same conditions?

We were debating in the @rust-lang/lang meeting whether miri even could check alignment. I was assuming that we have some idea of what the alignment of an allocation will be (based on what type it was created to represent), and hence we could do the checks, but we weren't clear on what actually happens.

In general, what kind of guarantees do we expect to make here, either at runtime or compilation time? Are these covered in the comment above?

Our general feeling is that this is a "best effort" check and it's ok to go forward, but we were not clear on the overall limits of the extent to which miri can check this.

Copy link

Contributor

@oli-obk oli-obk on Oct 19

Well... these are only debug assertions, and they are commented out at present. But assuming that is irrelevant to the point: we are checking that the pointer is aligned by at least the alignment of the type of the pointee.

Miri checks everything, but miri uses the runtime path here, not the compile-time path.

CTFE mostly checks nothing unless necessary for being able to operate without ICEing. I don't remember if any alignment checks are still happening, but if they are, it's only because it was easier than having to separate the miri and CTFE logic.

Can we clarify these in-code comments to be specific about which checks are done or not done? Otherwise I think it's misleading to imply we are checking all of non null, alignment, and non-overlapping if that's not the case.

Copy link

Contributor

Author

@jfrimmel jfrimmel on Oct 19

Suggested change
// check is done implicitly by the CTFE-engine // Some best-effort checks (TODO: which) are done by the CTFE-engine. //This is fine as the runtime checks only happen in debug mode, so // undefined behavior would still occur in the release mode.

Maybe with a comment like this (obviously filled with the correct CTFE-checks done)?

Copy link

Contributor

@oli-obk oli-obk on Oct 20

CTFE does the following checks:

Make sure the total number of bytes is less than usize::max_value

let size = size.checked_mul(count, self).ok_or_else(|| { err_ub_format!( "overflow computing total size of `{}`", if nonoverlapping { "copy_nonoverlapping" } else { "copy" } ) })?;

Make sure both arguments are pointers with provenance

let src = self.read_pointer(&src)?; let dst = self.read_pointer(&dst)?;

Make sure that the pointers are in bounds of the allocation they point to and aligned properly

Note that "properly aligned" is pessimistic. If you allocate a [u8] and convert that to a [u16], it will still assume every byte has alignment 1, in contrast to real hardware, where every second byte has alignment 2.

let src_parts = self.get_ptr_access(src, size, src_align)?; let dest_parts = self.get_ptr_access(dest, size * num_copies, dest_align)?; // `Size` multiplication

Make sure the copy actually is nonoverlapping

if nonoverlapping { // `Size` additions if (src_offset <= dest_offset && src_offset + size > dest_offset) || (dest_offset <= src_offset && dest_offset + size > src_offset) { throw_ub_format!("copy_nonoverlapping called on overlapping ranges") } }

Copy link

Contributor

Author

@jfrimmel jfrimmel on Oct 20

Thanks for this great summary!

So, if I understand this correctly, the CTFE-does check the is_nonoverlapping and is_not_null (I assume null-pointers neither point to allocations nor have provonace) cases. So the is_aligned-part is missing.

One could simple update the comment with this information. But I wanna ask first: would it be even possible/reasonable to check the alignment?

Copy link

Contributor

@oli-obk oli-obk on Oct 20

alignment is checked, but the check is more conservative than the runtime check. This happens together with inbounds checks


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK