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

"Dangling" means multiple things #478

Open
Manishearth opened this issue Nov 28, 2023 · 5 comments
Open

"Dangling" means multiple things #478

Manishearth opened this issue Nov 28, 2023 · 5 comments
Labels
C-terminology Category: Discussing terminology -- which term to use, how to define it, adding it to the glossary

Comments

@Manishearth
Copy link
Member

Manishearth commented Nov 28, 2023

In the C++ world, typically, a "dangling" pointer is one to memory that was previously allocated and subsequently deallocated. Let's call these freed-dangling. These are just bad, period.

In Rust, APIs like NonNull::dangling()` produce pointers that were not ever allocated, primarily constructed to be "aligned but not null".. Let's call these align-dangling. It's good practice to use align-dangling pointers when working with collections or ZSTs.

We tend to use these meanings interchangeably. They are largely the same when it comes to the validity of pointer accesses, except around zero-sized types: zero-sized reads are not valid when reading from freed memory, unless the pointer was obtained as a direct cast from an integer literal (presumably these get normalized to align-dangling pointers).

This can lead to some confusion around terminology, for example with this code (credit @kupiakos), where we have both a freed-dangling and an align-dangling NonNull::dangling() pointer, and miri complains about the former, but says "out-of-bounds pointer use: alloc921 has been freed, so this pointer is dangling", implicitly calling it "dangling".

We should potentially pin down what meaning of "dangling" we intend everywhere, use it consistently, and update the docs of NonNull::dangling() to reference ZST validity. We don't necessarily need to split these meanings as long as we're clear about it; splitting the meanings may cause more confusion than it's worth.

@RalfJung
Copy link
Member

RalfJung commented Nov 28, 2023

I consider there to be three kinds of "dangling" pointers:

  • pointers with no provenance whatsoever -- that's what you call "align-dangling", but it has nothing to do with alignment so I'd rather avoid that term; this is what ptr::invalid (maybe to be renamed) creates
  • pointers with provenance of some allocation that has been freed -- that's what you call "freed-dangling"
  • pointers with provenance of some allocation that is still live but the pointer is out-of-bounds of that allocation -- we might call this "oob/out-of-bounds-dangling"

In C and C++, creating the latter kind of pointer is not possible (it's UB), but in Rust it's possible and they should be considered "dangling" as well IMO.

I agree it'd be good to clean up the terminology here. Relatedly, the term "dereferenceable" also needs clarification.

@RalfJung RalfJung added the C-terminology Category: Discussing terminology -- which term to use, how to define it, adding it to the glossary label Nov 28, 2023
@Manishearth
Copy link
Member Author

but it has nothing to do with alignment so I'd rather avoid that term

Yeah it's typically just used in a case where you want something aligned. I don't have a better term for it, page0-dangling perhaps.

@RalfJung
Copy link
Member

They can point to literally any address though, ptr::invalid takes a usize. I sometimes call them "(raw) integer pointers", but that doesn't really fit the pattern here.

@digama0
Copy link

digama0 commented Nov 29, 2023

They are largely the same when it comes to the validity of pointer accesses, except around zero-sized types: zero-sized reads are not valid when reading from freed memory, unless the pointer was obtained as a direct cast from an integer literal (presumably these get normalized to align-dangling pointers).

I believe this is no longer true as of the recent FCP: zero sized reads from any pointer are now valid, so AFAIK freed-dangling pointers are indistinguishable from align-dangling (which I would call no-provenance / null-provenance pointers). The linked documentation is out of date.

@RalfJung
Copy link
Member

rust-lang/rust#117945 is tracking implementing that FCP.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-terminology Category: Discussing terminology -- which term to use, how to define it, adding it to the glossary
Projects
None yet
Development

No branches or pull requests

3 participants