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.
For
Vec
, the use of.get_unchecked_mut(len)
dereferences to&mut [T]
over the initialized length (same aslen
), then forms&mut T
at offsetlen
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::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.