diff --git a/src/fn_call.rs b/src/fn_call.rs index 038f5ed8a047..83eb37708e8e 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -93,6 +93,21 @@ 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 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, 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)?; + } + } "posix_memalign" => { let ret = this.deref_operand(args[0])?; let align = this.read_scalar(args[1])?.to_usize(this)?; diff --git a/tests/run-pass/calloc.rs b/tests/run-pass/calloc.rs new file mode 100644 index 000000000000..4c520da85e87 --- /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); + assert!(!p4.is_null()); + let slice = slice::from_raw_parts(p4 as *const u8, 4 * 8); + assert_eq!(&slice, &[0_u8; 4 * 8]); + libc::free(p4); + } +}