Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit e649a9a

Browse files
committed
check for extern static size mismatches
1 parent 59f9a91 commit e649a9a

File tree

3 files changed

+50
-3
lines changed

3 files changed

+50
-3
lines changed

src/machine.rs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -638,12 +638,35 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
638638
) -> InterpResult<'tcx, Pointer<Provenance>> {
639639
let link_name = ecx.item_link_name(def_id);
640640
if let Some(&ptr) = ecx.machine.extern_statics.get(&link_name) {
641+
// Various parts of the engine rely on `get_alloc_info` for size and alignment
642+
// information. That uses the type information of this static.
643+
// Make sure it matches the Miri allocation for this.
644+
let Provenance::Concrete { alloc_id, .. } = ptr.provenance else {
645+
panic!("extern_statics cannot contain wildcards")
646+
};
647+
let (shim_size, shim_align, _kind) = ecx.get_alloc_info(alloc_id);
648+
let extern_decl_layout =
649+
ecx.tcx.layout_of(ty::ParamEnv::empty().and(ecx.tcx.type_of(def_id))).unwrap();
650+
if extern_decl_layout.size != shim_size || extern_decl_layout.align.abi != shim_align {
651+
throw_unsup_format!(
652+
"`extern` static `{name}` from crate `{krate}` has been declared \
653+
with a size of {decl_size} bytes and alignment of {decl_align} bytes, \
654+
but Miri emulates it via an extern static shim \
655+
with a size of {shim_size} bytes and alignment of {shim_align} bytes",
656+
name = ecx.tcx.def_path_str(def_id),
657+
krate = ecx.tcx.crate_name(def_id.krate),
658+
decl_size = extern_decl_layout.size.bytes(),
659+
decl_align = extern_decl_layout.align.abi.bytes(),
660+
shim_size = shim_size.bytes(),
661+
shim_align = shim_align.bytes(),
662+
)
663+
}
641664
Ok(ptr)
642665
} else {
643666
throw_unsup_format!(
644-
"`extern` static `{}` from crate `{}` is not supported by Miri",
645-
ecx.tcx.def_path_str(def_id),
646-
ecx.tcx.crate_name(def_id.krate),
667+
"`extern` static `{name}` from crate `{krate}` is not supported by Miri",
668+
name = ecx.tcx.def_path_str(def_id),
669+
krate = ecx.tcx.crate_name(def_id.krate),
647670
)
648671
}
649672
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//@ only-target-linux: we need a specific extern supported on this target
2+
//@normalize-stderr-test: "[48] bytes" -> "N bytes"
3+
4+
extern "C" {
5+
static mut environ: i8;
6+
}
7+
8+
fn main() {
9+
let _val = unsafe { environ }; //~ ERROR: /has been declared with a size of 1 bytes and alignment of 1 bytes, but Miri emulates it via an extern static shim with a size of [48] bytes and alignment of [48] bytes/
10+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: unsupported operation: `extern` static `environ` from crate `extern_static_wrong_size` has been declared with a size of 1 bytes and alignment of 1 bytes, but Miri emulates it via an extern static shim with a size of N bytes and alignment of N bytes
2+
--> $DIR/extern_static_wrong_size.rs:LL:CC
3+
|
4+
LL | let _val = unsafe { environ };
5+
| ^^^^^^^ `extern` static `environ` from crate `extern_static_wrong_size` has been declared with a size of 1 bytes and alignment of 1 bytes, but Miri emulates it via an extern static shim with a size of N bytes and alignment of N bytes
6+
|
7+
= help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
8+
= note: backtrace:
9+
= note: inside `main` at $DIR/extern_static_wrong_size.rs:LL:CC
10+
11+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
12+
13+
error: aborting due to previous error
14+

0 commit comments

Comments
 (0)