this.write_scalar(Scalar::Ptr(ptr.with_default_tag()), dest)?;
}
}
+ "posix_memalign" => {
+ let ret = this.deref_operand(args[0])?;
+ let align = this.read_scalar(args[1])?.to_usize(this)?;
+ let size = this.read_scalar(args[2])?.to_usize(this)?;
+ // align must be a power of 2, and also at least ptr-sized (wtf, POSIX)
+ if !align.is_power_of_two() {
+ return err!(HeapAllocNonPowerOfTwoAlignment(align));
+ }
+ if align < this.pointer_size().bytes() {
+ return err!(MachineError(format!(
+ "posix_memalign: alignment must be at least the size of a pointer, but is {}",
+ align,
+ )));
+ }
+ if size == 0 {
+ this.write_null(ret.into())?;
+ } else {
+ let ptr = this.memory_mut().allocate(
+ Size::from_bytes(size),
+ Align::from_bytes(align).unwrap(),
+ MiriMemoryKind::C.into()
+ );
+ this.write_scalar(Scalar::Ptr(ptr.with_default_tag()), ret.into())?;
+ }
+ this.write_null(dest)?;
+ }
"free" => {
let ptr = this.read_scalar(args[0])?.not_undef()?;
#![feature(box_syntax)]
+#![feature(allocator_api)]
+
+use std::alloc::{Global, Alloc, Layout, System};
fn make_box() -> Box<(i16, i16)> {
Box::new((1, 2))
assert_eq!(s.capacity(), 9);
}
+fn check_overalign_requests<T: Alloc>(mut allocator: T) {
+ let size = 8;
+ let align = 16; // greater than size
+ let iterations = 1; // Miri is deterministic, no need to try many times
+ unsafe {
+ let pointers: Vec<_> = (0..iterations).map(|_| {
+ allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap()
+ }).collect();
+ for &ptr in &pointers {
+ assert_eq!((ptr.as_ptr() as usize) % align, 0,
+ "Got a pointer less aligned than requested")
+ }
+
+ // Clean up
+ for &ptr in &pointers {
+ allocator.dealloc(ptr, Layout::from_size_align(size, align).unwrap())
+ }
+ }
+}
+
fn main() {
assert_eq!(*make_box(), (1, 2));
assert_eq!(*make_box_syntax(), (1, 2));
allocate_reallocate();
+
+ check_overalign_requests(System);
+ check_overalign_requests(Global);
}