Skip to content

Commit

Permalink
to alloc.rs
Browse files Browse the repository at this point in the history
  • Loading branch information
devnexen committed May 17, 2024
1 parent 34ef27e commit 9d0eb2a
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 52 deletions.
38 changes: 38 additions & 0 deletions src/shims/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,4 +172,42 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
}
}
}

fn aligned_alloc(
&mut self,
align: u64,
size: u64,
) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
let this = self.eval_context_mut();
// Alignment must be a power of 2, and "supported by the implementation".
// We decide that "supported by the implementation" means that the
// size must be a multiple of the alignment. (This restriction seems common
// enough that it is stated on <https://en.cppreference.com/w/c/memory/aligned_alloc>
// as a general rule, but the actual standard has no such rule.)
// If any of these are violated, we have to return NULL.
// All fundamental alignments must be supported.
//
// macOS and Illumos are buggy in that they require the alignment
// to be at least the size of a pointer, so they do not support all fundamental
// alignments. We do not emulate those platform bugs.
//
// Linux also sets errno to EINVAL, but that's non-standard behavior that we do not
// emulate.
// FreeBSD says some of these cases are UB but that's violating the C standard.
// http://en.cppreference.com/w/cpp/memory/c/aligned_alloc
// Linux: https://linux.die.net/man/3/aligned_alloc
// FreeBSD: https://man.freebsd.org/cgi/man.cgi?query=aligned_alloc&apropos=0&sektion=3&manpath=FreeBSD+9-current&format=html
match size.checked_rem(align) {
Some(0) if align.is_power_of_two() => {
let align = align.max(this.malloc_align(size).bytes());
let ptr = this.allocate_ptr(
Size::from_bytes(size),
Align::from_bytes(align).unwrap(),
MiriMemoryKind::C.into(),
)?;
Ok(ptr.into())
}
_ => Ok(Pointer::null()),
}
}
}
35 changes: 2 additions & 33 deletions src/shims/unix/foreign_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use std::str;

use rustc_middle::ty::layout::LayoutOf;
use rustc_span::Symbol;
use rustc_target::abi::{Align, Size};
use rustc_target::spec::abi::Abi;

use crate::shims::alloc::EvalContextExt as _;
Expand Down Expand Up @@ -304,38 +303,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let align = this.read_target_usize(align)?;
let size = this.read_target_usize(size)?;

// Alignment must be a power of 2, and "supported by the implementation".
// We decide that "supported by the implementation" means that the
// size must be a multiple of the alignment. (This restriction seems common
// enough that it is stated on <https://en.cppreference.com/w/c/memory/aligned_alloc>
// as a general rule, but the actual standard has no such rule.)
// If any of these are violated, we have to return NULL.
// All fundamental alignments must be supported.
//
// macOS and Illumos are buggy in that they require the alignment
// to be at least the size of a pointer, so they do not support all fundamental
// alignments. We do not emulate those platform bugs.
//
// Linux also sets errno to EINVAL, but that's non-standard behavior that we do not
// emulate.
// FreeBSD says some of these cases are UB but that's violating the C standard.
// http://en.cppreference.com/w/cpp/memory/c/aligned_alloc
// Linux: https://linux.die.net/man/3/aligned_alloc
// FreeBSD: https://man.freebsd.org/cgi/man.cgi?query=aligned_alloc&apropos=0&sektion=3&manpath=FreeBSD+9-current&format=html
match size.checked_rem(align) {
Some(0) if align.is_power_of_two() => {
let align = align.max(this.malloc_align(size).bytes());
let ptr = this.allocate_ptr(
Size::from_bytes(size),
Align::from_bytes(align).unwrap(),
MiriMemoryKind::C.into(),
)?;
this.write_pointer(ptr, dest)?;
},
_ => {
this.write_null(dest)?;
}
}
let res = this.aligned_alloc(align, size)?;
this.write_pointer(res, dest)?;
}

// Dynamic symbol loading
Expand Down
21 changes: 2 additions & 19 deletions src/shims/wasi/foreign_items.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use rustc_span::Symbol;
use rustc_target::abi::{Align, Size};
use rustc_target::spec::abi::Abi;

use crate::shims::alloc::EvalContextExt as _;
Expand Down Expand Up @@ -33,24 +32,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let align = this.read_target_usize(align)?;
let size = this.read_target_usize(size)?;

// Alignment must be a power of 2.
// wasi libc makes no check for the size though but
// here we do check it is a multiple of alignment.

match size.checked_rem(align) {
Some(0) if align.is_power_of_two() => {
let align = align.max(this.malloc_align(size).bytes());
let ptr = this.allocate_ptr(
Size::from_bytes(size),
Align::from_bytes(align).unwrap(),
MiriMemoryKind::C.into(),
)?;
this.write_pointer(ptr, dest)?;
}
_ => {
this.write_null(dest)?;
}
}
let res = this.aligned_alloc(align, size)?;
this.write_pointer(res, dest)?;
}

_ => return Ok(EmulateItemResult::NotSupported),
Expand Down

0 comments on commit 9d0eb2a

Please sign in to comment.