Skip to content

Commit 5dfc8f1

Browse files
committed
fix nits and handling of extern static
1 parent 61ae06f commit 5dfc8f1

File tree

5 files changed

+42
-36
lines changed

5 files changed

+42
-36
lines changed

src/librustc_mir/interpret/memory.rs

+23-14
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
use std::collections::VecDeque;
2020
use std::ptr;
2121

22-
use rustc::ty::{self, Instance, query::TyCtxtAt};
22+
use rustc::ty::{self, Instance, ParamEnv, query::TyCtxtAt};
2323
use rustc::ty::layout::{self, Align, TargetDataLayout, Size, HasDataLayout};
2424
use rustc::mir::interpret::{Pointer, AllocId, Allocation, ConstValue, GlobalId,
2525
EvalResult, Scalar, EvalErrorKind, AllocType, PointerArithmetic,
@@ -235,7 +235,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
235235
// Check non-NULL/Undef, extract offset
236236
let (offset, alloc_align) = match ptr {
237237
Scalar::Ptr(ptr) => {
238-
let (size, align) = self.get_size_and_align(ptr.alloc_id)?;
238+
let (size, align) = self.get_size_and_align(ptr.alloc_id);
239239
// check this is not NULL -- which we can ensure only if this is in-bounds
240240
// of some (potentially dead) allocation.
241241
if ptr.offset > size {
@@ -359,19 +359,28 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
359359
}
360360
}
361361

362-
pub fn get_size_and_align(&self, id: AllocId) -> EvalResult<'tcx, (Size, Align)> {
363-
Ok(match self.get(id) {
364-
Ok(alloc) => (Size::from_bytes(alloc.bytes.len() as u64), alloc.align),
365-
Err(err) => match err.kind {
366-
EvalErrorKind::DanglingPointerDeref =>
367-
// This should be in the dead allocation map
368-
*self.dead_alloc_map.get(&id).expect(
369-
"allocation missing in dead_alloc_map"
370-
),
371-
// E.g. a function ptr allocation
372-
_ => return Err(err)
362+
pub fn get_size_and_align(&self, id: AllocId) -> (Size, Align) {
363+
if let Ok(alloc) = self.get(id) {
364+
return (Size::from_bytes(alloc.bytes.len() as u64), alloc.align);
365+
}
366+
// Could also be a fn ptr or extern static
367+
match self.tcx.alloc_map.lock().get(id) {
368+
Some(AllocType::Function(..)) => (Size::ZERO, Align::from_bytes(1, 1).unwrap()),
369+
Some(AllocType::Static(did)) => {
370+
// The only way `get` couldnÄt have worked here is if this is an extern static
371+
assert!(self.tcx.is_foreign_item(did));
372+
// Use size and align of the type
373+
let ty = self.tcx.type_of(did);
374+
let layout = self.tcx.layout_of(ParamEnv::empty().and(ty)).unwrap();
375+
(layout.size, layout.align)
373376
}
374-
})
377+
_ => {
378+
// Must be a deallocated pointer
379+
*self.dead_alloc_map.get(&id).expect(
380+
"allocation missing in dead_alloc_map"
381+
)
382+
}
383+
}
375384
}
376385

377386
pub fn get_mut(

src/librustc_mir/interpret/terminator.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
384384
} else {
385385
// FIXME: The caller thinks this function cannot return. How do
386386
// we verify that the callee agrees?
387-
// On the plus side, the the callee every writes to its return place,
387+
// On the plus side, the the callee ever writes to its return place,
388388
// that will be detected as UB (because we set that to NULL above).
389389
}
390390
Ok(())

src/librustc_mir/interpret/validity.rs

+13-16
Original file line numberDiff line numberDiff line change
@@ -209,22 +209,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
209209
}
210210
// for safe ptrs, recursively check
211211
if let ty::Ref(..) = value.layout.ty.sty {
212-
if const_mode {
213-
// Skip validation entirely for some external statics
214-
if let Scalar::Ptr(ptr) = place.ptr {
215-
let alloc_kind = self.tcx.alloc_map.lock().get(ptr.alloc_id);
216-
if let Some(AllocType::Static(did)) = alloc_kind {
217-
// `extern static` cannot be validated as they have no body.
218-
// They are not even properly aligned.
219-
// Statics from other crates are already checked.
220-
// They might be checked at a different type, but for now we want
221-
// to avoid recursing too deeply. This is not sound!
222-
if !did.is_local() || self.tcx.is_foreign_item(did) {
223-
return Ok(());
224-
}
225-
}
226-
}
227-
}
228212
// Make sure this is non-NULL and aligned
229213
let (size, align) = self.size_and_align_of(place.extra, place.layout)?;
230214
match self.memory.check_align(place.ptr, align) {
@@ -244,6 +228,19 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
244228
if !place.layout.is_zst() {
245229
let ptr = try_validation!(place.ptr.to_ptr(),
246230
"integer pointer in non-ZST reference", path);
231+
if const_mode {
232+
// Skip validation entirely for some external statics
233+
let alloc_kind = self.tcx.alloc_map.lock().get(ptr.alloc_id);
234+
if let Some(AllocType::Static(did)) = alloc_kind {
235+
// `extern static` cannot be validated as they have no body.
236+
// FIXME: Statics from other crates are also skipped.
237+
// They might be checked at a different type, but for now we
238+
// want to avoid recursing too deeply. This is not sound!
239+
if !did.is_local() || self.tcx.is_foreign_item(did) {
240+
return Ok(());
241+
}
242+
}
243+
}
247244
try_validation!(self.memory.check_bounds(ptr, size, false),
248245
"dangling (not entirely in bounds) reference", path);
249246
}

src/test/ui/issues/issue-14227.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@
1111
#![allow(safe_extern_statics, warnings)]
1212

1313
extern {
14-
pub static symbol: ();
14+
pub static symbol: u32;
1515
}
16-
static CRASH: () = symbol;
16+
static CRASH: u32 = symbol;
1717
//~^ ERROR could not evaluate static initializer
1818
//~| tried to read from foreign (extern) static
1919

src/test/ui/issues/issue-14227.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error[E0080]: could not evaluate static initializer
2-
--> $DIR/issue-14227.rs:16:20
2+
--> $DIR/issue-14227.rs:16:21
33
|
4-
LL | static CRASH: () = symbol;
5-
| ^^^^^^ tried to read from foreign (extern) static
4+
LL | static CRASH: u32 = symbol;
5+
| ^^^^^^ tried to read from foreign (extern) static
66

77
error: aborting due to previous error
88

0 commit comments

Comments
 (0)