]> git.lizzy.rs Git - rust.git/commitdiff
check for extern static size mismatches
authorRalf Jung <post@ralfj.de>
Wed, 20 Jul 2022 21:40:27 +0000 (17:40 -0400)
committerRalf Jung <post@ralfj.de>
Wed, 20 Jul 2022 22:32:03 +0000 (18:32 -0400)
src/machine.rs
tests/fail/extern_static_wrong_size.rs [new file with mode: 0644]
tests/fail/extern_static_wrong_size.stderr [new file with mode: 0644]

index 1ac60e2ad84be1f40f2f5dd9c902100faa12add4..67a6c997e99027e71a6e5d67d2d5acd22e7c8305 100644 (file)
@@ -638,12 +638,35 @@ fn extern_static_base_pointer(
     ) -> InterpResult<'tcx, Pointer<Provenance>> {
         let link_name = ecx.item_link_name(def_id);
         if let Some(&ptr) = ecx.machine.extern_statics.get(&link_name) {
+            // Various parts of the engine rely on `get_alloc_info` for size and alignment
+            // information. That uses the type information of this static.
+            // Make sure it matches the Miri allocation for this.
+            let Provenance::Concrete { alloc_id, .. } = ptr.provenance else {
+                panic!("extern_statics cannot contain wildcards")
+            };
+            let (shim_size, shim_align, _kind) = ecx.get_alloc_info(alloc_id);
+            let extern_decl_layout =
+                ecx.tcx.layout_of(ty::ParamEnv::empty().and(ecx.tcx.type_of(def_id))).unwrap();
+            if extern_decl_layout.size != shim_size || extern_decl_layout.align.abi != shim_align {
+                throw_unsup_format!(
+                    "`extern` static `{name}` from crate `{krate}` has been declared \
+                    with a size of {decl_size} bytes and alignment of {decl_align} bytes, \
+                    but Miri emulates it via an extern static shim \
+                    with a size of {shim_size} bytes and alignment of {shim_align} bytes",
+                    name = ecx.tcx.def_path_str(def_id),
+                    krate = ecx.tcx.crate_name(def_id.krate),
+                    decl_size = extern_decl_layout.size.bytes(),
+                    decl_align = extern_decl_layout.align.abi.bytes(),
+                    shim_size = shim_size.bytes(),
+                    shim_align = shim_align.bytes(),
+                )
+            }
             Ok(ptr)
         } else {
             throw_unsup_format!(
-                "`extern` static `{}` from crate `{}` is not supported by Miri",
-                ecx.tcx.def_path_str(def_id),
-                ecx.tcx.crate_name(def_id.krate),
+                "`extern` static `{name}` from crate `{krate}` is not supported by Miri",
+                name = ecx.tcx.def_path_str(def_id),
+                krate = ecx.tcx.crate_name(def_id.krate),
             )
         }
     }
diff --git a/tests/fail/extern_static_wrong_size.rs b/tests/fail/extern_static_wrong_size.rs
new file mode 100644 (file)
index 0000000..17061f0
--- /dev/null
@@ -0,0 +1,10 @@
+//@ only-target-linux: we need a specific extern supported on this target
+//@normalize-stderr-test: "[48] bytes" -> "N bytes"
+
+extern "C" {
+    static mut environ: i8;
+}
+
+fn main() {
+    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/
+}
diff --git a/tests/fail/extern_static_wrong_size.stderr b/tests/fail/extern_static_wrong_size.stderr
new file mode 100644 (file)
index 0000000..fdeb7bb
--- /dev/null
@@ -0,0 +1,14 @@
+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
+  --> $DIR/extern_static_wrong_size.rs:LL:CC
+   |
+LL |     let _val = unsafe { environ };
+   |                         ^^^^^^^ `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
+   |
+   = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
+   = note: backtrace:
+   = note: inside `main` at $DIR/extern_static_wrong_size.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+