-
Notifications
You must be signed in to change notification settings - Fork 97
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
Do not assume that ZST-typed symbols refer to unique objects #3134
Conversation
It seems that rustc does not necessarily create unique objects for ZST-typed symbols, unless they are parameters. Resolves: model-checking#3129
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please confirm that is really the case and paste a reference here?
Not exactly a "reference", but still a very extensive discussion including pointers to the actual implementation (yes, this is all about the implementation of the Rust compiler, nothing here is specified in the documentation): https://stackoverflow.com/questions/58529934/why-do-zero-sized-types-cause-real-allocations-in-some-cases |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @tautschnig for working on this, but I really think we should ask the Rust team (maybe create an issue in https://github.com/rust-lang/unsafe-code-guidelines) about what guarantees we should expect when it comes to comparing two raw pointers to ZST objects.
I always find that searching for ZST related issues and guarantees is a rabbit hole. Just from my latest search:
- Iterators over slices of ZST behave strange rust-lang/rust#42789: This is a case where exact address is expected due to pointer identity.
- When are things guaranteed to have unique addresses? rust-lang/unsafe-code-guidelines#206: This issues does mention ZST a bit, and it seems that the address of a ZST may be the same as anything including a non-ZST.
- https://users.rust-lang.org/t/addresses-of-zsts/64106: When taking the address of a ZST field, the address is still expected to be in bounds of the struct.
Ok, I gave this a thought, and I think the correct solution would be to add a UB check if users try to compare two ZST pointers. My reasoning is:
|
Why should we add a UB check? Comparing any two (raw) pointers is explicitly permitted in Rust as far as I can tell?! Edit:
|
A further note: the implementation pointed to in the above SO-post (rust-lang/rust#63635) continued to exist until rust-lang/rust#111768. It does seem, however, that at that point |
I created rust-lang/unsafe-code-guidelines#503 to hopefully get some answers to these questions. |
Thank you!!! Given their answers, my interpretation is that we should not do the parameter-specific piece and will instead have to modify the Closure/zst_param.rs test, because the non-equality asserted in there is not actually guaranteed. |
I have now updated the implementation to the above effect. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current fix will work for the exact issue at hand, but the following will still always evaluate to false
, even though it could be true:
let a1 = &() as *const _;
let a2 = &() as *const _;
let a3 = &() as *const _;
let a4 = &() as *const _;
cover!(a1 == a2 && a3 == a4 && a1 != a3);
So to make this really sound, you need to set all addresses to be any non-null + aligned address value.
[...]
Hmm, yes, but still those also need to be addresses such that dereferencing pointers with such addresses also works. The following might work:
A problem, however, will arise when lifetimes of ZST objects are required to be honoured. Then we'd have to reference-count each entry in this array, which seems like unreasonable overhead. |
De-referencing a ZST dangling pointer is considered valid in Rust since it is a no-op. So as long as the pointer is aligned, there should be no problem. I believe Kani also treats that as a no-op, i.e., it does not emit a de-reference instruction. I don't think we will be able to track ZST lifetimes until we have a different mechanism to handle provenance. |
Which means that Kani cannot detect invalid ZST access due to deallocation. This is a limitation that should be documented, if you don't mind. |
Summary of a discussion that @celinval and I had:
|
For 5, we should change the if to be: if sz == 0 {
true
} else {
// invoke read ok
} |
@tautschnig any updates? |
I have now pushed my update, but I am yet to understand why |
Those tests used to exercise a path that no longer exists. With the new implementation, non-zst dangling pointers will reach the Kani intrinsic, which in regular tests is a loop. I.e., we are no longer able to test those two cases with concrete tests, and they should be removed. |
[...]
Thanks, now done. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please take a look at the s2n-quic test that regressed?
Everything else looks good!
I have now locally re-run this test multiple times both with current |
For reference, here is the auto-generated changelog ## What's Changed * Upgrade toolchain to 2024-04-18 and improve toolchain workflow by @celinval in #3149 * Automatic toolchain upgrade to nightly-2024-04-19 by @github-actions in #3150 * Stabilize cover statement and update contracts RFC by @celinval in #3091 * Automatic toolchain upgrade to nightly-2024-04-20 by @github-actions in #3154 * Bump tests/perf/s2n-quic from `2d5e891` to `5f88e54` by @dependabot in #3140 * Automatic cargo update to 2024-04-22 by @github-actions in #3157 * Automatic toolchain upgrade to nightly-2024-04-21 by @github-actions in #3158 * Bump tests/perf/s2n-quic from `5f88e54` to `9730578` by @dependabot in #3159 * Fix cargo audit error by @jaisnan in #3160 * Fix cbmc-update CI job by @tautschnig in #3156 * Automatic cargo update to 2024-04-29 by @github-actions in #3165 * Bump tests/perf/s2n-quic from `9730578` to `1436af7` by @dependabot in #3166 * Do not assume that ZST-typed symbols refer to unique objects by @tautschnig in #3134 * Fix copyright check for `expected` tests by @adpaco-aws in #3170 * Remove kani::Arbitrary from the modifies contract instrumentation by @feliperodri in #3169 * Automatic cargo update to 2024-05-06 by @github-actions in #3172 * Bump tests/perf/s2n-quic from `1436af7` to `6dd41e0` by @dependabot in #3174 * Avoid unnecessary uses of Location::none() by @tautschnig in #3173 **Full Changelog**: kani-0.50.0...kani-0.51.0 By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses. --------- Co-authored-by: Adrian Palacios <[email protected]>
…hecking#3134) The Rust specification does not guarantee that ZST-typed symbols are backed by unique objects, and `rustc` appears to make use of this as can be demonstrated for both locals and statics. For parameters no such example has been found, but as there remains a lack of a guarantee we err on the safe side. Resolves: model-checking#3129
…hecking#3134) The Rust specification does not guarantee that ZST-typed symbols are backed by unique objects, and `rustc` appears to make use of this as can be demonstrated for both locals and statics. For parameters no such example has been found, but as there remains a lack of a guarantee we err on the safe side. Resolves: model-checking#3129
For reference, here is the auto-generated changelog ## What's Changed * Upgrade toolchain to 2024-04-18 and improve toolchain workflow by @celinval in model-checking#3149 * Automatic toolchain upgrade to nightly-2024-04-19 by @github-actions in model-checking#3150 * Stabilize cover statement and update contracts RFC by @celinval in model-checking#3091 * Automatic toolchain upgrade to nightly-2024-04-20 by @github-actions in model-checking#3154 * Bump tests/perf/s2n-quic from `2d5e891` to `5f88e54` by @dependabot in model-checking#3140 * Automatic cargo update to 2024-04-22 by @github-actions in model-checking#3157 * Automatic toolchain upgrade to nightly-2024-04-21 by @github-actions in model-checking#3158 * Bump tests/perf/s2n-quic from `5f88e54` to `9730578` by @dependabot in model-checking#3159 * Fix cargo audit error by @jaisnan in model-checking#3160 * Fix cbmc-update CI job by @tautschnig in model-checking#3156 * Automatic cargo update to 2024-04-29 by @github-actions in model-checking#3165 * Bump tests/perf/s2n-quic from `9730578` to `1436af7` by @dependabot in model-checking#3166 * Do not assume that ZST-typed symbols refer to unique objects by @tautschnig in model-checking#3134 * Fix copyright check for `expected` tests by @adpaco-aws in model-checking#3170 * Remove kani::Arbitrary from the modifies contract instrumentation by @feliperodri in model-checking#3169 * Automatic cargo update to 2024-05-06 by @github-actions in model-checking#3172 * Bump tests/perf/s2n-quic from `1436af7` to `6dd41e0` by @dependabot in model-checking#3174 * Avoid unnecessary uses of Location::none() by @tautschnig in model-checking#3173 **Full Changelog**: model-checking/kani@kani-0.50.0...kani-0.51.0 By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses. --------- Co-authored-by: Adrian Palacios <[email protected]>
The Rust specification does not guarantee that ZST-typed symbols are backed by unique objects, and
rustc
appears to make use of this as can be demonstrated for both locals and statics. For parameters no such example has been found, but as there remains a lack of a guarantee we err on the safe side.Resolves: #3129
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 and MIT licenses.