diff --git a/src/shims/unix/foreign_items.rs b/src/shims/unix/foreign_items.rs index 08f64e499b..b5165548d1 100644 --- a/src/shims/unix/foreign_items.rs +++ b/src/shims/unix/foreign_items.rs @@ -259,16 +259,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let einval = this.eval_libc_i32("EINVAL"); this.write_int(einval, dest)?; } else { - if size == 0 { - this.write_null(&ret)?; - } else { - let ptr = this.allocate_ptr( - Size::from_bytes(size), - Align::from_bytes(align).unwrap(), - MiriMemoryKind::C.into(), - )?; - this.write_pointer(ptr, &ret)?; - } + let ptr = this.allocate_ptr( + Size::from_bytes(size), + Align::from_bytes(align).unwrap(), + MiriMemoryKind::C.into(), + )?; + this.write_pointer(ptr, &ret)?; this.write_null(dest)?; } } diff --git a/tests/fail-dep/libc/posix_memalign_size_zero_double_free.rs b/tests/fail-dep/libc/posix_memalign_size_zero_double_free.rs new file mode 100644 index 0000000000..b6b7b007f2 --- /dev/null +++ b/tests/fail-dep/libc/posix_memalign_size_zero_double_free.rs @@ -0,0 +1,14 @@ +//@ignore-target-windows: No posix_memalign on Windows + +use std::ptr; + +fn main() { + let mut ptr: *mut libc::c_void = ptr::null_mut(); + let align = 64; + let size = 0; + unsafe { + let _ = libc::posix_memalign(&mut ptr, align, size); + libc::free(ptr); + libc::free(ptr); //~ERROR: dangling + } +} diff --git a/tests/fail-dep/libc/posix_memalign_size_zero_double_free.stderr b/tests/fail-dep/libc/posix_memalign_size_zero_double_free.stderr new file mode 100644 index 0000000000..3ed117c5a0 --- /dev/null +++ b/tests/fail-dep/libc/posix_memalign_size_zero_double_free.stderr @@ -0,0 +1,25 @@ +error: Undefined Behavior: memory access failed: ALLOC has been freed, so this pointer is dangling + --> $DIR/posix_memalign_size_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/posix_memalign_size_zero_double_free.rs:LL:CC + | +LL | let _ = libc::posix_memalign(&mut ptr, align, size); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: ALLOC was deallocated here: + --> $DIR/posix_memalign_size_zero_double_free.rs:LL:CC + | +LL | libc::free(ptr); + | ^^^^^^^^^^^^^^^ + = note: BACKTRACE (of the first span): + = note: inside `main` at $DIR/posix_memalign_size_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 + diff --git a/tests/fail-dep/libc/posix_memalign_size_zero_leak.rs b/tests/fail-dep/libc/posix_memalign_size_zero_leak.rs new file mode 100644 index 0000000000..1a4c9605fe --- /dev/null +++ b/tests/fail-dep/libc/posix_memalign_size_zero_leak.rs @@ -0,0 +1,10 @@ +//@ignore-target-windows: No posix_memalign on Windows + +use std::ptr; + +fn main() { + let mut ptr: *mut libc::c_void = ptr::null_mut(); + let align = 64; + let size = 0; + let _ = unsafe { libc::posix_memalign(&mut ptr, align, size) }; //~ERROR: memory leak +} diff --git a/tests/fail-dep/libc/posix_memalign_size_zero_leak.stderr b/tests/fail-dep/libc/posix_memalign_size_zero_leak.stderr new file mode 100644 index 0000000000..7ea0fa3146 --- /dev/null +++ b/tests/fail-dep/libc/posix_memalign_size_zero_leak.stderr @@ -0,0 +1,15 @@ +error: memory leaked: ALLOC (C heap, size: 0, align: 64), allocated here: + --> $DIR/posix_memalign_size_zero_leak.rs:LL:CC + | +LL | let _ = unsafe { libc::posix_memalign(&mut ptr, align, size) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: BACKTRACE: + = note: inside `main` at $DIR/posix_memalign_size_zero_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 + diff --git a/tests/pass-dep/libc/libc-mem.rs b/tests/pass-dep/libc/libc-mem.rs index 5df3ace749..b36fb436b5 100644 --- a/tests/pass-dep/libc/libc-mem.rs +++ b/tests/pass-dep/libc/libc-mem.rs @@ -190,11 +190,10 @@ fn test_memalign() { let align = 64; let size = 0; assert_eq!(libc::posix_memalign(&mut ptr, align, size), 0); - // We are not required to return null if size == 0, but we currently do. - // It's fine to remove this assert if we start returning non-null pointers. - assert!(ptr.is_null()); + // Non-null pointer is returned if size == 0. + // (This is not a guarantee, it just reflects our current behavior.) + assert!(!ptr.is_null()); assert!(ptr.is_aligned_to(align)); - // Regardless of what we return, it must be `free`able. libc::free(ptr); }