From 0e6deee76ef49e44d1089d6f2b8f9966a1c2db0a Mon Sep 17 00:00:00 2001 From: Tim Diekmann Date: Thu, 18 Apr 2019 01:17:19 +0200 Subject: [PATCH 1/3] Add `realloc` --- src/fn_call.rs | 17 +++++++++++++++++ tests/run-pass/realloc.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 tests/run-pass/realloc.rs diff --git a/src/fn_call.rs b/src/fn_call.rs index 64dcce161dd7..6706cc1fbc3c 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -148,6 +148,23 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<' } } + "realloc" => { + let ptr = this.read_scalar(args[0])?.to_ptr()?; + 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.with_default_tag()), dest)?; + } + "__rust_alloc" => { let size = this.read_scalar(args[0])?.to_usize(this)?; let align = this.read_scalar(args[1])?.to_usize(this)?; diff --git a/tests/run-pass/realloc.rs b/tests/run-pass/realloc.rs new file mode 100644 index 000000000000..594fec717e97 --- /dev/null +++ b/tests/run-pass/realloc.rs @@ -0,0 +1,31 @@ +//ignore-windows: Uses POSIX APIs + +#![feature(rustc_private)] + +use core::slice; + +extern crate libc; + +fn main() { + unsafe { + // Use calloc for initialized memory + let p1 = libc::calloc(20, 1); + + // old size < new size + let p2 = libc::realloc(p1, 40); + let slice = slice::from_raw_parts(p2 as *const u8, 20); + assert_eq!(&slice, &[0_u8; 20]); + + // old size == new size + let p3 = libc::realloc(p2, 40); + let slice = slice::from_raw_parts(p3 as *const u8, 20); + assert_eq!(&slice, &[0_u8; 20]); + + // old size > new size + let p4 = libc::realloc(p3, 10); + let slice = slice::from_raw_parts(p4 as *const u8, 10); + assert_eq!(&slice, &[0_u8; 10]); + + libc::free(p4); + } +} From afb64232dbc30047e001c1a24abc9de485b78d04 Mon Sep 17 00:00:00 2001 From: Tim Diekmann Date: Thu, 18 Apr 2019 12:39:18 +0200 Subject: [PATCH 2/3] Fix for latest upstream update --- src/fn_call.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fn_call.rs b/src/fn_call.rs index 7b1ea73eb80f..310b57641904 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -162,7 +162,7 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<' align, MiriMemoryKind::C.into(), )?; - this.write_scalar(Scalar::Ptr(new_ptr.with_default_tag()), dest)?; + this.write_scalar(Scalar::Ptr(new_ptr), dest)?; } "__rust_alloc" => { From 9ecc07c9b2df3cf88223d97ddea95a61a548e09e Mon Sep 17 00:00:00 2001 From: Tim Diekmann Date: Thu, 18 Apr 2019 15:20:32 +0200 Subject: [PATCH 3/3] 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); + } }