-
Notifications
You must be signed in to change notification settings - Fork 146
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
Use MaybeUninit for storage of inline items #162
Conversation
If you're bumping MSRV, you might as well get rid of hacks such as #158 |
I saw that but didn't want to change too many unrelated things in this PR. I'm willing to make that change too if desired though. |
FWIW this PR fixes instances of UB in firefox, among other things. e.g (not a comprehensive list):
|
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.
So this makes SmallVec<[T; size]>
use MaybeUninit<[T; size]>
, shouldn't it conceptually use [MaybeUninit<T>; size]
?
Anyhow this looks fine, with the Cargo.lock
updated to account for the new minimum rust version change.
lib.rs
Outdated
// this check should be optimized away entirely for valid ones. | ||
assert!( | ||
(mem::size_of::<A>() == A::size() * mem::size_of::<A::Item>()) && | ||
(mem::align_of::<A>() >= mem::align_of::<A::Item>()) |
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.
nit: Parens here are redundant.
This is designed to merged after servo#162, as it deprecates a function that should be no longer necessary on newer Rust versions.
This is designed to merged after servo#162, as it deprecates a function that should be no longer necessary on newer Rust versions.
This is designed to merged after servo#162, as it deprecates a function that should be no longer necessary on newer Rust versions.
This is designed to merged after servo#162, as it deprecates a function that should be no longer necessary on newer Rust versions.
☔ The latest upstream changes (presumably #167) made this pull request unmergeable. Please resolve the merge conflicts. |
This would be a good change to land given the new |
@thomcc Do you have some spare cycles to look at the merge conflict?
|
Ah, right, thanks for the prod. Sorry about the delay, I'll update it tonight. |
This includes two breaking changes, in addition to the fact that it will require a MSRV bump: 1. The functions on the `Array` trait `ptr` and `ptr_mut` have been removed. Because these took a `&self`/`&mut self` argument, there's no way for us to call them when we only have a `MaybeUninit<A>`. Now, we just use the memory of the object directly. This limits the flexibility of custom implementations of `Array`, (they can no longer return pointers to values other than themselves) but I imagine this is very rare and was probably broken somehow to begin with. Anybody who does this will get a compile error. 2. `from_buf_and_len_unchecked` now takes a MaybeUninit<A>, so that callers have the option of only partially initializing the array.
IIUC there's no difference in practice. And this is less of a change to the API surface, and less work to implement. But yeah... possibly?
Not sure what you mean by this. This repository has Cargo.lock in it's .gitignore. |
I meant the Cargo.toml version, sorry. But I guess we can just update it later if you want. Anyhow this looks good. |
I've rebased the branch so that it's up to date with the latest master, but I'm... unsure what github is still upset about regarding conflicts. 😅 It even says on master...thomcc:maybe-uninit that it's able to be merged... Maybe it will sort itself out in a bit... |
@bors-servo r+ |
📌 Commit 28c09eb has been approved by |
Use MaybeUninit for storage of inline items Fixes #126 I didn't see a PR open for this, and was poking around so I figured I'd do it. Sorry if I stepped on anyone's toes. This should remove the use of mem::uninitialized, and ensure that all values used directly or via references are initialized. (e.g. T and &T are always initialized, but `*const T` and `*mut T` may not be, which is fine). With these changes, `miri` passes. I also changed the CI to run `miri`, hopefully. That said, this includes three breaking changes, so it will require a min version bump. 1. The functions on the `Array` trait `ptr` and `ptr_mut` have been removed. Because these took a `&self`/`&mut self` argument, there's no way for us to call them when we only have a `MaybeUninit<A>`. Now, we just use the memory of the object directly. This limits the flexibility of custom implementations of `Array`, as they can no longer return pointers to values other than themselves, but hopefully nobody does that (IMO there's a pretty good case for sealing `Array`...) 2. `SmallVec::from_buf_and_len_unchecked` now takes a MaybeUninit<A> and not an A. This means that callers have the option of only partially initializing said array without risking nasal demons. I can undo this change if desired, as it's 3. Rust 1.36.0 is required to use MaybeUninit, so this bumps the MSRV from 1.20.0 to 1.36.0. It seems tricky to make the use of MaybeUninit optional here, at least without a bunch or work (ignoring the fact that doing so would require adding a build.rs which parses `rustc -Vv` to tell us the version). <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/rust-smallvec/162) <!-- Reviewable:end -->
☀️ Test successful - checks-travis |
This is designed to merged after #162, as it deprecates a function that should be no longer necessary on newer Rust versions.
@@ -11,4 +11,5 @@ script: | | |||
([ $TRAVIS_RUST_VERSION != nightly ] || cargo check --verbose --no-default-features) && | |||
([ $TRAVIS_RUST_VERSION != nightly ] || cargo test --verbose --features union) && | |||
([ $TRAVIS_RUST_VERSION != nightly ] || cargo test --verbose --all-features) && | |||
([ $TRAVIS_RUST_VERSION != nightly ] || cargo bench --verbose bench) | |||
([ $TRAVIS_RUST_VERSION != nightly ] || cargo bench --verbose bench) && | |||
([ $TRAVIS_RUST_VERSION != nightly ] || bash ./scripts/run_miri.sh) |
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.
This is awesome -- I had adding Miri here on my TODO list but didn't get around to actually do that yet. :)
Any chance we could do a minor release with this too so downstream projects can run miri again? :) |
I would prefer to do this in the next major release, because it increases our minimum Rust version to 1.36 (from 1.20 in the previous release). Although a Rust version increase is not a breaking change at the source level, it still causes problems for downstream crates when it happens in a minor update to a widely-used library. #73 is tracking the breaking changes going into the next major release. I'll try to get the last items merged in the next few days, and then publish the release. |
This is designed to merged after servo#162, as it deprecates a function that should be no longer necessary on newer Rust versions.
* [breaking change] Use `MaybeUninit` internally to avoid possible undefined behavior (servo#162, servo#170). * [breaking change] The `drain` method now takes a range argument, just like the standard `Vec::drain` (servo#145). * [breaking change] Remove the `unreachable` function and replace it with the new standard `unreachable_unchecked` function (servo#164). * [breaking change] Use `no_std` by default. This crate depends only on `core` and `alloc` by default. If the optional `write` feature is enabled then it depends on `std` so that `SmallVec<[u8, _]>` can implement the `std::io::Write` trait (servo#173). * Add support for 96-element small vectors, `SmallVec<[T; 96]>` (servo#163). * Iterators now implement `FusedIterator` (servo#172). * Indexing now uses the standard `SliceIndex` trait (servo#166). * Remove the deprecated `VecLike` trait (servo#165). * Use `NonNull` internally (servo#171). * Add automatic fuzz testing and MIRI testing (servo#168, servo#162). * Update syntax and formatting to Rust 2018 standard (servo#174, servo#167).
Version 1.0.0 * Requires Rust 1.36 or later. * [breaking change] Use `MaybeUninit` to avoid possible undefined behavior (#162, #170). * [breaking change] The `drain` method now takes a range argument, just like the standard `Vec::drain` (#145). * [breaking change] Remove the `unreachable` function and replace it with the new standard `unreachable_unchecked` function (#164). * [breaking change] Use `no_std` by default. This crate depends only on `core` and `alloc` by default. If the optional `write` feature is enabled then it depends on `std` so that `SmallVec<[u8;_]>` can implement the `std::io::Write` trait (#173). * Add support for 96-element small vectors, `SmallVec<[T; 96]>` (#163). * Iterators now implement `FusedIterator` (#172). * Indexing now uses the standard `SliceIndex` trait (#166). * Remove the deprecated `VecLike` trait (#165). * Use `NonNull` internally (#171). * Add automatic fuzz testing and MIRI testing (#168, #162). * Update syntax and formatting to Rust 2018 standard (#174, #167).
When rust-lang/rust#66059 lands, many users of the 0.6 series will see their programs break because of the incorrect |
If the concern is the MSRV bump, one option is to use https://crates.io/crates/maybe-uninit: for Rust versions prior to 1.36, that's not actually fixing the UB, but it is certainly no worse than what smallvec currently does. And for newer Rust versions, the UB is fixed. |
This is a backport of servo#162 to the smallvec 0.6 branch. To avoid bumping the minimum Rust version, the `maybe-uninit` crate is used in place of `std::mem::MaybeUninit`. To avoid breaking changes, the `Array::ptr` and `ptr_mut` methods are retained but are no longer used, and the API to `from_buf_and_len_unchecked` is unchanged.
Submitted #180 to backport the MaybeUninit changes to 0.6 using the |
This is a backport of servo#162 to the smallvec 0.6 branch. To avoid bumping the minimum Rust version, the `maybe-uninit` crate is used in place of `std::mem::MaybeUninit`. To avoid breaking changes, the `Array::ptr` and `ptr_mut` methods are retained but are no longer used, and the API to `from_buf_and_len_unchecked` is unchanged.
bump smallvec to 1.0 This includes servo/rust-smallvec#162, fixing an unsoundness in smallvec. See servo/rust-smallvec#175 for the 1.0 release announcement. Cc @mbrubeck @emilio
Fixes #126
I didn't see a PR open for this, and was poking around so I figured I'd do it. Sorry if I stepped on anyone's toes.
This should remove the use of mem::uninitialized, and ensure that all values used directly or via references are initialized. (e.g. T and &T are always initialized, but
*const T
and*mut T
may not be, which is fine).With these changes,
miri
passes. I also changed the CI to runmiri
, hopefully.That said, this includes three breaking changes, so it will require a min version bump.
The functions on the
Array
traitptr
andptr_mut
have been removed. Because these took a&self
/&mut self
argument, there's no way for us to call them when we only have aMaybeUninit<A>
. Now, we just use the memory of the object directly.This limits the flexibility of custom implementations of
Array
, as they can no longer return pointers to values other than themselves, but hopefully nobody does that (IMO there's a pretty good case for sealingArray
...)SmallVec::from_buf_and_len_unchecked
now takes a MaybeUninit and not an A. This means that callers have the option of only partially initializing said array without risking nasal demons. I can undo this change if desired, as it'sRust 1.36.0 is required to use MaybeUninit, so this bumps the MSRV from 1.20.0 to 1.36.0. It seems tricky to make the use of MaybeUninit optional here, at least without a bunch or work (ignoring the fact that doing so would require adding a build.rs which parses
rustc -Vv
to tell us the version).This change is