Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect error message for offset_from() on pointers to two different allocations. #4143

Open
theemathas opened this issue Jan 21, 2025 · 2 comments

Comments

@theemathas
Copy link

theemathas commented Jan 21, 2025

I ran the following code with Miri:

fn main() {
    unsafe {
        (&1_u8 as *const u8).offset_from(&2_u8);
    }
}

I expected Miri to sensibly report some UB, but instead I got the following:

error: Undefined Behavior: out-of-bounds `offset_from` origin: expected a pointer to the end of 4 bytes of memory, but got alloc4 which is at the beginning of the allocation
 --> src/main.rs:3:9
  |
3 |         (&1_u8 as *const u8).offset_from(&2_u8);
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from` origin: expected a pointer to the end of 4 bytes of memory, but got alloc4 which is at the beginning of the allocation
  |
  = 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:3:9: 3:48

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

The error message doesn't make any sense. I don't know where Miri got the "4 bytes of memory" expectation from. So I think the error is incorrect.

Reproducible on the playground with rust version 1.86.0-nightly (2025-01-20 f3d1d47fd84dfcf7f513)

@theemathas
Copy link
Author

theemathas commented Jan 21, 2025

For some reason, printing the pointer before calling offset_from() causes Miri to expect a very large allocation:

fn main() {
    let x: &u8 = &1_u8;
    println!("{:p}", x);
    unsafe {
        (x as *const u8).offset_from(&2_u8);
    }
}
error: Undefined Behavior: out-of-bounds `offset_from` origin: expected a pointer to the end of 51524 bytes of memory, but got alloc10 which is at the beginning of the allocation
 --> src/main.rs:5:9
  |
5 |         (x as *const u8).offset_from(&2_u8);
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from` origin: expected a pointer to the end of 51524 bytes of memory, but got alloc10 which is at the beginning of the allocation
  |
  = 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:5:9: 5:44

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

Note the "expected a pointer to the end of 51524 bytes of memory" in the error. I think this indicates that something has gone very wrong inside miri.

@RalfJung
Copy link
Member

The error is confusing but not fundamentally incorrect: the nicest way to check "are these two pointers in the same allocation" that also accounts for edge cases like identical pointers is to check "is the memory range between them dereferenceable from both pointers". That's what Miri is doing, and it's where the "4 bytes of memory" expectation comes from: the two pointers happen to be 4 bytes apart in that case.

I still think that this is the nicest implementation strategy, but we should probably find a way to make the error less confusing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants