Skip to content

Commit 0ff05c4

Browse files
committed
Auto merge of #1219 - RalfJung:error-cleanup, r=RalfJung
rustup for error reform This is the Miri side of rust-lang/rust#69839.
2 parents 6b56aef + 49051e0 commit 0ff05c4

File tree

77 files changed

+185
-207
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+185
-207
lines changed

rust-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
660326e9791d5caf3186b14521498c2584a494ab
1+
57e1da59cd0761330b4ea8d47b16340a78eeafa9

src/helpers.rs

+44-36
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use crate::*;
1818
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
1919

2020
/// Gets an instance for a path.
21-
fn resolve_did<'mir, 'tcx>(tcx: TyCtxt<'tcx>, path: &[&str]) -> InterpResult<'tcx, DefId> {
21+
fn try_resolve_did<'mir, 'tcx>(tcx: TyCtxt<'tcx>, path: &[&str]) -> Option<DefId> {
2222
tcx.crates()
2323
.iter()
2424
.find(|&&krate| tcx.original_crate_name(krate).as_str() == path[0])
@@ -41,19 +41,47 @@ fn resolve_did<'mir, 'tcx>(tcx: TyCtxt<'tcx>, path: &[&str]) -> InterpResult<'tc
4141
}
4242
None
4343
})
44-
.ok_or_else(|| {
45-
let path = path.iter().map(|&s| s.to_owned()).collect();
46-
err_unsup!(PathNotFound(path)).into()
47-
})
4844
}
4945

5046
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
5147
/// Gets an instance for a path.
52-
fn resolve_path(&self, path: &[&str]) -> InterpResult<'tcx, ty::Instance<'tcx>> {
53-
Ok(ty::Instance::mono(
54-
self.eval_context_ref().tcx.tcx,
55-
resolve_did(self.eval_context_ref().tcx.tcx, path)?,
56-
))
48+
fn resolve_path(&self, path: &[&str]) -> ty::Instance<'tcx> {
49+
let did = try_resolve_did(self.eval_context_ref().tcx.tcx, path)
50+
.unwrap_or_else(|| panic!("failed to find required Rust item: {:?}", path));
51+
ty::Instance::mono(self.eval_context_ref().tcx.tcx, did)
52+
}
53+
54+
/// Evaluates the scalar at the specified path. Returns Some(val)
55+
/// if the path could be resolved, and None otherwise
56+
fn eval_path_scalar(
57+
&mut self,
58+
path: &[&str],
59+
) -> InterpResult<'tcx, ScalarMaybeUndef<Tag>> {
60+
let this = self.eval_context_mut();
61+
let instance = this.resolve_path(path);
62+
let cid = GlobalId { instance, promoted: None };
63+
let const_val = this.const_eval_raw(cid)?;
64+
let const_val = this.read_scalar(const_val.into())?;
65+
return Ok(const_val);
66+
}
67+
68+
/// Helper function to get a `libc` constant as a `Scalar`.
69+
fn eval_libc(&mut self, name: &str) -> InterpResult<'tcx, Scalar<Tag>> {
70+
self.eval_context_mut()
71+
.eval_path_scalar(&["libc", name])?
72+
.not_undef()
73+
}
74+
75+
/// Helper function to get a `libc` constant as an `i32`.
76+
fn eval_libc_i32(&mut self, name: &str) -> InterpResult<'tcx, i32> {
77+
self.eval_libc(name)?.to_i32()
78+
}
79+
80+
/// Helper function to get the `TyLayout` of a `libc` type
81+
fn libc_ty_layout(&mut self, name: &str) -> InterpResult<'tcx, TyLayout<'tcx>> {
82+
let this = self.eval_context_mut();
83+
let ty = this.resolve_path(&["libc", name]).monomorphic_ty(*this.tcx);
84+
this.layout_of(ty)
5785
}
5886

5987
/// Write a 0 of the appropriate size to `dest`.
@@ -98,7 +126,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
98126
if this.machine.communicate {
99127
// Fill the buffer using the host's rng.
100128
getrandom::getrandom(&mut data)
101-
.map_err(|err| err_unsup_format!("getrandom failed: {}", err))?;
129+
.map_err(|err| err_unsup_format!("host getrandom failed: {}", err))?;
102130
} else {
103131
let rng = this.memory.extra.rng.get_mut();
104132
rng.fill_bytes(&mut data);
@@ -313,26 +341,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
313341
}
314342
}
315343

316-
/// Helper function to get a `libc` constant as a `Scalar`.
317-
fn eval_libc(&mut self, name: &str) -> InterpResult<'tcx, Scalar<Tag>> {
318-
self.eval_context_mut()
319-
.eval_path_scalar(&["libc", name])?
320-
.ok_or_else(|| err_unsup_format!("Path libc::{} cannot be resolved.", name))?
321-
.not_undef()
322-
}
323-
324-
/// Helper function to get a `libc` constant as an `i32`.
325-
fn eval_libc_i32(&mut self, name: &str) -> InterpResult<'tcx, i32> {
326-
self.eval_libc(name)?.to_i32()
327-
}
328-
329-
/// Helper function to get the `TyLayout` of a `libc` type
330-
fn libc_ty_layout(&mut self, name: &str) -> InterpResult<'tcx, TyLayout<'tcx>> {
331-
let this = self.eval_context_mut();
332-
let ty = this.resolve_path(&["libc", name])?.monomorphic_ty(*this.tcx);
333-
this.layout_of(ty)
334-
}
335-
336344
// Writes several `ImmTy`s contiguosly into memory. This is useful when you have to pack
337345
// different values into a struct.
338346
fn write_packed_immediates(
@@ -360,7 +368,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
360368
fn check_no_isolation(&self, name: &str) -> InterpResult<'tcx> {
361369
if !self.eval_context_ref().machine.communicate {
362370
throw_unsup_format!(
363-
"`{}` not available when isolation is enabled. Pass the flag `-Zmiri-disable-isolation` to disable it.",
371+
"`{}` not available when isolation is enabled (pass the flag `-Zmiri-disable-isolation` to disable isolation)",
364372
name,
365373
)
366374
}
@@ -416,13 +424,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
416424
AlreadyExists => "EEXIST",
417425
WouldBlock => "EWOULDBLOCK",
418426
_ => {
419-
throw_unsup_format!("The {} error cannot be transformed into a raw os error", e)
427+
throw_unsup_format!("io error {} cannot be transformed into a raw os error", e)
420428
}
421429
})?
422430
} else {
423431
// FIXME: we have to implement the Windows equivalent of this.
424432
throw_unsup_format!(
425-
"Setting the last OS error from an io::Error is unsupported for {}.",
433+
"setting the last OS error from an io::Error is unsupported for {}.",
426434
target.target_os
427435
)
428436
};
@@ -531,7 +539,7 @@ pub fn immty_from_int_checked<'tcx>(
531539
) -> InterpResult<'tcx, ImmTy<'tcx, Tag>> {
532540
let int = int.into();
533541
Ok(ImmTy::try_from_int(int, layout).ok_or_else(|| {
534-
err_unsup_format!("Signed value {:#x} does not fit in {} bits", int, layout.size.bits())
542+
err_unsup_format!("signed value {:#x} does not fit in {} bits", int, layout.size.bits())
535543
})?)
536544
}
537545

@@ -541,6 +549,6 @@ pub fn immty_from_uint_checked<'tcx>(
541549
) -> InterpResult<'tcx, ImmTy<'tcx, Tag>> {
542550
let int = int.into();
543551
Ok(ImmTy::try_from_uint(int, layout).ok_or_else(|| {
544-
err_unsup_format!("Signed value {:#x} does not fit in {} bits", int, layout.size.bits())
552+
err_unsup_format!("unsigned value {:#x} does not fit in {} bits", int, layout.size.bits())
545553
})?)
546554
}

src/intptrcast.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,6 @@ impl<'mir, 'tcx> GlobalState {
4343
int: u64,
4444
memory: &Memory<'mir, 'tcx, Evaluator<'tcx>>,
4545
) -> InterpResult<'tcx, Pointer<Tag>> {
46-
if int == 0 {
47-
throw_unsup!(InvalidNullPointerUsage);
48-
}
49-
5046
let global_state = memory.extra.intptrcast.borrow();
5147
let pos = global_state.int_to_ptr_map.binary_search_by_key(&int, |(addr, _)| *addr);
5248

@@ -57,7 +53,7 @@ impl<'mir, 'tcx> GlobalState {
5753
// zero. The pointer is untagged because it was created from a cast
5854
Pointer::new_with_tag(alloc_id, Size::from_bytes(0), Tag::Untagged)
5955
}
60-
Err(0) => throw_unsup!(DanglingPointerDeref),
56+
Err(0) => throw_ub!(InvalidIntPointerUsage(int)),
6157
Err(pos) => {
6258
// This is the largest of the adresses smaller than `int`,
6359
// i.e. the greatest lower bound (glb)
@@ -69,7 +65,7 @@ impl<'mir, 'tcx> GlobalState {
6965
// This pointer is untagged because it was created from a cast
7066
Pointer::new_with_tag(alloc_id, Size::from_bytes(offset), Tag::Untagged)
7167
} else {
72-
throw_unsup!(DanglingPointerDeref)
68+
throw_ub!(InvalidIntPointerUsage(int))
7369
}
7470
}
7571
})

src/shims/dlsym.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ impl Dlsym {
1515
Ok(match name {
1616
"getentropy" => Some(GetEntropy),
1717
"__pthread_get_minstack" => None,
18-
_ => throw_unsup_format!("Unsupported dlsym: {}", name),
18+
_ => throw_unsup_format!("unsupported dlsym: {}", name),
1919
})
2020
}
2121
}

src/shims/foreign_items.rs

+16-39
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
165165
.expect("No panic runtime found!");
166166
let panic_runtime = tcx.crate_name(*panic_runtime);
167167
let start_panic_instance =
168-
this.resolve_path(&[&*panic_runtime.as_str(), link_name])?;
168+
this.resolve_path(&[&*panic_runtime.as_str(), link_name]);
169169
return Ok(Some(&*this.load_mir(start_panic_instance.def, None)?));
170170
}
171171
_ => {}
@@ -222,12 +222,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
222222
"__rust_alloc" => {
223223
let size = this.read_scalar(args[0])?.to_machine_usize(this)?;
224224
let align = this.read_scalar(args[1])?.to_machine_usize(this)?;
225-
if size == 0 {
226-
throw_unsup!(HeapAllocZeroBytes);
227-
}
228-
if !align.is_power_of_two() {
229-
throw_unsup!(HeapAllocNonPowerOfTwoAlignment(align));
230-
}
225+
Self::check_alloc_request(size, align)?;
231226
let ptr = this.memory.allocate(
232227
Size::from_bytes(size),
233228
Align::from_bytes(align).unwrap(),
@@ -238,12 +233,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
238233
"__rust_alloc_zeroed" => {
239234
let size = this.read_scalar(args[0])?.to_machine_usize(this)?;
240235
let align = this.read_scalar(args[1])?.to_machine_usize(this)?;
241-
if size == 0 {
242-
throw_unsup!(HeapAllocZeroBytes);
243-
}
244-
if !align.is_power_of_two() {
245-
throw_unsup!(HeapAllocNonPowerOfTwoAlignment(align));
246-
}
236+
Self::check_alloc_request(size, align)?;
247237
let ptr = this.memory.allocate(
248238
Size::from_bytes(size),
249239
Align::from_bytes(align).unwrap(),
@@ -257,12 +247,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
257247
let ptr = this.read_scalar(args[0])?.not_undef()?;
258248
let old_size = this.read_scalar(args[1])?.to_machine_usize(this)?;
259249
let align = this.read_scalar(args[2])?.to_machine_usize(this)?;
260-
if old_size == 0 {
261-
throw_unsup!(HeapAllocZeroBytes);
262-
}
263-
if !align.is_power_of_two() {
264-
throw_unsup!(HeapAllocNonPowerOfTwoAlignment(align));
265-
}
250+
// No need to check old_size/align; we anyway check that they match the allocation.
266251
let ptr = this.force_ptr(ptr)?;
267252
this.memory.deallocate(
268253
ptr,
@@ -274,12 +259,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
274259
let old_size = this.read_scalar(args[1])?.to_machine_usize(this)?;
275260
let align = this.read_scalar(args[2])?.to_machine_usize(this)?;
276261
let new_size = this.read_scalar(args[3])?.to_machine_usize(this)?;
277-
if old_size == 0 || new_size == 0 {
278-
throw_unsup!(HeapAllocZeroBytes);
279-
}
280-
if !align.is_power_of_two() {
281-
throw_unsup!(HeapAllocNonPowerOfTwoAlignment(align));
282-
}
262+
Self::check_alloc_request(new_size, align)?;
263+
// No need to check old_size; we anyway check that they match the allocation.
283264
let ptr = this.force_ptr(this.read_scalar(args[0])?.not_undef()?)?;
284265
let align = Align::from_bytes(align).unwrap();
285266
let new_ptr = this.memory.reallocate(
@@ -455,26 +436,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
455436
_ => match this.tcx.sess.target.target.target_os.as_str() {
456437
"linux" | "macos" => return posix::EvalContextExt::emulate_foreign_item_by_name(this, link_name, args, dest, ret),
457438
"windows" => return windows::EvalContextExt::emulate_foreign_item_by_name(this, link_name, args, dest, ret),
458-
target => throw_unsup_format!("The {} target platform is not supported", target),
439+
target => throw_unsup_format!("the {} target platform is not supported", target),
459440
}
460441
};
461442

462443
Ok(true)
463444
}
464445

465-
/// Evaluates the scalar at the specified path. Returns Some(val)
466-
/// if the path could be resolved, and None otherwise
467-
fn eval_path_scalar(
468-
&mut self,
469-
path: &[&str],
470-
) -> InterpResult<'tcx, Option<ScalarMaybeUndef<Tag>>> {
471-
let this = self.eval_context_mut();
472-
if let Ok(instance) = this.resolve_path(path) {
473-
let cid = GlobalId { instance, promoted: None };
474-
let const_val = this.const_eval_raw(cid)?;
475-
let const_val = this.read_scalar(const_val.into())?;
476-
return Ok(Some(const_val));
446+
/// Check some basic requirements for this allocation request:
447+
/// non-zero size, power-of-two alignment.
448+
fn check_alloc_request(size: u64, align: u64) -> InterpResult<'tcx> {
449+
if size == 0 {
450+
throw_ub_format!("creating allocation with size 0");
451+
}
452+
if !align.is_power_of_two() {
453+
throw_ub_format!("creating allocation with non-power-of-two alignment {}", align);
477454
}
478-
return Ok(None);
455+
Ok(())
479456
}
480457
}

src/shims/foreign_items/posix.rs

+13-23
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
138138
let size = this.read_scalar(args[2])?.to_machine_usize(this)?;
139139
// Align must be power of 2, and also at least ptr-sized (POSIX rules).
140140
if !align.is_power_of_two() {
141-
throw_unsup!(HeapAllocNonPowerOfTwoAlignment(align));
141+
throw_ub_format!("posix_memalign: alignment must be a power of two, but is {}", align);
142142
}
143143
if align < this.pointer_size().bytes() {
144144
throw_ub_format!(
@@ -185,7 +185,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
185185
};
186186

187187
// Figure out how large a pthread TLS key actually is.
188-
// This is `libc::pthread_key_t`.
188+
// To this end, deref the argument type. This is `libc::pthread_key_t`.
189189
let key_type = args[0].layout.ty
190190
.builtin_deref(true)
191191
.ok_or_else(|| err_ub_format!(
@@ -195,12 +195,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
195195
let key_layout = this.layout_of(key_type)?;
196196

197197
// Create key and write it into the memory where `key_ptr` wants it.
198-
let key = this.machine.tls.create_tls_key(dtor) as u128;
199-
if key_layout.size.bits() < 128 && key >= (1u128 << key_layout.size.bits() as u128)
200-
{
201-
throw_unsup!(OutOfTls);
202-
}
203-
198+
let key = this.machine.tls.create_tls_key(dtor, key_layout.size)?;
204199
this.write_scalar(Scalar::from_uint(key, key_layout.size), key_place.into())?;
205200

206201
// Return success (`0`).
@@ -294,28 +289,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
294289

295290
trace!("sysconf() called with name {}", name);
296291
// TODO: Cache the sysconf integers via Miri's global cache.
297-
let paths = &[
298-
(&["libc", "_SC_PAGESIZE"], Scalar::from_int(PAGE_SIZE, dest.layout.size)),
299-
(&["libc", "_SC_GETPW_R_SIZE_MAX"], Scalar::from_int(-1, dest.layout.size)),
300-
(
301-
&["libc", "_SC_NPROCESSORS_ONLN"],
302-
Scalar::from_int(NUM_CPUS, dest.layout.size),
303-
),
292+
let sysconfs = &[
293+
("_SC_PAGESIZE", Scalar::from_int(PAGE_SIZE, dest.layout.size)),
294+
("_SC_GETPW_R_SIZE_MAX", Scalar::from_int(-1, dest.layout.size)),
295+
("_SC_NPROCESSORS_ONLN", Scalar::from_int(NUM_CPUS, dest.layout.size)),
304296
];
305297
let mut result = None;
306-
for &(path, path_value) in paths {
307-
if let Some(val) = this.eval_path_scalar(path)? {
308-
let val = val.to_i32()?;
309-
if val == name {
310-
result = Some(path_value);
311-
break;
312-
}
298+
for &(sysconf_name, value) in sysconfs {
299+
let sysconf_name = this.eval_libc_i32(sysconf_name)?;
300+
if sysconf_name == name {
301+
result = Some(value);
302+
break;
313303
}
314304
}
315305
if let Some(result) = result {
316306
this.write_scalar(result, dest)?;
317307
} else {
318-
throw_unsup_format!("Unimplemented sysconf name: {}", name)
308+
throw_unsup_format!("unimplemented sysconf name: {}", name)
319309
}
320310
}
321311

src/shims/foreign_items/posix/linux.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
5656

5757
"syscall" => {
5858
let sys_getrandom = this
59-
.eval_path_scalar(&["libc", "SYS_getrandom"])?
60-
.expect("Failed to get libc::SYS_getrandom")
59+
.eval_libc("SYS_getrandom")?
6160
.to_machine_usize(this)?;
6261

6362
let sys_statx = this
64-
.eval_path_scalar(&["libc", "SYS_statx"])?
65-
.expect("Failed to get libc::SYS_statx")
63+
.eval_libc("SYS_statx")?
6664
.to_machine_usize(this)?;
6765

6866
match this.read_scalar(args[0])?.to_machine_usize(this)? {

src/shims/foreign_items/windows.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -154,14 +154,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
154154
// This just creates a key; Windows does not natively support TLS destructors.
155155

156156
// Create key and return it.
157-
let key = this.machine.tls.create_tls_key(None) as u128;
158-
159-
// Figure out how large a TLS key actually is. This is `c::DWORD`.
160-
if dest.layout.size.bits() < 128
161-
&& key >= (1u128 << dest.layout.size.bits() as u128)
162-
{
163-
throw_unsup!(OutOfTls);
164-
}
157+
let key = this.machine.tls.create_tls_key(None, dest.layout.size)?;
165158
this.write_scalar(Scalar::from_uint(key, dest.layout.size), dest)?;
166159
}
167160
"TlsGetValue" => {

0 commit comments

Comments
 (0)