From 6e4264bf27882dfee5276e18834ceb9edb040c23 Mon Sep 17 00:00:00 2001 From: Tim Diekmann <21277928+TimDiekmann@users.noreply.github.com> Date: Sun, 7 Apr 2019 20:52:12 +0200 Subject: [PATCH 1/6] Add `calloc` --- src/fn_call.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/fn_call.rs b/src/fn_call.rs index 038f5ed8a047..911f76929d5a 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -93,6 +93,28 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<' this.write_scalar(Scalar::Ptr(ptr.with_default_tag()), dest)?; } } + "calloc" => { + let items = this.read_scalar(args[0])?.to_usize(this)?; + let count = this.read_scalar(args[1])?.to_usize(this)?; + let size = if let Some(size) = items.checked_add(count) { + size + } else { + return err!(MachineError(format!( + "calloc: overflow of items * size: {} * {}", + items, size, + ))); + }; + if size == 0 { + this.write_null(dest)?; + } else { + let align = this.tcx.data_layout.pointer_align.abi; + let ptr = this.memory_mut().allocate(Size::from_bytes(size), align, MiriMemoryKind::C.into()); + this.memory_mut() + .get_mut(ptr.alloc_id)? + .write_repeat(tcx, ptr, 0, Size::from_bytes(size))?; + this.write_scalar(Scalar::Ptr(ptr.with_default_tag()), dest)?; + } + } "posix_memalign" => { let ret = this.deref_operand(args[0])?; let align = this.read_scalar(args[1])?.to_usize(this)?; From d1d05c8b4127295717b6f893e22cf657b4dbf1db Mon Sep 17 00:00:00 2001 From: Tim Diekmann Date: Sun, 7 Apr 2019 21:09:21 +0200 Subject: [PATCH 2/6] Fix tagging order --- src/fn_call.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/fn_call.rs b/src/fn_call.rs index 911f76929d5a..062cc900e176 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -100,19 +100,21 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<' size } else { return err!(MachineError(format!( - "calloc: overflow of items * size: {} * {}", - items, size, + "calloc: overflow of items * count: {} * {}", + items, count, ))); }; if size == 0 { this.write_null(dest)?; } else { let align = this.tcx.data_layout.pointer_align.abi; - let ptr = this.memory_mut().allocate(Size::from_bytes(size), align, MiriMemoryKind::C.into()); + let ptr = this.memory_mut() + .allocate(Size::from_bytes(size), align, MiriMemoryKind::C.into()) + .with_default_tag(); this.memory_mut() .get_mut(ptr.alloc_id)? .write_repeat(tcx, ptr, 0, Size::from_bytes(size))?; - this.write_scalar(Scalar::Ptr(ptr.with_default_tag()), dest)?; + this.write_scalar(Scalar::Ptr(ptr), dest)?; } } "posix_memalign" => { From a59e155206ca596722a67e967848fa2d3e516e8c Mon Sep 17 00:00:00 2001 From: Tim Diekmann Date: Mon, 8 Apr 2019 01:12:44 +0200 Subject: [PATCH 3/6] Tidy up calloc code --- src/fn_call.rs | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/src/fn_call.rs b/src/fn_call.rs index 062cc900e176..2db23bd48c54 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -95,25 +95,16 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<' } "calloc" => { let items = this.read_scalar(args[0])?.to_usize(this)?; - let count = this.read_scalar(args[1])?.to_usize(this)?; - let size = if let Some(size) = items.checked_add(count) { - size - } else { - return err!(MachineError(format!( - "calloc: overflow of items * count: {} * {}", - items, count, - ))); - }; - if size == 0 { + let len = this.read_scalar(args[1])?.to_usize(this)?; + let bytes = items.checked_mul(len).ok_or_else(|| InterpError::Overflow(mir::BinOp::Mul))?; + + if bytes== 0 { this.write_null(dest)?; } else { + let size = Size::from_bytes(bytes); let align = this.tcx.data_layout.pointer_align.abi; - let ptr = this.memory_mut() - .allocate(Size::from_bytes(size), align, MiriMemoryKind::C.into()) - .with_default_tag(); - this.memory_mut() - .get_mut(ptr.alloc_id)? - .write_repeat(tcx, ptr, 0, Size::from_bytes(size))?; + let ptr = this.memory_mut().allocate(size, align, MiriMemoryKind::C.into()).with_default_tag(); + this.memory_mut().get_mut(ptr.alloc_id)?.write_repeat(tcx, ptr, 0, size)?; this.write_scalar(Scalar::Ptr(ptr), dest)?; } } From fa0755c9fd9f7c43fbd313db32935ff37e588ee2 Mon Sep 17 00:00:00 2001 From: Tim Diekmann Date: Mon, 8 Apr 2019 01:12:50 +0200 Subject: [PATCH 4/6] Add calloc test --- tests/run-pass/calloc.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/run-pass/calloc.rs diff --git a/tests/run-pass/calloc.rs b/tests/run-pass/calloc.rs new file mode 100644 index 000000000000..8e8e2e5f10f4 --- /dev/null +++ b/tests/run-pass/calloc.rs @@ -0,0 +1,26 @@ +//ignore-windows: Uses POSIX APIs + +#![feature(rustc_private)] + +use core::slice; + +extern crate libc; + +fn main() { + unsafe { + let p1 = libc::calloc(0, 0); + assert!(p1.is_null()); + + let p2 = libc::calloc(20, 0); + assert!(p2.is_null()); + + let p3 = libc::calloc(0, 20); + assert!(p3.is_null()); + + let p4 = libc::calloc(4, 8) as *const u8; + assert!(!p4.is_null()); + + let slice = slice::from_raw_parts(p4, 4 * 8); + assert_eq!(&slice, &[0_u8; 4 * 8]); + } +} From fdefac8599a385a87de02f06d5a77f726a524904 Mon Sep 17 00:00:00 2001 From: Tim Diekmann Date: Mon, 8 Apr 2019 01:26:52 +0200 Subject: [PATCH 5/6] Fix calloc test Forgot to free the memory. Miri found the bug :) --- tests/run-pass/calloc.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/run-pass/calloc.rs b/tests/run-pass/calloc.rs index 8e8e2e5f10f4..4c520da85e87 100644 --- a/tests/run-pass/calloc.rs +++ b/tests/run-pass/calloc.rs @@ -17,10 +17,10 @@ fn main() { let p3 = libc::calloc(0, 20); assert!(p3.is_null()); - let p4 = libc::calloc(4, 8) as *const u8; + let p4 = libc::calloc(4, 8); assert!(!p4.is_null()); - - let slice = slice::from_raw_parts(p4, 4 * 8); + let slice = slice::from_raw_parts(p4 as *const u8, 4 * 8); assert_eq!(&slice, &[0_u8; 4 * 8]); + libc::free(p4); } } From 32d01263a96d1dfca9b484aba74f97a887c4a24a Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Mon, 8 Apr 2019 10:44:02 +0200 Subject: [PATCH 6/6] Update src/fn_call.rs Co-Authored-By: TimDiekmann <21277928+TimDiekmann@users.noreply.github.com> --- 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 2db23bd48c54..83eb37708e8e 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -98,7 +98,7 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<' let len = this.read_scalar(args[1])?.to_usize(this)?; let bytes = items.checked_mul(len).ok_or_else(|| InterpError::Overflow(mir::BinOp::Mul))?; - if bytes== 0 { + if bytes == 0 { this.write_null(dest)?; } else { let size = Size::from_bytes(bytes);