-
Notifications
You must be signed in to change notification settings - Fork 1
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
Address stacked borrows violation in SymbolTable::intern
#236
Conversation
@CAD97 sorry for the out of the blue ping, but you've contributed here in the past and if you could lend a hand, I would appreciate a review on this fix for a stacked borrows violation in the |
2193b3b
to
569b01b
Compare
marking this as blocked since I would like to get this reviewed by a few eyes before merging. |
Speaking for myself, not as part of T-opsem. If the box gets moved when the symbol table grows, that's still a potential problem. It's probably not one which will actually get hit, but that's because of implementation details of the collection (i.e. that it uses The more thorough fix would be to replace the use of Make sure to test with That said, if you're okay with relying on the implementation of the symbol table (probably Note that as a slight mitigation, despite the Rust-level UB, the fact that interned symbols are immutable means that rustc has not yet exploited this UB, and thus the lowering to LLVM IR does not contain any UB. (This may change in the future.) |
Thanks @CAD97! Responses to your comments inline.
I suspected this to be the case which is why I added this line to all of the tests that run under Miri. I hope this will prevent regressions if the underlying collection, which is intaglio/tests/leak_drop/bytes.rs Line 20 in fe7870e
This seems like a reasonable change to make as well as one that's not too disruptive to the
Yup it looks like this being made the default in nightly is the reason I got the build failure on the weekly CI that runs on a cron against Do you have any suggestions for additional Miri flags I should add in CI? The current set of intaglio/.github/workflows/miri.yaml Line 18 in 70ccd8b
This is correct, the symbol tables store the |
@CAD97 I've added a |
This stacked borrows violation impacts all `SymbolTable` variants in this crate and has been present in all published versions. The `SymbolTable::intern` function previously worked like this: 1. Convert the given contents to be interned into a `Cow<'static, T>`. 2. Check to see if this content is already interned by checking the internal bimap. If found, return the matching symbol. 3. Convert the `Cow` into an `Interned` which is an enum of either a &'static T` or a `Box<T>`. 4. Borrow a `&'static T` from the `Interned`. 5. Push the `Interned` into the vec. 6. Add the `&'static T` to the map. 7. Check that the insertion happened correctly with some debug assertions. 8. Return the computed symbol. As of at least rustc 1.73.0-nightly (31395ec38 2023-07-24), Miri pops all borrows from the `Interned` at step 5 when the `Interned` is moved into the vec, which means the borrow made at 4 is untracked when Miri executes the debug assertions. The fix here is to make the assignment/move of the `Interned` happen first so Miri doesn't retag the inner `Box<T>`. This is accomplished by reordering the `self.vec.push` operation to immediately follow step 3. An additional unchecked index into the vec is used to get a shared access to that `Interned` object to later derive the `&'static T`. This commit also adds an additional test to resolve a slice from the symbol table to ensure Miri does not disagree as the `Interned` is moved during growth of the `SymbolTable`. Fixes #235.
TIL: https://rust-lang.github.io/rfcs/3346-t-opsem.html
Thanks again for your help @CAD97! |
See #235, #236. See #236 (comment). Introduce a new `PinBox` type which stores a boxed slice as a `NonNull` pointer. The pointer is converted back to a `Box` on drop.
bfbea04
to
71c9493
Compare
See #235, #236. See #236 (comment). Introduce a new `PinBox` type which stores a boxed slice as a `NonNull` pointer. The pointer is converted back to a `Box` on drop.
71c9493
to
c0d1eb6
Compare
Bad habit of not bothering to add an actual LICENSE file; the Cargo.toml records the SPDX license identifier as MIT OR Apache-2.0. However, I also consider Everything looks good to me. Theoretically the change to insertion ordering isn't needed once using |
Now that this is released in v1.9.0, I've filled a RustSec advisory here: I do not intend to file for a GitHub Security Advisory (GHSA) or a CVE. |
it looks like yup! merged 5 days ago, which means the cron running the weekly Miri CI would have hit it on Tuesday. |
I missed the |
This stacked borrows violation impacts all
SymbolTable
variants in this crate and has been present in all published versions.The
SymbolTable::intern
function previously worked like this:Cow<'static, T>
.Cow
into anInterned
which is an enum of either a&'static T
or aBox<T>
.&'static T
from theInterned
.Interned
into the vec.&'static T
to the map.As of at least rustc 1.73.0-nightly (31395ec38 2023-07-24), Miri pops all borrows from the
Interned
at step 5 when theInterned
is moved into the vec, which means the borrow made at 4 is untracked when Miri executes the debug assertions.The fix here is to make the assignment/move of the
Interned
happen first so Miri doesn't retag the innerBox<T>
. This is accomplished by reordering theself.vec.push
operation to immediately follow step 3. An additional unchecked index into the vec is used to get a shared access to thatInterned
object to later derive the&'static T
.This commit also adds an additional test to resolve a slice from the symbol table to ensure Miri does not disagree as the
Interned
is moved during growth of theSymbolTable
.Fixes #235.