Skip to content

Miri checks ptr.read() but not dereferencing a pointer (*ptr) #1526

Closed

Description

@elichai

Hi,
miri complains on this:

fn main() {
    unsafe {
        let a = [1u8,2,3];
        let b = &a[0] as *const u8;
        println!("{}", b.add(1).read());
    }
}

https://play.rust-lang.org/?gist=5af194a447ac5e0d38796c809e3a0e6f
but not on this:

fn main() {
    unsafe {
        let a = [1u8,2,3];
        let b = &a[0] as *const u8;
        println!("{}", *b.add(1));
    }
}

https://play.rust-lang.org/?gist=6b7d13c8b77d8e14e06d9133a19e992f

Activity

  1. RalfJung commented on Aug 26, 2020

    @RalfJung
    Member

    I just tried on the playground, and I do get an error for the second example as well:

    error: Undefined Behavior: trying to reborrow for SharedReadOnly, but parent tag <untagged> does not have an appropriate item in the borrow stack
     --> src/main.rs:5:24
      |
    5 |         println!("{}", *b.add(1));
      |                        ^^^^^^^^^ trying to reborrow for SharedReadOnly, but parent tag <untagged> does not have an appropriate item in the borrow stack
      |
      = help: this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental
      = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
    
  2. added
    C-supportCategory: Not necessarily a bug, but someone asking for support
    on Aug 26, 2020
  3. elichai commented on Aug 26, 2020

    @elichai
    ContributorAuthor

    Ha, you're right, this is weird.
    This on the other hand doesn't give an error:

    fn main() {
        unsafe {
            let a = [1u8, 2, 3];
            let b = &a[0] as *const u8;
            if !a.is_empty() {
                println!("{}", *b.add(1));
            }
        }
    }
  4. RalfJung commented on Aug 26, 2020

    @RalfJung
    Member

    But neither does this:

    fn main() {
        unsafe {
            let a = [1u8, 2, 3];
            let b = &a[0] as *const u8;
            if !a.is_empty() {
                println!("{}", b.add(1).read());
            }
        }
    }
  5. RalfJung commented on Aug 26, 2020

    @RalfJung
    Member

    This has nothing to do with deref vs read. This is caused by is_empty creating a raw pointer and Stacked Borrows not tracking raw pointers in detail -- so it "confuses" the raw pointer created there with b. That is currently expected behavior, though I would like to do more precise tracking of raw pointers eventually (but this might completely kill performance... and we'll have to see how compatible it is with real code).

  6. elichai commented on Aug 26, 2020

    @elichai
    ContributorAuthor

    @RalfJung Yes. this is a completely different issue than what I was describing,
    what happened is that I had a complex function, saw that it didn't error, I removed a lot of code, replaced with read() and it did, so I wrongly assumed it was the read() change. sorry.

  7. elichai commented on Aug 26, 2020

    @elichai
    ContributorAuthor

    So together with my confusion and the fact that this is expected behavior I'll close this issue.
    if you're curious this was the code snippet that got me here: rust-lang/rust#75943 (trying to minimize that down in the playground got me to accidentally assume deref was the problem)

  8. RalfJung commented on Aug 26, 2020

    @RalfJung
    Member

    I opened rust-lang/unsafe-code-guidelines#248 to track the underlying problem.

  9. added a commit that references this issue on Aug 28, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-supportCategory: Not necessarily a bug, but someone asking for support

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions