Skip to content

Commit 32e93ed

Browse files
committed
Update to Memory -> Allocation method move
1 parent 68ba6cd commit 32e93ed

File tree

4 files changed

+58
-31
lines changed

4 files changed

+58
-31
lines changed

src/fn_call.rs

+25-15
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
114114
None => self.tcx.item_name(def_id).as_str(),
115115
};
116116

117+
let tcx = &{self.tcx.tcx};
118+
117119
// All these functions take raw pointers, so if we access memory directly
118120
// (as opposed to through a place), we have to remember to erase any tag
119121
// that might still hang around!
@@ -175,7 +177,9 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
175177
MiriMemoryKind::Rust.into()
176178
)?
177179
.with_default_tag();
178-
self.memory_mut().write_repeat(ptr.into(), 0, Size::from_bytes(size))?;
180+
self.memory_mut()
181+
.get_mut(ptr.alloc_id)?
182+
.write_repeat(tcx, ptr, 0, Size::from_bytes(size))?;
179183
self.write_scalar(Scalar::Ptr(ptr), dest)?;
180184
}
181185
"__rust_dealloc" => {
@@ -239,7 +243,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
239243
"dlsym" => {
240244
let _handle = self.read_scalar(args[0])?;
241245
let symbol = self.read_scalar(args[1])?.to_ptr()?;
242-
let symbol_name = self.memory().read_c_str(symbol)?;
246+
let symbol_name = self.memory().get(symbol.alloc_id)?.read_c_str(tcx, symbol)?;
243247
let err = format!("bad c unicode symbol: {:?}", symbol_name);
244248
let symbol_name = ::std::str::from_utf8(symbol_name).unwrap_or(&err);
245249
return err!(Unimplemented(format!(
@@ -346,7 +350,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
346350
"getenv" => {
347351
let result = {
348352
let name_ptr = self.read_scalar(args[0])?.to_ptr()?;
349-
let name = self.memory().read_c_str(name_ptr)?;
353+
let name = self.memory().get(name_ptr.alloc_id)?.read_c_str(tcx, name_ptr)?;
350354
match self.machine.env_vars.get(name) {
351355
Some(&var) => Scalar::Ptr(var),
352356
None => Scalar::ptr_null(&*self.tcx),
@@ -360,8 +364,8 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
360364
{
361365
let name_ptr = self.read_scalar(args[0])?.not_undef()?;
362366
if !name_ptr.is_null_ptr(self) {
363-
let name = self.memory().read_c_str(name_ptr.to_ptr()?
364-
)?.to_owned();
367+
let name_ptr = name_ptr.to_ptr()?;
368+
let name = self.memory().get(name_ptr.alloc_id)?.read_c_str(tcx, name_ptr)?.to_owned();
365369
if !name.is_empty() && !name.contains(&b'=') {
366370
success = Some(self.machine.env_vars.remove(&name));
367371
}
@@ -382,9 +386,10 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
382386
{
383387
let name_ptr = self.read_scalar(args[0])?.not_undef()?;
384388
let value_ptr = self.read_scalar(args[1])?.to_ptr()?;
385-
let value = self.memory().read_c_str(value_ptr)?;
389+
let value = self.memory().get(value_ptr.alloc_id)?.read_c_str(tcx, value_ptr)?;
386390
if !name_ptr.is_null_ptr(self) {
387-
let name = self.memory().read_c_str(name_ptr.to_ptr()?)?;
391+
let name_ptr = name_ptr.to_ptr()?;
392+
let name = self.memory().get(name_ptr.alloc_id)?.read_c_str(tcx, name_ptr)?;
388393
if !name.is_empty() && !name.contains(&b'=') {
389394
new = Some((name.to_owned(), value.to_owned()));
390395
}
@@ -397,9 +402,12 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
397402
Align::from_bytes(1).unwrap(),
398403
MiriMemoryKind::Env.into(),
399404
)?.with_default_tag();
400-
self.memory_mut().write_bytes(value_copy.into(), &value)?;
401-
let trailing_zero_ptr = value_copy.offset(Size::from_bytes(value.len() as u64), self)?.into();
402-
self.memory_mut().write_bytes(trailing_zero_ptr, &[0])?;
405+
{
406+
let alloc = self.memory_mut().get_mut(value_copy.alloc_id)?;
407+
alloc.write_bytes(tcx, value_copy, &value)?;
408+
let trailing_zero_ptr = value_copy.offset(Size::from_bytes(value.len() as u64), tcx)?;
409+
alloc.write_bytes(tcx, trailing_zero_ptr, &[0])?;
410+
}
403411
if let Some(var) = self.machine.env_vars.insert(
404412
name.to_owned(),
405413
value_copy,
@@ -444,7 +452,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
444452

445453
"strlen" => {
446454
let ptr = self.read_scalar(args[0])?.to_ptr()?;
447-
let n = self.memory().read_c_str(ptr)?.len();
455+
let n = self.memory().get(ptr.alloc_id)?.read_c_str(tcx, ptr)?.len();
448456
self.write_scalar(Scalar::from_uint(n as u64, dest.layout.size), dest)?;
449457
}
450458

@@ -507,13 +515,15 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
507515
let key_layout = self.layout_of(key_type)?;
508516

509517
// Create key and write it into the memory where key_ptr wants it
510-
let key = self.machine.tls.create_tls_key(dtor, &*self.tcx) as u128;
518+
let key = self.machine.tls.create_tls_key(dtor, tcx) as u128;
511519
if key_layout.size.bits() < 128 && key >= (1u128 << key_layout.size.bits() as u128) {
512520
return err!(OutOfTls);
513521
}
514-
self.memory_mut().write_scalar(
522+
523+
self.memory().check_align(key_ptr.into(), key_layout.align.abi)?;
524+
self.memory_mut().get_mut(key_ptr.alloc_id)?.write_scalar(
525+
tcx,
515526
key_ptr,
516-
key_layout.align.abi,
517527
Scalar::from_uint(key, key_layout.size).into(),
518528
key_layout.size,
519529
)?;
@@ -610,7 +620,7 @@ impl<'a, 'mir, 'tcx: 'mir + 'a> EvalContextExt<'tcx, 'mir> for super::MiriEvalCo
610620
// This just creates a key; Windows does not natively support TLS dtors.
611621

612622
// Create key and return it
613-
let key = self.machine.tls.create_tls_key(None, &*self.tcx) as u128;
623+
let key = self.machine.tls.create_tls_key(None, tcx) as u128;
614624

615625
// Figure out how large a TLS key actually is. This is c::DWORD.
616626
if dest.layout.size.bits() < 128 && key >= (1u128 << dest.layout.size.bits() as u128) {

src/intrinsic.rs

+17-4
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
2828
if self.emulate_intrinsic(instance, args, dest)? {
2929
return Ok(());
3030
}
31-
31+
let tcx = &{self.tcx.tcx};
3232
let substs = instance.substs;
3333

3434
// All these intrinsics take raw pointers, so if we access memory directly
@@ -248,6 +248,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
248248
// FIXME: We do not properly validate in case of ZSTs and when doing it in memory!
249249
// However, this only affects direct calls of the intrinsic; calls to the stable
250250
// functions wrapping them do get their validation.
251+
// FIXME: should we check that the destination pointer is aligned even for ZSTs?
251252
if !dest.layout.is_zst() { // nothing to do for ZST
252253
match dest.layout.abi {
253254
layout::Abi::Scalar(ref s) => {
@@ -263,7 +264,9 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
263264
// Do it in memory
264265
let mplace = self.force_allocation(dest)?;
265266
assert!(mplace.meta.is_none());
266-
self.memory_mut().write_repeat(mplace.ptr, 0, dest.layout.size)?;
267+
// not a zst, must be valid pointer
268+
let ptr = mplace.ptr.to_ptr()?;
269+
self.memory_mut().get_mut(ptr.alloc_id)?.write_repeat(tcx, ptr, 0, dest.layout.size)?;
267270
}
268271
}
269272
}
@@ -412,6 +415,7 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
412415
// FIXME: We do not properly validate in case of ZSTs and when doing it in memory!
413416
// However, this only affects direct calls of the intrinsic; calls to the stable
414417
// functions wrapping them do get their validation.
418+
// FIXME: should we check alignment for ZSTs?
415419
if !dest.layout.is_zst() { // nothing to do for ZST
416420
match dest.layout.abi {
417421
layout::Abi::Scalar(..) => {
@@ -426,7 +430,10 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
426430
// Do it in memory
427431
let mplace = self.force_allocation(dest)?;
428432
assert!(mplace.meta.is_none());
429-
self.memory_mut().mark_definedness(mplace.ptr.to_ptr()?, dest.layout.size, false)?;
433+
let ptr = mplace.ptr.to_ptr()?;
434+
self.memory_mut()
435+
.get_mut(ptr.alloc_id)?
436+
.mark_definedness(ptr, dest.layout.size, false)?;
430437
}
431438
}
432439
}
@@ -439,7 +446,13 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
439446
let ptr = self.read_scalar(args[0])?.not_undef()?;
440447
let count = self.read_scalar(args[2])?.to_usize(self)?;
441448
self.memory().check_align(ptr, ty_layout.align.abi)?;
442-
self.memory_mut().write_repeat(ptr, val_byte, ty_layout.size * count)?;
449+
let byte_count = ty_layout.size * count;
450+
if byte_count.bytes() != 0 {
451+
let ptr = ptr.to_ptr()?;
452+
self.memory_mut()
453+
.get_mut(ptr.alloc_id)?
454+
.write_repeat(tcx, ptr, val_byte, byte_count)?;
455+
}
443456
}
444457

445458
name => return err!(Unimplemented(format!("unimplemented intrinsic: {}", name))),

src/operator.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,12 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
142142
// allocations sit right next to each other. The C/C++ standards are
143143
// somewhat fuzzy about this case, so I think for now this check is
144144
// "good enough".
145-
// We require liveness, as dead allocations can of course overlap.
146-
self.memory().check_bounds_ptr(left, InboundsCheck::Live)?;
147-
self.memory().check_bounds_ptr(right, InboundsCheck::Live)?;
148-
// Two live in-bounds pointers, we can compare across allocations
145+
// Dead allocations in miri cannot overlap with live allocations, but
146+
// on read hardware this can easily happen. Thus for comparisons we require
147+
// both pointers to be live.
148+
self.memory().get(left.alloc_id)?.check_bounds_ptr(left)?;
149+
self.memory().get(right.alloc_id)?.check_bounds_ptr(right)?;
150+
// Two in-bounds pointers, we can compare across allocations
149151
left == right
150152
}
151153
}
@@ -158,7 +160,8 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
158160
// Case I: Comparing with NULL
159161
if bits == 0 {
160162
// Test if the ptr is in-bounds. Then it cannot be NULL.
161-
if self.memory().check_bounds_ptr(ptr, InboundsCheck::MaybeDead).is_ok() {
163+
// Even dangling pointers cannot be NULL.
164+
if self.memory().check_bounds_ptr_maybe_dead(ptr).is_ok() {
162165
return Ok(false);
163166
}
164167
}
@@ -298,9 +301,10 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'a, 'mir, '
298301
if let Scalar::Ptr(ptr) = ptr {
299302
// Both old and new pointer must be in-bounds of a *live* allocation.
300303
// (Of the same allocation, but that part is trivial with our representation.)
301-
self.memory().check_bounds_ptr(ptr, InboundsCheck::Live)?;
304+
let alloc = self.memory().get(ptr.alloc_id)?;
305+
alloc.check_bounds_ptr(ptr)?;
302306
let ptr = ptr.signed_offset(offset, self)?;
303-
self.memory().check_bounds_ptr(ptr, InboundsCheck::Live)?;
307+
alloc.check_bounds_ptr(ptr)?;
304308
Ok(Scalar::Ptr(ptr))
305309
} else {
306310
// An integer pointer. They can only be offset by 0, and we pretend there

src/stacked_borrows.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc::hir::{Mutability, MutMutable, MutImmutable};
55

66
use crate::{
77
EvalResult, EvalErrorKind, MiriEvalContext, HelpersEvalContextExt, Evaluator, MutValueVisitor,
8-
MemoryKind, MiriMemoryKind, RangeMap, AllocId, Allocation, AllocationExtra, InboundsCheck,
8+
MemoryKind, MiriMemoryKind, RangeMap, AllocId, Allocation, AllocationExtra,
99
Pointer, MemPlace, Scalar, Immediate, ImmTy, PlaceTy, MPlaceTy,
1010
};
1111

@@ -500,8 +500,8 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
500500
}
501501

502502
// Get the allocation
503-
self.memory().check_bounds(ptr, size, InboundsCheck::Live)?;
504-
let alloc = self.memory().get(ptr.alloc_id).expect("We checked that the ptr is fine!");
503+
let alloc = self.memory().get(ptr.alloc_id)?;
504+
alloc.check_bounds(self, ptr, size)?;
505505
// If we got here, we do some checking, *but* we leave the tag unchanged.
506506
if let Borrow::Shr(Some(_)) = ptr.tag {
507507
assert_eq!(mutability, Some(MutImmutable));
@@ -543,8 +543,8 @@ impl<'a, 'mir, 'tcx> EvalContextExt<'tcx> for MiriEvalContext<'a, 'mir, 'tcx> {
543543
ptr, place.layout.ty, new_bor);
544544

545545
// Get the allocation. It might not be mutable, so we cannot use `get_mut`.
546-
self.memory().check_bounds(ptr, size, InboundsCheck::Live)?;
547-
let alloc = self.memory().get(ptr.alloc_id).expect("We checked that the ptr is fine!");
546+
let alloc = self.memory().get(ptr.alloc_id)?;
547+
alloc.check_bounds(self, ptr, size)?;
548548
// Update the stacks.
549549
if let Borrow::Shr(Some(_)) = new_bor {
550550
// Reference that cares about freezing. We need a frozen-sensitive reborrow.

0 commit comments

Comments
 (0)