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

Improve #Safety of various methods in core::ptr #68701

Merged
merged 4 commits into from
Feb 17, 2020
Merged

Conversation

amosonn
Copy link
Contributor

@amosonn amosonn commented Jan 31, 2020

For read, read_unaligned,read_volatile, replace, and drop_in_place:

  • The value they point to must be properly initialized

For replace, additionally:

  • The pointer must be readable

@rust-highfive
Copy link
Collaborator

r? @withoutboats

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 31, 2020
@withoutboats
Copy link
Contributor

r? @RalfJung

@@ -123,6 +123,8 @@ mod mut_ptr;
///
/// * `to_drop` must be properly aligned.
///
/// * `to_drop` must point to a properly initialized value of type `T`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm... this one is tricky, actually. Namely, in general, this is not sufficient... the term "initialized" here, in the sense it is used in these docs, is basically what I called "validity invariant"; however, for drop_in_place, in general we even need the "safety invariant" to hold. Except that for some types we know that dropping them doesn't do anything, so e.g. for ManuallyDrop<Vec<u8>>, we do not need the safety invariant to hold.

I think I'd be more comfortable with something that points out that, since T's destructor is going to be called on the value, UB may be caused if the value is not actually valid for destructing -- the details of this depend on the type.

Cc @Centril @rust-lang/wg-unsafe-code-guidelines

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sounds quite reasonable to me.

Copy link
Contributor Author

@amosonn amosonn Feb 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would leave this bullet there, since this first produces a &mut T to call drop on, so if it isn't initialized this is inst-UB (like in all the other methods, which return a T).

Then we can add something like:

"The T value to_drop points to must be valid for destructing, which may mean it must uphold additional invariants - this is type dependent."

Is this sufficient? Is there a link for further reading which would be relevant?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RalfJung Hmm, reading through the post you linked to, you're stating that (at least currently) having a &mut T to a non-fully-initialized T is actually Ok. Does this mean we should remove that bullet about "properly initialized", since, depending on the destructor, we might e.g. not be reading some field, making it fine for it to be uninitialized?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would leave this bullet there, since this first produces a &mut T to call drop on, so if it isn't initialized this is inst-UB (like in all the other methods, which return a T).

Arguably it wouldn't do that for types that don't even need dropping, would it?

Though, conservatively, it is probably best to declare e.g. drop_in_place(0 as *mut i32) UB for now even if we want to relax this later.

"The T value to_drop points to must be valid for destructing, which may mean it must uphold additional invariants - this is type dependent."

Yeah, adding something like this would be better.
I don't know of a helpful link here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For anyone who stubles upon this: it seems that relying on a type not being Drop if it's Copy is not necessarily wished for (AFAII, related to making UnsafeCell impl Copy):
#60715 (comment)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you misunderstood that other post... even when Cell: Copy, I doubt we'll ever allow types that are Copy + Drop. Since Copy types are implicitly duplicated all the time, all of these copies would have to have their destructor running -- that is the kind of implicit cost Rust tries hard to avoid.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, it does directly say

People already abuse it for making sure a type has a no-op Drop impl, which is its own headache [..]

But this might of course be a misguided complaint?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think @pythonesque just wanted to say that saying T: Copy is a rather roundabout and bad way to say "T has a no-op Drop". It is correct, but (a) the intent is unclear (it looks like you want to copy the type but really you care about its lack of a drop shim), and (b) it is imprecise (many types, such as &mut T, have a no-op Drop but are not Copy).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, thanks for the explanation!

src/libcore/ptr/mod.rs Outdated Show resolved Hide resolved
src/libcore/ptr/mod.rs Outdated Show resolved Hide resolved
s/for reads and writes/for both ...
Added missing condition:
`dst` must be readable
For all methods which read a value of type T, `read`, `read_unaligned`,
`read_volatile` and `replace`, added missing
constraint:
The value they point to must be properly initialized
src/libcore/ptr/mod.rs Outdated Show resolved Hide resolved
Added missing conditions:
- Valid for writes
- Valid for destructing
@RalfJung
Copy link
Member

Thanks!

@bors r+ rollup

@bors
Copy link
Contributor

bors commented Feb 16, 2020

📌 Commit 943e653 has been approved by RalfJung

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Feb 16, 2020
JohnTitor added a commit to JohnTitor/rust that referenced this pull request Feb 16, 2020
Improve #Safety of various methods in core::ptr

For `read`, `read_unaligned`,`read_volatile`, `replace`, and `drop_in_place`:

- The value they point to must be properly initialized

For `replace`, additionally:

- The pointer must be readable
JohnTitor added a commit to JohnTitor/rust that referenced this pull request Feb 16, 2020
Improve #Safety of various methods in core::ptr

For `read`, `read_unaligned`,`read_volatile`, `replace`, and `drop_in_place`:

- The value they point to must be properly initialized

For `replace`, additionally:

- The pointer must be readable
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Feb 16, 2020
Improve #Safety of various methods in core::ptr

For `read`, `read_unaligned`,`read_volatile`, `replace`, and `drop_in_place`:

- The value they point to must be properly initialized

For `replace`, additionally:

- The pointer must be readable
JohnTitor added a commit to JohnTitor/rust that referenced this pull request Feb 17, 2020
Improve #Safety of various methods in core::ptr

For `read`, `read_unaligned`,`read_volatile`, `replace`, and `drop_in_place`:

- The value they point to must be properly initialized

For `replace`, additionally:

- The pointer must be readable
bors added a commit that referenced this pull request Feb 17, 2020
Rollup of 6 pull requests

Successful merges:

 - #68495 (Updating str.chars docs to mention crates.io.)
 - #68701 (Improve #Safety of various methods in core::ptr)
 - #69158 (Don't print block exit state in dataflow graphviz if unchanged)
 - #69179 (Rename `FunctionRetTy` to `FnRetTy`)
 - #69186 ([tiny] parser: `macro_rules` is a weak keyword)
 - #69188 (Clean up E0309 explanation)

Failed merges:

r? @ghost
@bors bors merged commit 943e653 into rust-lang:master Feb 17, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants