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

Miri: better document and fix dynamic const pattern soundness checks #71655

Merged
merged 6 commits into from
Apr 30, 2020

Conversation

RalfJung
Copy link
Member

rust-lang/const-eval#42 got me thinking about soundness for consts being used in patterns, and I found a hole in our existing dynamic checks: a const referring to a mutable static in a different crate was not caught. This PR fixes that. It also adds some comments that explain which invariants are crucial for soundness of const-patterns.

Curiously, trying to weaponize this soundness hole failed: pattern matching compilation ICEd when encountering the cross-crate static, saying "expected allocation ID alloc0 to point to memory". I don't know why that would happen, statics should be entirely normal memory for pattern matching to access.

r? @oli-obk
Cc @rust-lang/wg-const-eval

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Apr 28, 2020
@RalfJung
Copy link
Member Author

Curiously, trying to weaponize this soundness hole failed: pattern matching compilation ICEd when encountering the cross-crate static, saying "expected allocation ID alloc0 to point to memory". I don't know why that would happen, statics should be entirely normal memory for pattern matching to access.

@rpjohnst solved this puzzle: pattern-match compilation has no support for GlobalAlloc::Static, which (accidentally?) introduced another line of defense and thus guarded against the soundness bug here.

const SLICE_MUT: &[u8; 1] = { //~ ERROR undefined behavior to use this value
//~| NOTE encountered a reference pointing to a static variable
//~| NOTE
unsafe { &static_cross_crate::ZERO }
Copy link
Contributor

Choose a reason for hiding this comment

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

won't this be worked around if you do &static_cross_crate::ZERO[0] here, and then pattern matching suddenly sees the mutable memory?

Copy link
Member Author

Choose a reason for hiding this comment

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

Why would that happen? It's still a reference to a GlobalAlloc::Static.

I can add that testcase.

Copy link
Member Author

Choose a reason for hiding this comment

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

You are right, that error does not get caught. But I do not understand why. The pointer should be the same, shouldn't it?

Are we somewhere accidentally "leaking" the internal pointer of the static, as opposed to the lazy one?

Copy link
Member Author

@RalfJung RalfJung Apr 29, 2020

Choose a reason for hiding this comment

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

Ah, never mind -- we have to actually use the constant to cause the error. (Not sure why though, we should be evaluating all consts whether they are used or not... probably because I did allow(const_err).)

Copy link
Contributor

Choose a reason for hiding this comment

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

Are we somewhere accidentally "leaking" the internal pointer of the static, as opposed to the lazy one?

If that case isn't doing it, then using &&[u8] for the static and using &*static_cross_crate::ZERO will definitely do it, or by using an enum and getting a reference to a field. Any operation that needs to actually read from the static in order to produce the reference will yield the internal AllocId instead of the lazy one.

Copy link
Member Author

Choose a reason for hiding this comment

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

Any operation that needs to actually read from the static in order to produce the reference will yield the internal AllocId instead of the lazy one.

I don't think that's true. The code in memory.rs is very careful to never leak the internal AllocId back to the interpreter.

Also, any code that actually reads from the static will fail the before_access_static dynamic check, and this is already covered.

@oli-obk
Copy link
Contributor

oli-obk commented Apr 29, 2020

@bors r+

@bors
Copy link
Contributor

bors commented Apr 29, 2020

📌 Commit 979bbf2 has been approved by oli-obk

@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 Apr 29, 2020
@RalfJung
Copy link
Member Author

@bors r-
Let me add another testcase along the lines of what you proposed above. What do you mean by "using an enum and getting a reference to a field"?

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Apr 29, 2020
@RalfJung
Copy link
Member Author

All right, did that and also explained in memory.rs that not leaking the "resolved" AllocId is important.

@bors r=oli-obk

@bors
Copy link
Contributor

bors commented Apr 29, 2020

📌 Commit 07772fc has been approved by oli-obk

@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-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Apr 29, 2020
@rust-highfive

This comment has been minimized.

@RalfJung RalfJung closed this Apr 29, 2020
@RalfJung RalfJung reopened this Apr 29, 2020
bors added a commit to rust-lang-ci/rust that referenced this pull request Apr 30, 2020
Rollup of 5 pull requests

Successful merges:

 - rust-lang#71205 (rustc: fix check_attr() for methods, closures and foreign functions)
 - rust-lang#71540 (Suggest deref when coercing `ty::Ref` to `ty::RawPtr`)
 - rust-lang#71655 (Miri: better document and fix dynamic const pattern soundness checks)
 - rust-lang#71672 (document missing stable counterparts of intrinsics)
 - rust-lang#71692 (Add clarification on std::cfg macro docs v. #[cfg] attribute)

Failed merges:

r? @ghost
@bors bors merged commit 71bf986 into rust-lang:master Apr 30, 2020
@RalfJung RalfJung deleted the const-pattern-soundness branch May 1, 2020 08:49
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.

4 participants