Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 13 additions & 14 deletions src/shims/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
if kind == MiriMemoryKind::WinHeap || size >= min_align {
return Align::from_bytes(min_align).unwrap();
}
if size == 0 {
return Align::ONE;
}
// We have `size < min_align`. Round `size` *down* to the next power of two and use that.
fn prev_power_of_two(x: u64) -> u64 {
let next_pow2 = x.next_power_of_two();
Expand Down Expand Up @@ -85,21 +88,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
kind: MiriMemoryKind,
) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
let this = self.eval_context_mut();
if size == 0 {
Ok(Pointer::null())
} else {
let align = this.min_align(size, kind);
let ptr = this.allocate_ptr(Size::from_bytes(size), align, kind.into())?;
if zero_init {
// We just allocated this, the access is definitely in-bounds and fits into our address space.
this.write_bytes_ptr(
ptr.into(),
iter::repeat(0u8).take(usize::try_from(size).unwrap()),
)
.unwrap();
}
Ok(ptr.into())
let align = this.min_align(size, kind);
let ptr = this.allocate_ptr(Size::from_bytes(size), align, kind.into())?;
if zero_init {
// We just allocated this, the access is definitely in-bounds and fits into our address space.
this.write_bytes_ptr(
ptr.into(),
iter::repeat(0u8).take(usize::try_from(size).unwrap()),
)
.unwrap();
}
Ok(ptr.into())
}

fn free(
Expand Down
7 changes: 7 additions & 0 deletions tests/fail-dep/libc/malloc_zero_double_free.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
fn main() {
unsafe {
let ptr = libc::malloc(0);
libc::free(ptr);
libc::free(ptr); //~ERROR: dangling
}
}
25 changes: 25 additions & 0 deletions tests/fail-dep/libc/malloc_zero_double_free.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
error: Undefined Behavior: memory access failed: ALLOC has been freed, so this pointer is dangling
--> $DIR/malloc_zero_double_free.rs:LL:CC
|
LL | libc::free(ptr);
| ^^^^^^^^^^^^^^^ memory access failed: ALLOC has been freed, so this pointer is dangling
|
= 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
help: ALLOC was allocated here:
--> $DIR/malloc_zero_double_free.rs:LL:CC
|
LL | let ptr = libc::malloc(0);
| ^^^^^^^^^^^^^^^
help: ALLOC was deallocated here:
--> $DIR/malloc_zero_double_free.rs:LL:CC
|
LL | libc::free(ptr);
| ^^^^^^^^^^^^^^^
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/malloc_zero_double_free.rs:LL:CC

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

error: aborting due to 1 previous error

5 changes: 5 additions & 0 deletions tests/fail-dep/libc/malloc_zero_memory_leak.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fn main() {
unsafe {
let _ptr = libc::malloc(0); //~ERROR: memory leak
}
}
15 changes: 15 additions & 0 deletions tests/fail-dep/libc/malloc_zero_memory_leak.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
error: memory leaked: ALLOC (C heap, size: 0, align: 1), allocated here:
--> $DIR/malloc_zero_memory_leak.rs:LL:CC
|
LL | let _ptr = libc::malloc(0);
| ^^^^^^^^^^^^^^^
|
= note: BACKTRACE:
= note: inside `main` at $DIR/malloc_zero_memory_leak.rs:LL:CC

note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace

note: the evaluated program leaked memory, pass `-Zmiri-ignore-leaks` to disable this check

error: aborting due to 1 previous error

14 changes: 9 additions & 5 deletions tests/pass-dep/libc/libc-mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,10 @@ fn test_malloc() {
}

unsafe {
// Realloc with size 0 is okay for the null pointer
// Realloc with size 0 is okay for the null pointer (and acts like `malloc(0)`)
let p2 = libc::realloc(ptr::null_mut(), 0);
assert!(p2.is_null());
assert!(!p2.is_null());
libc::free(p2);
}

unsafe {
Expand All @@ -126,13 +127,16 @@ fn test_malloc() {
fn test_calloc() {
unsafe {
let p1 = libc::calloc(0, 0);
assert!(p1.is_null());
assert!(!p1.is_null());
libc::free(p1);

let p2 = libc::calloc(20, 0);
assert!(p2.is_null());
assert!(!p2.is_null());
libc::free(p2);

let p3 = libc::calloc(0, 20);
assert!(p3.is_null());
assert!(!p3.is_null());
libc::free(p3);

let p4 = libc::calloc(4, 8);
assert!(!p4.is_null());
Expand Down