-
Notifications
You must be signed in to change notification settings - Fork 356
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Check fixed args number for variadic function #4122
base: master
Are you sure you want to change the base?
Changes from all commits
bfc626a
b10bb99
7f915d2
a64c116
b6acfa9
eb844f3
26f231b
1e956b1
7b1c08a
317d68d
b95b2c6
476fd11
9aa7f98
b7039cd
df32a54
c8510d4
65963d6
15109d2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -928,6 +928,30 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { | |||||||
interp_ok(()) | ||||||||
} | ||||||||
|
||||||||
/// Check the number of fixed args. | ||||||||
/// Returns a tuple that consisting of an array of fixed args, and a slice of varargs. | ||||||||
fn check_fixed_args_count<'a, const N: usize>( | ||||||||
&self, | ||||||||
name: &'a str, | ||||||||
abi: &FnAbi<'tcx, Ty<'tcx>>, | ||||||||
args: &'a [OpTy<'tcx>], | ||||||||
) -> InterpResult<'tcx, (&'a [OpTy<'tcx>; N], &'a [OpTy<'tcx>])> { | ||||||||
if abi.fixed_count != u32::try_from(N).unwrap() { | ||||||||
throw_ub_format!( | ||||||||
"incorrect number of fixed arguments for variadic function `{name}`: got {}, expected {N}", | ||||||||
abi.fixed_count | ||||||||
) | ||||||||
} | ||||||||
if let Some(args) = args.split_first_chunk() { | ||||||||
return interp_ok(args); | ||||||||
} | ||||||||
throw_ub_format!( | ||||||||
"incorrect number of arguments for `{name}`: got {}, expected at least {}", | ||||||||
args.len(), | ||||||||
N | ||||||||
) | ||||||||
} | ||||||||
|
||||||||
fn frame_in_std(&self) -> bool { | ||||||||
let this = self.eval_context_ref(); | ||||||||
let frame = this.frame(); | ||||||||
|
@@ -990,6 +1014,23 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { | |||||||
check_arg_count(args) | ||||||||
} | ||||||||
|
||||||||
/// Check shim for variadic function. | ||||||||
/// Returns a tuple that consisting of an array of fixed args, and a slice of varargs. | ||||||||
fn check_shim_variadic<'a, const N: usize>( | ||||||||
&mut self, | ||||||||
abi: &FnAbi<'tcx, Ty<'tcx>>, | ||||||||
exp_abi: Conv, | ||||||||
link_name: Symbol, | ||||||||
shim_name: &'a str, | ||||||||
args: &'a [OpTy<'tcx>], | ||||||||
) -> InterpResult<'tcx, (&'a [OpTy<'tcx>; N], &'a [OpTy<'tcx>])> | ||||||||
where | ||||||||
&'a [OpTy<'tcx>; N]: TryFrom<&'a [OpTy<'tcx>]>, | ||||||||
{ | ||||||||
self.check_abi_and_shim_symbol_clash(abi, exp_abi, link_name)?; | ||||||||
self.check_fixed_args_count(shim_name, abi, args) | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why does this need |
||||||||
} | ||||||||
|
||||||||
/// Mark a machine allocation that was just created as immutable. | ||||||||
fn mark_immutable(&mut self, mplace: &MPlaceTy<'tcx>) { | ||||||||
let this = self.eval_context_mut(); | ||||||||
|
@@ -1183,7 +1224,7 @@ where | |||||||
throw_ub_format!("incorrect number of arguments: got {}, expected {}", args.len(), N) | ||||||||
} | ||||||||
|
||||||||
/// Check that the number of args is at least the minumim what we expect. | ||||||||
/// Check that the number of args is at least the minimum what we expect. | ||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||
pub fn check_min_arg_count<'a, 'tcx, const N: usize>( | ||||||||
name: &'a str, | ||||||||
args: &'a [OpTy<'tcx>], | ||||||||
|
@@ -1198,6 +1239,21 @@ pub fn check_min_arg_count<'a, 'tcx, const N: usize>( | |||||||
) | ||||||||
} | ||||||||
|
||||||||
/// Check that the number of varargs is at least the minimum what we expect. | ||||||||
pub fn check_min_vararg_count<'a, 'tcx, const N: usize>( | ||||||||
name: &'a str, | ||||||||
args: &'a [OpTy<'tcx>], | ||||||||
) -> InterpResult<'tcx, &'a [OpTy<'tcx>; N]> { | ||||||||
if let Some((ops, _)) = args.split_first_chunk() { | ||||||||
return interp_ok(ops); | ||||||||
} | ||||||||
throw_ub_format!( | ||||||||
"not enough variadic arguments for `{name}`: got {}, expected at least {}", | ||||||||
args.len(), | ||||||||
N | ||||||||
) | ||||||||
} | ||||||||
|
||||||||
pub fn isolation_abort_error<'tcx>(name: &str) -> InterpResult<'tcx> { | ||||||||
throw_machine_stop!(TerminationInfo::UnsupportedInIsolation(format!( | ||||||||
"{name} not available when isolation is enabled", | ||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -3,7 +3,7 @@ use rustc_middle::ty::Ty; | |||||||||
use rustc_span::Symbol; | ||||||||||
use rustc_target::callconv::{Conv, FnAbi}; | ||||||||||
|
||||||||||
use crate::helpers::check_min_arg_count; | ||||||||||
use crate::helpers::check_min_vararg_count; | ||||||||||
use crate::shims::unix::thread::{EvalContextExt as _, ThreadNameResult}; | ||||||||||
use crate::*; | ||||||||||
|
||||||||||
|
@@ -16,18 +16,18 @@ pub fn prctl<'tcx>( | |||||||||
args: &[OpTy<'tcx>], | ||||||||||
dest: &MPlaceTy<'tcx>, | ||||||||||
) -> InterpResult<'tcx> { | ||||||||||
// We do not use `check_shim` here because `prctl` is variadic. The argument | ||||||||||
// count is checked bellow. | ||||||||||
ecx.check_abi_and_shim_symbol_clash(abi, Conv::C, link_name)?; | ||||||||||
// `prctl` is variadic. The argument count is checked below. | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Not sure which value this comment still adds. |
||||||||||
let (fixed_args, varargs) = | ||||||||||
ecx.check_shim_variadic::<1>(abi, Conv::C, link_name, "prctl", args)?; | ||||||||||
Comment on lines
+20
to
+21
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Same everywhere else -- you should never use turbofish here. |
||||||||||
|
||||||||||
// FIXME: Use constants once https://github.com/rust-lang/libc/pull/3941 backported to the 0.2 branch. | ||||||||||
let pr_set_name = 15; | ||||||||||
let pr_get_name = 16; | ||||||||||
|
||||||||||
let [op] = check_min_arg_count("prctl", args)?; | ||||||||||
let [op] = fixed_args; | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
let res = match ecx.read_scalar(op)?.to_i32()? { | ||||||||||
op if op == pr_set_name => { | ||||||||||
let [_, name] = check_min_arg_count("prctl(PR_SET_NAME, ...)", args)?; | ||||||||||
let [name] = check_min_vararg_count("prctl(PR_SET_NAME, ...)", varargs)?; | ||||||||||
let name = ecx.read_scalar(name)?; | ||||||||||
let thread = ecx.pthread_self()?; | ||||||||||
// The Linux kernel silently truncates long names. | ||||||||||
|
@@ -38,7 +38,7 @@ pub fn prctl<'tcx>( | |||||||||
Scalar::from_u32(0) | ||||||||||
} | ||||||||||
op if op == pr_get_name => { | ||||||||||
let [_, name] = check_min_arg_count("prctl(PR_GET_NAME, ...)", args)?; | ||||||||||
let [name] = check_min_vararg_count("prctl(PR_GET_NAME, ...)", varargs)?; | ||||||||||
let name = ecx.read_scalar(name)?; | ||||||||||
let thread = ecx.pthread_self()?; | ||||||||||
let len = Scalar::from_target_usize(TASK_COMM_LEN as u64, ecx); | ||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,7 +6,7 @@ use std::io::ErrorKind; | |
|
||
use rustc_abi::Size; | ||
|
||
use crate::helpers::check_min_arg_count; | ||
use crate::helpers::check_min_vararg_count; | ||
use crate::shims::files::FileDescription; | ||
use crate::shims::unix::linux_like::epoll::EpollReadyEvents; | ||
use crate::shims::unix::*; | ||
|
@@ -127,10 +127,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { | |
interp_ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) | ||
} | ||
|
||
fn fcntl(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, Scalar> { | ||
fn fcntl( | ||
&mut self, | ||
fixed_args: &[OpTy<'tcx>; 2], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of passing a 2-element array, just pass two arguments. |
||
varargs: &[OpTy<'tcx>], | ||
) -> InterpResult<'tcx, Scalar> { | ||
let this = self.eval_context_mut(); | ||
|
||
let [fd_num, cmd] = check_min_arg_count("fcntl", args)?; | ||
let [fd_num, cmd] = fixed_args; | ||
|
||
let fd_num = this.read_scalar(fd_num)?.to_i32()?; | ||
let cmd = this.read_scalar(cmd)?.to_i32()?; | ||
|
@@ -163,7 +167,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { | |
"fcntl(fd, F_DUPFD_CLOEXEC, ...)" | ||
}; | ||
|
||
let [_, _, start] = check_min_arg_count(cmd_name, args)?; | ||
let [start] = check_min_vararg_count(cmd_name, varargs)?; | ||
let start = this.read_scalar(start)?.to_i32()?; | ||
|
||
if let Some(fd) = this.machine.fds.get(fd_num) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably error if the function is not a vararg fn?
Please also put "vararg" in the name then, e.g.
check_vargarg_fixed_arg_count
.(We used
arg_count
before so please don't useargs_count
here now.)