Skip to content

Commit 831141a

Browse files
committed
Move some functions around to keep order in sync with memory.rs
1 parent 5217e4c commit 831141a

File tree

1 file changed

+72
-72
lines changed

1 file changed

+72
-72
lines changed

src/librustc/mir/interpret/allocation.rs

Lines changed: 72 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,78 @@ impl<Tag, Extra: Default> Allocation<Tag, Extra> {
111111

112112
impl<'tcx> ::serialize::UseSpecializedDecodable for &'tcx Allocation {}
113113

114+
/// Various correctness checks for `Pointer`s
115+
impl<'tcx, Tag: Copy, Extra> Allocation<Tag, Extra> {
116+
/// Check that the pointer is aligned AND non-NULL. This supports ZSTs in two ways:
117+
/// You can pass a scalar, and a `Pointer` does not have to actually still be allocated.
118+
pub fn check_align(
119+
&self,
120+
ptr: Pointer<Tag>,
121+
required_align: Align
122+
) -> EvalResult<'tcx> {
123+
// Check non-NULL/Undef, extract offset
124+
125+
// check this is not NULL -- which we can ensure only if this is in-bounds
126+
let size = Size::from_bytes(self.bytes.len() as u64);
127+
if ptr.offset > size {
128+
return err!(PointerOutOfBounds {
129+
ptr: ptr.erase_tag(),
130+
access: true,
131+
allocation_size: size,
132+
});
133+
};
134+
// Check alignment
135+
if self.align.abi() < required_align.abi() {
136+
return err!(AlignmentCheckFailed {
137+
has: self.align,
138+
required: required_align,
139+
});
140+
}
141+
let offset = ptr.offset.bytes();
142+
if offset % required_align.abi() == 0 {
143+
Ok(())
144+
} else {
145+
let has = offset % required_align.abi();
146+
err!(AlignmentCheckFailed {
147+
has: Align::from_bytes(has, has).unwrap(),
148+
required: required_align,
149+
})
150+
}
151+
}
152+
153+
/// Check if the pointer is "in-bounds". Notice that a pointer pointing at the end
154+
/// of an allocation (i.e., at the first *inaccessible* location) *is* considered
155+
/// in-bounds! This follows C's/LLVM's rules. The `access` boolean is just used
156+
/// for the error message.
157+
/// If you want to check bounds before doing a memory access, be sure to
158+
/// check the pointer one past the end of your access, then everything will
159+
/// work out exactly.
160+
pub fn check_bounds_ptr(&self, ptr: Pointer<Tag>, access: bool) -> EvalResult<'tcx> {
161+
let allocation_size = self.bytes.len() as u64;
162+
if ptr.offset.bytes() > allocation_size {
163+
return err!(PointerOutOfBounds {
164+
ptr: ptr.erase_tag(),
165+
access,
166+
allocation_size: Size::from_bytes(allocation_size),
167+
});
168+
}
169+
Ok(())
170+
}
171+
172+
/// Check if the memory range beginning at `ptr` and of size `Size` is "in-bounds".
173+
#[inline(always)]
174+
pub fn check_bounds(
175+
&self,
176+
cx: impl HasDataLayout,
177+
ptr: Pointer<Tag>,
178+
size: Size,
179+
access: bool
180+
) -> EvalResult<'tcx> {
181+
// if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
182+
self.check_bounds_ptr(ptr.offset(size, cx)?, access)
183+
}
184+
}
185+
114186
/// Byte accessors
115187
impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
116188
/// The last argument controls whether we error out when there are undefined
@@ -527,78 +599,6 @@ impl<'tcx, Tag: Copy, Extra> Allocation<Tag, Extra> {
527599
}
528600
}
529601

530-
impl<'tcx, Tag: Copy, Extra> Allocation<Tag, Extra> {
531-
/// Check that the pointer is aligned AND non-NULL. This supports ZSTs in two ways:
532-
/// You can pass a scalar, and a `Pointer` does not have to actually still be allocated.
533-
pub fn check_align(
534-
&self,
535-
ptr: Pointer<Tag>,
536-
required_align: Align
537-
) -> EvalResult<'tcx> {
538-
// Check non-NULL/Undef, extract offset
539-
540-
// check this is not NULL -- which we can ensure only if this is in-bounds
541-
let size = Size::from_bytes(self.bytes.len() as u64);
542-
if ptr.offset > size {
543-
return err!(PointerOutOfBounds {
544-
ptr: ptr.erase_tag(),
545-
access: true,
546-
allocation_size: size,
547-
});
548-
};
549-
// Check alignment
550-
if self.align.abi() < required_align.abi() {
551-
return err!(AlignmentCheckFailed {
552-
has: self.align,
553-
required: required_align,
554-
});
555-
}
556-
let offset = ptr.offset.bytes();
557-
if offset % required_align.abi() == 0 {
558-
Ok(())
559-
} else {
560-
let has = offset % required_align.abi();
561-
err!(AlignmentCheckFailed {
562-
has: Align::from_bytes(has, has).unwrap(),
563-
required: required_align,
564-
})
565-
}
566-
}
567-
568-
/// Check if the pointer is "in-bounds". Notice that a pointer pointing at the end
569-
/// of an allocation (i.e., at the first *inaccessible* location) *is* considered
570-
/// in-bounds! This follows C's/LLVM's rules. The `access` boolean is just used
571-
/// for the error message.
572-
/// If you want to check bounds before doing a memory access, be sure to
573-
/// check the pointer one past the end of your access, then everything will
574-
/// work out exactly.
575-
pub fn check_bounds_ptr(&self, ptr: Pointer<Tag>, access: bool) -> EvalResult<'tcx> {
576-
let allocation_size = self.bytes.len() as u64;
577-
if ptr.offset.bytes() > allocation_size {
578-
return err!(PointerOutOfBounds {
579-
ptr: ptr.erase_tag(),
580-
access,
581-
allocation_size: Size::from_bytes(allocation_size),
582-
});
583-
}
584-
Ok(())
585-
}
586-
587-
/// Check if the memory range beginning at `ptr` and of size `Size` is "in-bounds".
588-
#[inline(always)]
589-
pub fn check_bounds(
590-
&self,
591-
cx: impl HasDataLayout,
592-
ptr: Pointer<Tag>,
593-
size: Size,
594-
access: bool
595-
) -> EvalResult<'tcx> {
596-
// if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
597-
self.check_bounds_ptr(ptr.offset(size, cx)?, access)
598-
}
599-
}
600-
601-
602602
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
603603
pub struct Relocations<Tag=(), Id=AllocId>(SortedMap<Size, (Tag, Id)>);
604604

0 commit comments

Comments
 (0)