From 9ecc07c9b2df3cf88223d97ddea95a61a548e09e Mon Sep 17 00:00:00 2001 From: Tim Diekmann Date: Thu, 18 Apr 2019 15:20:32 +0200 Subject: [PATCH] Add handling for `nullptr` and `size == 0` --- src/fn_call.rs | 48 ++++++++++++++++++++++++++++----------- tests/run-pass/realloc.rs | 16 ++++++++++++- 2 files changed, 50 insertions(+), 14 deletions(-) diff --git a/src/fn_call.rs b/src/fn_call.rs index 310b57641904..ae6aff10ac20 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -147,22 +147,44 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<' )?; } } - "realloc" => { - let ptr = this.read_scalar(args[0])?.to_ptr()?; + let old_ptr = this.read_scalar(args[0])?.not_undef()?; let new_size = this.read_scalar(args[1])?.to_usize(this)?; let align = this.tcx.data_layout.pointer_align.abi; - let memory = this.memory_mut(); - let old_size = memory.get(ptr.alloc_id)?.bytes.len(); - let new_ptr = memory.reallocate( - ptr, - Size::from_bytes(old_size as u64), - align, - Size::from_bytes(new_size), - align, - MiriMemoryKind::C.into(), - )?; - this.write_scalar(Scalar::Ptr(new_ptr), dest)?; + if old_ptr.is_null_ptr(this) { + if new_size == 0 { + this.write_null(dest)?; + } else { + let new_ptr = this.memory_mut().allocate( + Size::from_bytes(new_size), + align, + MiriMemoryKind::C.into() + ); + this.write_scalar(Scalar::Ptr(new_ptr), dest)?; + } + } else { + let old_ptr = old_ptr.to_ptr()?; + let memory = this.memory_mut(); + let old_size = Size::from_bytes(memory.get(old_ptr.alloc_id)?.bytes.len() as u64); + if new_size == 0 { + memory.deallocate( + old_ptr, + Some((old_size, align)), + MiriMemoryKind::C.into(), + )?; + this.write_null(dest)?; + } else { + let new_ptr = memory.reallocate( + old_ptr, + old_size, + align, + Size::from_bytes(new_size), + align, + MiriMemoryKind::C.into(), + )?; + this.write_scalar(Scalar::Ptr(new_ptr), dest)?; + } + } } "__rust_alloc" => { diff --git a/tests/run-pass/realloc.rs b/tests/run-pass/realloc.rs index 594fec717e97..c23b3e645c70 100644 --- a/tests/run-pass/realloc.rs +++ b/tests/run-pass/realloc.rs @@ -2,7 +2,7 @@ #![feature(rustc_private)] -use core::slice; +use core::{slice, ptr}; extern crate libc; @@ -28,4 +28,18 @@ fn main() { libc::free(p4); } + + unsafe { + let p1 = libc::malloc(20); + + let p2 = libc::realloc(p1, 0); + assert!(p2.is_null()); + } + + unsafe { + let p1 = libc::realloc(ptr::null_mut(), 20); + assert!(!p1.is_null()); + + libc::free(p1); + } }