Skip to content

Commit a22e355

Browse files
committed
make realloc with a size of zero fail
1 parent 422d1fe commit a22e355

File tree

4 files changed

+31
-5
lines changed

4 files changed

+31
-5
lines changed

src/shims/foreign_items.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
278278
let this = self.eval_context_mut();
279279
let new_align = this.min_align(new_size, kind);
280280
if this.ptr_is_null(old_ptr)? {
281+
// Here we must behave like `malloc`.
281282
if new_size == 0 {
282283
Ok(Pointer::null())
283284
} else {
@@ -287,8 +288,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
287288
}
288289
} else {
289290
if new_size == 0 {
290-
this.deallocate_ptr(old_ptr, None, kind.into())?;
291-
Ok(Pointer::null())
291+
// C, in their infinite wisdom, made this UB.
292+
// <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2464.pdf>
293+
throw_ub_format!("`realloc` with a size of zero");
292294
} else {
293295
let new_ptr = this.reallocate_ptr(
294296
old_ptr,

tests/fail-dep/realloc-zero.rs

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//@ignore-target-windows: No libc on Windows
2+
3+
fn main() {
4+
unsafe {
5+
let p1 = libc::malloc(20);
6+
// C made this UB...
7+
let p2 = libc::realloc(p1, 0); //~ERROR: `realloc` with a size of zero
8+
assert!(p2.is_null());
9+
}
10+
}

tests/fail-dep/realloc-zero.stderr

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
error: Undefined Behavior: `realloc` with a size of zero
2+
--> $DIR/realloc-zero.rs:LL:CC
3+
|
4+
LL | let p2 = libc::realloc(p1, 0);
5+
| ^^^^^^^^^^^^^^^^^^^^ `realloc` with a size of zero
6+
|
7+
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
8+
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
9+
= note: BACKTRACE:
10+
= note: inside `main` at $DIR/realloc-zero.rs:LL:CC
11+
12+
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
13+
14+
error: aborting due to 1 previous error
15+

tests/pass-dep/malloc.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,8 @@ fn main() {
3434
}
3535

3636
unsafe {
37-
let p1 = libc::malloc(20);
38-
39-
let p2 = libc::realloc(p1, 0);
37+
// Realloc with size 0 is okay for the null pointer
38+
let p2 = libc::realloc(ptr::null_mut(), 0);
4039
assert!(p2.is_null());
4140
}
4241

0 commit comments

Comments
 (0)