offset_from "same allocation" check is confused by int-to-ptr casts #3767
Closed
Description
This code fails with -Zmiri-disable-stacked-borrows
, but interestingly passes with SB:
use std::{mem::ManuallyDrop, slice};
fn extend_fail() {
let data = Data::allocate(b"hello");
assert_eq!(data.read(), b"hello");
let mut buffer = Vec::<u8>::with_capacity(1024);
buffer.extend(data.read());
assert_eq!(buffer.len(), 5);
}
fn main() {
extend_fail();
}
pub struct Data {
len: usize,
ptr: usize,
}
impl Data {
pub fn allocate(data: &[u8]) -> Self {
let mut data = ManuallyDrop::new(data.to_owned().into_boxed_slice());
Self {
len: data.len(),
ptr: data.as_mut_ptr() as usize,
}
}
pub fn read(&self) -> &[u8] {
unsafe {
// SAFETY: fine since we r/w it directly!
slice::from_raw_parts(self.ptr as *mut u8, self.len)
}
}
}
impl Drop for Data {
fn drop(&mut self) {
unsafe {
Vec::from_raw_parts(self.ptr as *mut u8, self.len, self.len);
}
}
}
gives
error: Undefined Behavior: `ptr_offset_from_unsigned` called on pointers into different allocations
--> /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/library/core/src/slice/iter.rs:136:1
|
136 | / iterator! {struct Iter -> *const T, &'a T, const, {/* no mut */}, as_ref, {
137 | | fn is_sorted_by<F>(self, mut compare: F) -> bool
138 | | where
139 | | Self: Sized,
... |
143 | | }
144 | | }}
| |__^ `ptr_offset_from_unsigned` called on pointers into different allocations
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `std::slice::Iter::<'_, u8>::make_slice` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/library/core/src/slice/iter/macros.rs:57:26: 57:48
= note: inside `std::slice::Iter::<'_, u8>::as_slice` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/library/core/src/slice/iter.rs:132:9: 132:26
= note: inside `<std::vec::Vec<u8> as std::vec::spec_extend::SpecExtend<&u8, std::slice::Iter<'_, u8>>>::spec_extend` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/library/alloc/src/vec/spec_extend.rs:54:21: 54:40
= note: inside `<std::vec::Vec<u8> as std::iter::Extend<&u8>>::extend::<&[u8]>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/library/alloc/src/vec/mod.rs:3251:9: 3251:43
note: inside `extend_fail`
--> x.rs:7:5
|
7 | buffer.extend(data.read());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
I think the "same allocation" check in the offset_from intrinsic doesn't work properly when there are wildcard pointers involved.
Metadata
Assignees
Labels
No labels