Skip to content

Commit 13f1b5f

Browse files
committed
Auto merge of #1393 - RalfJung:arg-count-cleanup, r=RalfJung
Make sure we check argument count everywhere and argument size for non-stub shims
2 parents 2f974f6 + 40800cf commit 13f1b5f

File tree

4 files changed

+59
-35
lines changed

4 files changed

+59
-35
lines changed

src/shims/foreign_items/posix.rs

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
3434
this.write_scalar(Scalar::from_i32(result), dest)?;
3535
}
3636
"setenv" => {
37-
let &[name, value, _overwrite] = check_arg_count(args)?;
37+
let &[name, value, overwrite] = check_arg_count(args)?;
38+
this.read_scalar(overwrite)?.to_i32()?;
3839
let result = this.setenv(name, value)?;
3940
this.write_scalar(Scalar::from_i32(result), dest)?;
4041
}
@@ -51,8 +52,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
5152

5253
// File related shims
5354
"open" | "open64" => {
54-
let &[path, flag, _mode] = check_arg_count(args)?;
55-
let result = this.open(path, flag)?;
55+
let &[path, flag, mode] = check_arg_count(args)?;
56+
let result = this.open(path, flag, mode)?;
5657
this.write_scalar(Scalar::from_i32(result), dest)?;
5758
}
5859
"fcntl" => {
@@ -379,19 +380,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
379380

380381
// Incomplete shims that we "stub out" just to get pre-main initialization code to work.
381382
// These shims are enabled only when the caller is in the standard library.
382-
| "pthread_attr_init"
383-
| "pthread_attr_destroy"
384-
| "pthread_attr_setstacksize"
385-
| "pthread_condattr_init"
386-
| "pthread_condattr_setclock"
387-
| "pthread_cond_init"
388-
| "pthread_condattr_destroy"
389-
| "pthread_cond_destroy" if this.frame().instance.to_string().starts_with("std::sys::unix::")
390-
=> {
391-
this.write_null(dest)?;
392-
}
393-
"pthread_attr_getguardsize" if this.frame().instance.to_string().starts_with("std::sys::unix::")
394-
=> {
383+
"pthread_attr_getguardsize"
384+
if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
395385
let &[_attr, guard_size] = check_arg_count(args)?;
396386
let guard_size = this.deref_operand(guard_size)?;
397387
let guard_size_layout = this.libc_ty_layout("size_t")?;
@@ -401,11 +391,33 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
401391
this.write_null(dest)?;
402392
}
403393

394+
| "pthread_attr_init"
395+
| "pthread_attr_destroy"
396+
| "pthread_condattr_init"
397+
| "pthread_condattr_destroy"
398+
| "pthread_cond_destroy"
399+
if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
400+
let &[_] = check_arg_count(args)?;
401+
this.write_null(dest)?;
402+
}
403+
| "pthread_cond_init"
404+
| "pthread_attr_setstacksize"
405+
| "pthread_condattr_setclock"
406+
if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
407+
let &[_, _] = check_arg_count(args)?;
408+
this.write_null(dest)?;
409+
}
410+
404411
| "signal"
405-
| "sigaction"
406412
| "sigaltstack"
407-
| "mprotect" if this.frame().instance.to_string().starts_with("std::sys::unix::")
408-
=> {
413+
if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
414+
let &[_, _] = check_arg_count(args)?;
415+
this.write_null(dest)?;
416+
}
417+
| "sigaction"
418+
| "mprotect"
419+
if this.frame().instance.to_string().starts_with("std::sys::unix::") => {
420+
let &[_, _, _] = check_arg_count(args)?;
409421
this.write_null(dest)?;
410422
}
411423

src/shims/foreign_items/windows.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
6363
this.write_scalar(Scalar::from_machine_isize(which.into(), this), dest)?;
6464
}
6565
"WriteFile" => {
66-
let &[handle, buf, n, written_ptr, _overlapped] = check_arg_count(args)?;
66+
let &[handle, buf, n, written_ptr, overlapped] = check_arg_count(args)?;
67+
this.read_scalar(overlapped)?.to_machine_usize(this)?; // this is a poiner, that we ignore
6768
let handle = this.read_scalar(handle)?.to_machine_isize(this)?;
6869
let buf = this.read_scalar(buf)?.not_undef()?;
6970
let n = this.read_scalar(n)?.to_u32()?;
@@ -251,22 +252,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
251252
// Just fake a HANDLE
252253
this.write_scalar(Scalar::from_machine_isize(1, this), dest)?;
253254
}
254-
"GetModuleHandleW" if this.frame().instance.to_string().starts_with("std::sys::windows::")
255-
=> {
255+
"GetModuleHandleW" if this.frame().instance.to_string().starts_with("std::sys::windows::") => {
256256
#[allow(non_snake_case)]
257257
let &[_lpModuleName] = check_arg_count(args)?;
258258
// Pretend this does not exist / nothing happened, by returning zero.
259259
this.write_null(dest)?;
260260
}
261-
"GetProcAddress" if this.frame().instance.to_string().starts_with("std::sys::windows::")
262-
=> {
261+
"GetProcAddress" if this.frame().instance.to_string().starts_with("std::sys::windows::") => {
263262
#[allow(non_snake_case)]
264263
let &[_hModule, _lpProcName] = check_arg_count(args)?;
265264
// Pretend this does not exist / nothing happened, by returning zero.
266265
this.write_null(dest)?;
267266
}
268-
"SetConsoleTextAttribute" if this.frame().instance.to_string().starts_with("std::sys::windows::")
269-
=> {
267+
"SetConsoleTextAttribute" if this.frame().instance.to_string().starts_with("std::sys::windows::") => {
270268
#[allow(non_snake_case)]
271269
let &[_hConsoleOutput, _wAttribute] = check_arg_count(args)?;
272270
// Pretend these does not exist / nothing happened, by returning zero.
@@ -281,17 +279,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
281279
| "InitializeCriticalSection"
282280
| "EnterCriticalSection"
283281
| "LeaveCriticalSection"
284-
| "DeleteCriticalSection" if this.frame().instance.to_string().starts_with("std::sys::windows::")
285-
=> {
282+
| "DeleteCriticalSection"
283+
if this.frame().instance.to_string().starts_with("std::sys::windows::") => {
286284
#[allow(non_snake_case)]
287285
let &[_lpCriticalSection] = check_arg_count(args)?;
288286
assert_eq!(this.get_total_thread_count()?, 1, "concurrency on Windows not supported");
289287
// Nothing to do, not even a return value.
290288
// (Windows locks are reentrant, and we have only 1 thread,
291289
// so not doing any futher checks here is at least not incorrect.)
292290
}
293-
"TryEnterCriticalSection" if this.frame().instance.to_string().starts_with("std::sys::windows::")
294-
=> {
291+
"TryEnterCriticalSection"
292+
if this.frame().instance.to_string().starts_with("std::sys::windows::") => {
295293
#[allow(non_snake_case)]
296294
let &[_lpCriticalSection] = check_arg_count(args)?;
297295
assert_eq!(this.get_total_thread_count()?, 1, "concurrency on Windows not supported");

src/shims/fs.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -238,13 +238,27 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
238238
&mut self,
239239
path_op: OpTy<'tcx, Tag>,
240240
flag_op: OpTy<'tcx, Tag>,
241+
mode_op: OpTy<'tcx, Tag>,
241242
) -> InterpResult<'tcx, i32> {
242243
let this = self.eval_context_mut();
243244

244245
this.check_no_isolation("open")?;
245246

246247
let flag = this.read_scalar(flag_op)?.to_i32()?;
247248

249+
// Check mode (size depends on platform).
250+
// FIXME: should we do something with the mode?
251+
match this.tcx.sess.target.target.target_os.as_str() {
252+
"macos" => {
253+
// FIXME: I think `mode` should be `u16` on macOS, but see
254+
// <https://github.com/rust-lang/rust/issues/71915>.
255+
// For now, just don't check on macos.
256+
}
257+
_ => {
258+
this.read_scalar(mode_op)?.to_u32()?;
259+
}
260+
};
261+
248262
let mut options = OpenOptions::new();
249263

250264
let o_rdonly = this.eval_libc_i32("O_RDONLY")?;
@@ -331,15 +345,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
331345
if args.len() < 2 {
332346
throw_ub_format!("incorrect number of arguments for fcntl: got {}, expected at least 2", args.len());
333347
}
348+
let fd = this.read_scalar(args[0])?.to_i32()?;
334349
let cmd = this.read_scalar(args[1])?.to_i32()?;
335350
// We only support getting the flags for a descriptor.
336351
if cmd == this.eval_libc_i32("F_GETFD")? {
337352
// Currently this is the only flag that `F_GETFD` returns. It is OK to just return the
338353
// `FD_CLOEXEC` value without checking if the flag is set for the file because `std`
339354
// always sets this flag when opening a file. However we still need to check that the
340355
// file itself is open.
341-
let &[fd, _] = check_arg_count(args)?;
342-
let fd = this.read_scalar(fd)?.to_i32()?;
356+
let &[_, _] = check_arg_count(args)?;
343357
if this.machine.file_handler.handles.contains_key(&fd) {
344358
Ok(this.eval_libc_i32("FD_CLOEXEC")?)
345359
} else {
@@ -352,8 +366,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
352366
// because exec() isn't supported. The F_DUPFD and F_DUPFD_CLOEXEC commands only
353367
// differ in whether the FD_CLOEXEC flag is pre-set on the new file descriptor,
354368
// thus they can share the same implementation here.
355-
let &[fd, _, start] = check_arg_count(args)?;
356-
let fd = this.read_scalar(fd)?.to_i32()?;
369+
let &[_, _, start] = check_arg_count(args)?;
357370
let start = this.read_scalar(start)?.to_i32()?;
358371
if fd < MIN_NORMAL_FILE_FD {
359372
throw_unsup_format!("duplicating file descriptors for stdin, stdout, or stderr is not supported")

src/shims/intrinsics.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
363363
| "atomic_singlethreadfence_acqrel"
364364
| "atomic_singlethreadfence"
365365
=> {
366-
// we are inherently singlethreaded and singlecored, this is a nop
366+
let &[] = check_arg_count(args)?;
367+
// FIXME: this will become relevant once we try to detect data races.
367368
}
368369

369370
_ if intrinsic_name.starts_with("atomic_xchg") => {

0 commit comments

Comments
 (0)