error: Undefined Behavior: memory access failed: alloc237 has been freed, so this pointer is dangling

error: Undefined Behavior: memory access failed: attempting to access 4 bytes, but got 0x20a24[noalloc] which is a dangling pointer (it has no provenance)

Miri がダングリングポインタへのアクセスを検出した。

パターン

パターン A

ヒープ領域

ヒープ領域を指すダングリングポインタにアクセスしたパターン。

サンプル

以下では、dangling_ptr から解放済のヒープ領域へのポインタが戻される。


fn main() {
    let ptr = dangling_ptr();
    let val = unsafe { *ptr };
    assert_eq!(val, 0);
}

fn dangling_ptr() -> *const i32 {
    let var = vec![0; 256];
    &var[255] as *const _
}

error: Undefined Behavior: memory access failed: alloc237 has been freed, so this pointer is dangling
  --> src\main.rs:3:24
   |
 3 |     let val = unsafe { *ptr };
   |                        ^^^^ Undefined Behavior occurred here
   |
   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
help: alloc237 was allocated here:
  --> src\main.rs:8:15
   |
 8 |     let var = vec![0; 256];
   |               ^^^^^^^^^^^^
help: alloc237 was deallocated here:
  --> src\main.rs:10:1
   |
10 | }
   | ^
   = note: BACKTRACE (of the first span):
   = note: inside `main` at src\main.rs:3:24: 3:28
   = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

パターン B

スタック領域

スタック領域を指すダングリングポインタにアクセスしたパターン。

サンプル

以下では、dangling_ptr から解放済のスタック領域へのポインタが戻される。


fn main() {
    let ptr = dangling_ptr();
    let val = unsafe { *ptr };
    assert_eq!(val, 0);
}

fn dangling_ptr() -> *const i32 {
    let var = 0;
    &var as *const _
}

warning: a dangling pointer will be produced because the local variable `var` will be dropped
 --> src\main.rs:9:5
  |
7 | fn dangling_ptr() -> *const i32 {
  |                      ---------- return type of the function is `*const i32`
8 |     let var = 0;
  |         --- `var` is part the function and will be dropped at the end of the function
9 |     &var as *const _
  |     ----^^^^^^^^^^^^
  |     |
  |     dangling pointer created here
  |
  = note: pointers do not have a lifetime; after returning, the `i32` will be deallocated at the end of the function because nothing is referencing it as far as the type system is concerned
  = note: `#[warn(dangling_pointers_from_locals)]` on by default

error: Undefined Behavior: memory access failed: alloc126 has been freed, so this pointer is dangling
  --> src\main.rs:3:24
   |
 3 |     let val = unsafe { *ptr };
   |                        ^^^^ Undefined Behavior occurred here
   |
   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
help: alloc126 was allocated here:
  --> src\main.rs:8:9
   |
 8 |     let var = 0;
   |         ^^^
help: alloc126 was deallocated here:
  --> src\main.rs:10:1
   |
10 | }
   | ^
   = note: BACKTRACE (of the first span):
   = note: inside `main` at src\main.rs:3:24: 3:28

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

パターン C

不明な起源

有効な『ポインタの起源』が存在しないパターン。

これは実際に起源が存在しない場合の他にも、誤って厳密な起源を用いる addr メソッドと公開された起源を用いるポインタから整数へのキャスト (with_exposed_provenance と等価) を併用した場合にもよく発生する。

サンプル

以下では、addr メソッドとポインタから整数へのキャストを併用している。


fn main() {
    let var = 0;
    let ptr = &var as *const i32;
    let addr = ptr.addr();
    let ptr = addr as *const i32;
    let val = unsafe { *ptr };
    assert_eq!(val, var);
}

warning: integer-to-pointer cast
 --> src\main.rs:5:15
  |
5 |     let ptr = addr as *const i32;
  |               ^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
  |
  = help: this program is using integer-to-pointer casts or (equivalently) `ptr::with_exposed_provenance`, which means that Miri might miss pointer bugs in this program
  = help: see https://doc.rust-lang.org/nightly/std/ptr/fn.with_exposed_provenance.html for more details on that operation
  = help: to ensure that Miri does not miss bugs in your program, use Strict Provenance APIs (https://doc.rust-lang.org/nightly/std/ptr/index.html#strict-provenance, https://crates.io/crates/sptr) instead
  = help: you can then set `MIRIFLAGS=-Zmiri-strict-provenance` to ensure you are not relying on `with_exposed_provenance` semantics
  = help: alternatively, `MIRIFLAGS=-Zmiri-permissive-provenance` disables this warning
  = note: BACKTRACE:
  = note: inside `main` at src\main.rs:5:15: 5:33

error: Undefined Behavior: memory access failed: attempting to access 4 bytes, but got 0x20a24[noalloc] which is a dangling pointer (it has no provenance)
 --> src\main.rs:6:24
  |
6 |     let val = unsafe { *ptr };
  |                        ^^^^ Undefined Behavior occurred here
  |
  = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
  = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
  = note: BACKTRACE:
  = note: inside `main` at src\main.rs:6:24: 6:28

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace