vcombey / fallible_collections

impl fallible collections in rust, quite as describe in RFC 2116
Apache License 2.0
31 stars 14 forks source link

Use pointer `add` in `try_extend_from_slice_no_copy` #36

Closed cuviper closed 1 year ago

cuviper commented 1 year ago

For Vec, the use of .get_unchecked_mut(len) dereferences to &mut [T] over the initialized length (same as len), then forms &mut T at offset len which is past the end.

Miri reports an error for this: ``` test vec::tests::tryvec_extend_from_slice ... error: Undefined Behavior: trying to retag from <207013> for Unique permission at alloc82282[0x0], but that tag does not exist in the borrow stack for this location --> /home/jistone/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/mod.rs:443:18 | 443 | unsafe { &mut *index.get_unchecked_mut(self) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | trying to retag from <207013> for Unique permission at alloc82282[0x0], but that tag does not exist in the borrow stack for this location | this error occurs as part of retag at alloc82282[0x0..0x1] | = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information help: <207013> would have been created here, but this is a zero-size retag ([0x0..0x0]) so the tag in question does not exist anywhere --> src/vec.rs:627:34 | 627 | core::ptr::write(self.get_unchecked_mut(len), element.try_clone()?); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: BACKTRACE (of the first span): = note: inside `core::slice::::get_unchecked_mut::` at /home/jistone/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/slice/mod.rs:443:18: 443:53 note: inside ` as vec::FallibleVec>::try_extend_from_slice_no_copy` --> src/vec.rs:627:34 | 627 | core::ptr::write(self.get_unchecked_mut(len), element.try_clone()?); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: inside ` as std::convert::TryFrom<&[u8]>>::try_from` --> src/vec.rs:367:9 | 367 | v.inner.try_extend_from_slice_no_copy(value)?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: inside `<&[u8] as std::convert::TryInto>>::try_into` at /home/jistone/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/convert/mod.rs:767:9: 767:26 note: inside `vec::tests::tryvec_extend_from_slice` --> src/vec.rs:949:35 | 949 | let mut vec: TryVec = b"foo".as_ref().try_into().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ note: inside closure --> src/vec.rs:948:35 | 947 | #[test] | ------- in this procedural macro expansion 948 | fn tryvec_extend_from_slice() { | ^ = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) ```

The code only wants a pointer to write though, so we can instead use .add(len) from the base pointer to get the next uninitialized location.