Skip to content

Commit f5efb68

Browse files
committed
miri: categorize errors into "unsupported" and "UB"
Also slightly refactor pointer bounds checks to avoid creating unnecessary temporary Errors
1 parent c20d7ee commit f5efb68

File tree

15 files changed

+293
-364
lines changed

15 files changed

+293
-364
lines changed

src/librustc/mir/interpret/allocation.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
314314
&self.get_bytes(cx, ptr, size_with_null)?[..size]
315315
}
316316
// This includes the case where `offset` is out-of-bounds to begin with.
317-
None => throw_unsup!(UnterminatedCString(ptr.erase_tag())),
317+
None => throw_ub!(UnterminatedCString(ptr.erase_tag())),
318318
})
319319
}
320320

@@ -573,7 +573,7 @@ impl<'tcx, Tag, Extra> Allocation<Tag, Extra> {
573573
fn check_defined(&self, ptr: Pointer<Tag>, size: Size) -> InterpResult<'tcx> {
574574
self.undef_mask
575575
.is_range_defined(ptr.offset, ptr.offset + size)
576-
.or_else(|idx| throw_unsup!(ReadUndefBytes(idx)))
576+
.or_else(|idx| throw_ub!(InvalidUndefBytes(Some(Pointer::new(ptr.alloc_id, idx)))))
577577
}
578578

579579
pub fn mark_definedness(&mut self, ptr: Pointer<Tag>, size: Size, new_state: bool) {

src/librustc/mir/interpret/error.rs

Lines changed: 113 additions & 182 deletions
Large diffs are not rendered by default.

src/librustc/mir/interpret/mod.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,13 @@ pub struct AllocId(pub u64);
161161

162162
impl fmt::Debug for AllocId {
163163
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
164-
write!(fmt, "alloc{}", self.0)
164+
fmt::Display::fmt(self, fmt)
165+
}
166+
}
167+
168+
impl fmt::Display for AllocId {
169+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
170+
write!(f, "alloc{}", self.0)
165171
}
166172
}
167173

@@ -351,12 +357,6 @@ impl<'s> AllocDecodingSession<'s> {
351357
}
352358
}
353359

354-
impl fmt::Display for AllocId {
355-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
356-
write!(f, "{}", self.0)
357-
}
358-
}
359-
360360
/// An allocation in the global (tcx-managed) memory can be either a function pointer,
361361
/// a static, or a "real" allocation with some data in it.
362362
#[derive(Debug, Clone, Eq, PartialEq, Hash, RustcDecodable, RustcEncodable, HashStable)]

src/librustc/mir/interpret/pointer.rs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -213,20 +213,4 @@ impl<'tcx, Tag> Pointer<Tag> {
213213
pub fn erase_tag(self) -> Pointer {
214214
Pointer { alloc_id: self.alloc_id, offset: self.offset, tag: () }
215215
}
216-
217-
/// Test if the pointer is "inbounds" of an allocation of the given size.
218-
/// A pointer is "inbounds" even if its offset is equal to the size; this is
219-
/// a "one-past-the-end" pointer.
220-
#[inline(always)]
221-
pub fn check_inbounds_alloc(
222-
self,
223-
allocation_size: Size,
224-
msg: CheckInAllocMsg,
225-
) -> InterpResult<'tcx, ()> {
226-
if self.offset > allocation_size {
227-
throw_unsup!(PointerOutOfBounds { ptr: self.erase_tag(), msg, allocation_size })
228-
} else {
229-
Ok(())
230-
}
231-
}
232216
}

src/librustc/mir/interpret/value.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -429,18 +429,19 @@ impl<'tcx, Tag> Scalar<Tag> {
429429
}
430430

431431
pub fn to_bool(self) -> InterpResult<'tcx, bool> {
432-
match self {
433-
Scalar::Raw { data: 0, size: 1 } => Ok(false),
434-
Scalar::Raw { data: 1, size: 1 } => Ok(true),
435-
_ => throw_unsup!(InvalidBool),
432+
let val = self.to_u8()?;
433+
match val {
434+
0 => Ok(false),
435+
1 => Ok(true),
436+
_ => throw_ub!(InvalidBool(val)),
436437
}
437438
}
438439

439440
pub fn to_char(self) -> InterpResult<'tcx, char> {
440441
let val = self.to_u32()?;
441442
match ::std::char::from_u32(val) {
442443
Some(c) => Ok(c),
443-
None => throw_unsup!(InvalidChar(val as u128)),
444+
None => throw_ub!(InvalidChar(val)),
444445
}
445446
}
446447

@@ -583,7 +584,7 @@ impl<'tcx, Tag> ScalarMaybeUndef<Tag> {
583584
pub fn not_undef(self) -> InterpResult<'static, Scalar<Tag>> {
584585
match self {
585586
ScalarMaybeUndef::Scalar(scalar) => Ok(scalar),
586-
ScalarMaybeUndef::Undef => throw_unsup!(ReadUndefBytes(Size::ZERO)),
587+
ScalarMaybeUndef::Undef => throw_ub!(InvalidUndefBytes(None)),
587588
}
588589
}
589590

src/librustc_mir/const_eval/machine.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
240240
Ok(Some(match ecx.load_mir(instance.def, None) {
241241
Ok(body) => *body,
242242
Err(err) => {
243-
if let err_unsup!(NoMirFor(ref path)) = err.kind {
243+
if let err_unsup!(NoMirFor(did)) = err.kind {
244+
let path = ecx.tcx.def_path_str(did);
244245
return Err(ConstEvalErrKind::NeedsRfc(format!(
245246
"calling extern function `{}`",
246247
path

src/librustc_mir/interpret/eval_context.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ pub enum LocalValue<Tag = (), Id = AllocId> {
138138
impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> {
139139
pub fn access(&self) -> InterpResult<'tcx, Operand<Tag>> {
140140
match self.value {
141-
LocalValue::Dead => throw_unsup!(DeadLocal),
141+
LocalValue::Dead => throw_ub!(DeadLocal),
142142
LocalValue::Uninitialized => {
143143
bug!("The type checker should prevent reading from a never-written local")
144144
}
@@ -152,7 +152,7 @@ impl<'tcx, Tag: Copy + 'static> LocalState<'tcx, Tag> {
152152
&mut self,
153153
) -> InterpResult<'tcx, Result<&mut LocalValue<Tag>, MemPlace<Tag>>> {
154154
match self.value {
155-
LocalValue::Dead => throw_unsup!(DeadLocal),
155+
LocalValue::Dead => throw_ub!(DeadLocal),
156156
LocalValue::Live(Operand::Indirect(mplace)) => Ok(Err(mplace)),
157157
ref mut local @ LocalValue::Live(Operand::Immediate(_))
158158
| ref mut local @ LocalValue::Uninitialized => Ok(Ok(local)),
@@ -326,7 +326,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
326326
if self.tcx.is_mir_available(did) {
327327
Ok(self.tcx.optimized_mir(did).unwrap_read_only())
328328
} else {
329-
throw_unsup!(NoMirFor(self.tcx.def_path_str(def_id)))
329+
throw_unsup!(NoMirFor(def_id))
330330
}
331331
}
332332
_ => Ok(self.tcx.instance_mir(instance)),

src/librustc_mir/interpret/intern.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
327327
if let Err(error) = interned {
328328
// This can happen when e.g. the tag of an enum is not a valid discriminant. We do have
329329
// to read enum discriminants in order to find references in enum variant fields.
330-
if let err_unsup!(ValidationFailure(_)) = error.kind {
330+
if let err_ub!(ValidationFailure(_)) = error.kind {
331331
let err = crate::const_eval::error_to_const_error(&ecx, error);
332332
match err.struct_error(
333333
ecx.tcx,
@@ -390,7 +390,7 @@ pub fn intern_const_alloc_recursive<M: CompileTimeMachine<'mir, 'tcx>>(
390390
}
391391
} else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) {
392392
// dangling pointer
393-
throw_unsup!(ValidationFailure("encountered dangling pointer in final constant".into()))
393+
throw_ub_format!("encountered dangling pointer in final constant")
394394
} else if ecx.tcx.alloc_map.lock().get(alloc_id).is_none() {
395395
// We have hit an `AllocId` that is neither in local or global memory and isn't marked
396396
// as dangling by local memory.

src/librustc_mir/interpret/intrinsics.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
134134
let bits = self.force_bits(val, layout_of.size)?;
135135
let kind = match layout_of.abi {
136136
ty::layout::Abi::Scalar(ref scalar) => scalar.value,
137-
_ => throw_unsup!(TypeNotPrimitive(ty)),
137+
_ => bug!("{} called on invalid type {:?}", intrinsic_name, ty),
138138
};
139139
let (nonzero, intrinsic_name) = match intrinsic_name {
140140
sym::cttz_nonzero => (true, sym::cttz),

src/librustc_mir/interpret/machine.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
281281
int: u64,
282282
) -> InterpResult<'tcx, Pointer<Self::PointerTag>> {
283283
Err((if int == 0 {
284-
err_unsup!(InvalidNullPointerUsage)
284+
err_ub!(InvalidNullPointerUsage)
285285
} else {
286286
err_unsup!(ReadBytesAsPointer)
287287
})

0 commit comments

Comments
 (0)