1
Fork 0

Rollup merge of #137920 - RalfJung:provenance-map-emptiness, r=oli-obk

interpret/provenance_map: consistently use range_is_empty

https://github.com/rust-lang/rust/pull/137704 started using this for per-ptr provenance; let's be consistent and use it also for the per-byte provenance check. Also rename the methods to avoid having both "get" and "is_empty" in the name.

r? ````@oli-obk````
This commit is contained in:
Michael Goulet 2025-03-06 12:22:27 -05:00 committed by GitHub
commit d21fc9d4f1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 22 additions and 22 deletions

View file

@ -470,7 +470,7 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
// Find the provenance. // Find the provenance.
let (offset, _prov) = self let (offset, _prov) = self
.provenance .provenance
.range_get_ptrs(range, cx) .range_ptrs_get(range, cx)
.first() .first()
.copied() .copied()
.expect("there must be provenance somewhere here"); .expect("there must be provenance somewhere here");

View file

@ -67,7 +67,7 @@ impl ProvenanceMap {
} }
impl<Prov: Provenance> ProvenanceMap<Prov> { impl<Prov: Provenance> ProvenanceMap<Prov> {
fn adjusted_range(range: AllocRange, cx: &impl HasDataLayout) -> Range<Size> { fn adjusted_range_ptrs(range: AllocRange, cx: &impl HasDataLayout) -> Range<Size> {
// We have to go back `pointer_size - 1` bytes, as that one would still overlap with // We have to go back `pointer_size - 1` bytes, as that one would still overlap with
// the beginning of this range. // the beginning of this range.
let adjusted_start = Size::from_bytes( let adjusted_start = Size::from_bytes(
@ -79,26 +79,21 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
/// Returns all ptr-sized provenance in the given range. /// Returns all ptr-sized provenance in the given range.
/// If the range has length 0, returns provenance that crosses the edge between `start-1` and /// If the range has length 0, returns provenance that crosses the edge between `start-1` and
/// `start`. /// `start`.
pub(super) fn range_get_ptrs( pub(super) fn range_ptrs_get(
&self, &self,
range: AllocRange, range: AllocRange,
cx: &impl HasDataLayout, cx: &impl HasDataLayout,
) -> &[(Size, Prov)] { ) -> &[(Size, Prov)] {
self.ptrs.range(Self::adjusted_range(range, cx)) self.ptrs.range(Self::adjusted_range_ptrs(range, cx))
} }
/// `pm.range_get_ptrs_is_empty(r, cx)` == `pm.range_get_ptrs(r, cx).is_empty()`, but is /// `pm.range_ptrs_is_empty(r, cx)` == `pm.range_ptrs_get(r, cx).is_empty()`, but is faster.
/// faster. pub(super) fn range_ptrs_is_empty(&self, range: AllocRange, cx: &impl HasDataLayout) -> bool {
pub(super) fn range_get_ptrs_is_empty( self.ptrs.range_is_empty(Self::adjusted_range_ptrs(range, cx))
&self,
range: AllocRange,
cx: &impl HasDataLayout,
) -> bool {
self.ptrs.range_is_empty(Self::adjusted_range(range, cx))
} }
/// Returns all byte-wise provenance in the given range. /// Returns all byte-wise provenance in the given range.
fn range_get_bytes(&self, range: AllocRange) -> &[(Size, Prov)] { fn range_bytes_get(&self, range: AllocRange) -> &[(Size, Prov)] {
if let Some(bytes) = self.bytes.as_ref() { if let Some(bytes) = self.bytes.as_ref() {
bytes.range(range.start..range.end()) bytes.range(range.start..range.end())
} else { } else {
@ -106,9 +101,14 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
} }
} }
/// Same as `range_bytes_get(range).is_empty()`, but faster.
fn range_bytes_is_empty(&self, range: AllocRange) -> bool {
self.bytes.as_ref().is_none_or(|bytes| bytes.range_is_empty(range.start..range.end()))
}
/// Get the provenance of a single byte. /// Get the provenance of a single byte.
pub fn get(&self, offset: Size, cx: &impl HasDataLayout) -> Option<Prov> { pub fn get(&self, offset: Size, cx: &impl HasDataLayout) -> Option<Prov> {
let prov = self.range_get_ptrs(alloc_range(offset, Size::from_bytes(1)), cx); let prov = self.range_ptrs_get(alloc_range(offset, Size::from_bytes(1)), cx);
debug_assert!(prov.len() <= 1); debug_assert!(prov.len() <= 1);
if let Some(entry) = prov.first() { if let Some(entry) = prov.first() {
// If it overlaps with this byte, it is on this byte. // If it overlaps with this byte, it is on this byte.
@ -132,7 +132,7 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
/// limit access to provenance outside of the `Allocation` abstraction. /// limit access to provenance outside of the `Allocation` abstraction.
/// ///
pub fn range_empty(&self, range: AllocRange, cx: &impl HasDataLayout) -> bool { pub fn range_empty(&self, range: AllocRange, cx: &impl HasDataLayout) -> bool {
self.range_get_ptrs_is_empty(range, cx) && self.range_get_bytes(range).is_empty() self.range_ptrs_is_empty(range, cx) && self.range_bytes_is_empty(range)
} }
/// Yields all the provenances stored in this map. /// Yields all the provenances stored in this map.
@ -164,14 +164,14 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
// provenance that overlaps with the given range. // provenance that overlaps with the given range.
let (first, last) = { let (first, last) = {
// Find all provenance overlapping the given range. // Find all provenance overlapping the given range.
if self.range_get_ptrs_is_empty(range, cx) { if self.range_ptrs_is_empty(range, cx) {
// No provenance in this range, we are done. This is the common case. // No provenance in this range, we are done. This is the common case.
return Ok(()); return Ok(());
} }
// This redoes some of the work of `range_get_ptrs_is_empty`, but this path is much // This redoes some of the work of `range_get_ptrs_is_empty`, but this path is much
// colder than the early return above, so it's worth it. // colder than the early return above, so it's worth it.
let provenance = self.range_get_ptrs(range, cx); let provenance = self.range_ptrs_get(range, cx);
( (
provenance.first().unwrap().0, provenance.first().unwrap().0,
provenance.last().unwrap().0 + cx.data_layout().pointer_size, provenance.last().unwrap().0 + cx.data_layout().pointer_size,
@ -284,8 +284,8 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
// This includes the existing bytewise provenance in the range, and ptr provenance // This includes the existing bytewise provenance in the range, and ptr provenance
// that overlaps with the begin/end of the range. // that overlaps with the begin/end of the range.
let mut dest_bytes_box = None; let mut dest_bytes_box = None;
let begin_overlap = self.range_get_ptrs(alloc_range(src.start, Size::ZERO), cx).first(); let begin_overlap = self.range_ptrs_get(alloc_range(src.start, Size::ZERO), cx).first();
let end_overlap = self.range_get_ptrs(alloc_range(src.end(), Size::ZERO), cx).first(); let end_overlap = self.range_ptrs_get(alloc_range(src.end(), Size::ZERO), cx).first();
if !Prov::OFFSET_IS_ADDR { if !Prov::OFFSET_IS_ADDR {
// There can't be any bytewise provenance, and we cannot split up the begin/end overlap. // There can't be any bytewise provenance, and we cannot split up the begin/end overlap.
if let Some(entry) = begin_overlap { if let Some(entry) = begin_overlap {
@ -308,10 +308,10 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
} else { } else {
trace!("no start overlapping entry"); trace!("no start overlapping entry");
} }
// Then the main part, bytewise provenance from `self.bytes`. // Then the main part, bytewise provenance from `self.bytes`.
if let Some(all_bytes) = self.bytes.as_ref() { bytes.extend(self.range_bytes_get(src));
bytes.extend(all_bytes.range(src.start..src.end()));
}
// And finally possibly parts of a pointer at the end. // And finally possibly parts of a pointer at the end.
if let Some(entry) = end_overlap { if let Some(entry) = end_overlap {
trace!("end overlapping entry: {entry:?}"); trace!("end overlapping entry: {entry:?}");