Skip to content

Commit 7d7cf4d

Browse files
authored
Merge pull request #696 from TimDiekmann/realloc
Add `realloc`
2 parents ae9e9cb + 9ecc07c commit 7d7cf4d

File tree

2 files changed

+84
-0
lines changed

2 files changed

+84
-0
lines changed

src/fn_call.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,45 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
147147
)?;
148148
}
149149
}
150+
"realloc" => {
151+
let old_ptr = this.read_scalar(args[0])?.not_undef()?;
152+
let new_size = this.read_scalar(args[1])?.to_usize(this)?;
153+
let align = this.tcx.data_layout.pointer_align.abi;
154+
if old_ptr.is_null_ptr(this) {
155+
if new_size == 0 {
156+
this.write_null(dest)?;
157+
} else {
158+
let new_ptr = this.memory_mut().allocate(
159+
Size::from_bytes(new_size),
160+
align,
161+
MiriMemoryKind::C.into()
162+
);
163+
this.write_scalar(Scalar::Ptr(new_ptr), dest)?;
164+
}
165+
} else {
166+
let old_ptr = old_ptr.to_ptr()?;
167+
let memory = this.memory_mut();
168+
let old_size = Size::from_bytes(memory.get(old_ptr.alloc_id)?.bytes.len() as u64);
169+
if new_size == 0 {
170+
memory.deallocate(
171+
old_ptr,
172+
Some((old_size, align)),
173+
MiriMemoryKind::C.into(),
174+
)?;
175+
this.write_null(dest)?;
176+
} else {
177+
let new_ptr = memory.reallocate(
178+
old_ptr,
179+
old_size,
180+
align,
181+
Size::from_bytes(new_size),
182+
align,
183+
MiriMemoryKind::C.into(),
184+
)?;
185+
this.write_scalar(Scalar::Ptr(new_ptr), dest)?;
186+
}
187+
}
188+
}
150189

151190
"__rust_alloc" => {
152191
let size = this.read_scalar(args[0])?.to_usize(this)?;

tests/run-pass/realloc.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//ignore-windows: Uses POSIX APIs
2+
3+
#![feature(rustc_private)]
4+
5+
use core::{slice, ptr};
6+
7+
extern crate libc;
8+
9+
fn main() {
10+
unsafe {
11+
// Use calloc for initialized memory
12+
let p1 = libc::calloc(20, 1);
13+
14+
// old size < new size
15+
let p2 = libc::realloc(p1, 40);
16+
let slice = slice::from_raw_parts(p2 as *const u8, 20);
17+
assert_eq!(&slice, &[0_u8; 20]);
18+
19+
// old size == new size
20+
let p3 = libc::realloc(p2, 40);
21+
let slice = slice::from_raw_parts(p3 as *const u8, 20);
22+
assert_eq!(&slice, &[0_u8; 20]);
23+
24+
// old size > new size
25+
let p4 = libc::realloc(p3, 10);
26+
let slice = slice::from_raw_parts(p4 as *const u8, 10);
27+
assert_eq!(&slice, &[0_u8; 10]);
28+
29+
libc::free(p4);
30+
}
31+
32+
unsafe {
33+
let p1 = libc::malloc(20);
34+
35+
let p2 = libc::realloc(p1, 0);
36+
assert!(p2.is_null());
37+
}
38+
39+
unsafe {
40+
let p1 = libc::realloc(ptr::null_mut(), 20);
41+
assert!(!p1.is_null());
42+
43+
libc::free(p1);
44+
}
45+
}

0 commit comments

Comments
 (0)