Auto merge of #1099 - RalfJung:os_str, r=RalfJung

tweak and use OsStr interfaces
This commit is contained in:
bors 2019-12-04 09:17:03 +00:00
commit 53fcf47e72
3 changed files with 32 additions and 27 deletions

View File

@ -1,5 +1,7 @@
//! Main evaluator loop and setting up the initial stack frame.
use std::ffi::OsStr;
use rand::rngs::StdRng;
use rand::SeedableRng;
@ -75,26 +77,15 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
let argc = Scalar::from_uint(config.args.len() as u128, ecx.pointer_size());
// Third argument (`argv`): created from `config.args`.
let argv = {
// For Windows, construct a command string with all the aguments (before we take apart `config.args`).
let mut cmd = String::new();
// Put each argument in memory, collect pointers.
let mut argvs = Vec::<Scalar<Tag>>::new();
for arg in config.args.iter() {
if !cmd.is_empty() {
cmd.push(' ');
}
cmd.push_str(&*shell_escape::windows::escape(arg.as_str().into()));
}
// Don't forget `0` terminator.
cmd.push(std::char::from_u32(0).unwrap());
// Collect the pointers to the individual strings.
let mut argvs = Vec::<Pointer<Tag>>::new();
for arg in config.args {
// Add `0` terminator.
let mut arg = arg.into_bytes();
arg.push(0);
argvs.push(
ecx.memory
.allocate_static_bytes(arg.as_slice(), MiriMemoryKind::Env.into()),
);
// Make space for `0` terminator.
let size = arg.len() as u64 + 1;
let arg_type = tcx.mk_array(tcx.types.u8, size);
let arg_place = ecx.allocate(ecx.layout_of(arg_type)?, MiriMemoryKind::Env.into());
ecx.write_os_str_to_c_string(OsStr::new(arg), arg_place.ptr, size)?;
argvs.push(arg_place.ptr);
}
// Make an array with all these pointers, in the Miri memory.
let argvs_layout = ecx.layout_of(
@ -107,7 +98,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
}
ecx.memory
.mark_immutable(argvs_place.ptr.assert_ptr().alloc_id)?;
// A pointer to that place is the argument.
// A pointer to that place is the 3rd argument for main.
let argv = argvs_place.ptr;
// Store `argc` and `argv` for macOS `_NSGetArg{c,v}`.
{
@ -127,6 +118,17 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
}
// Store command line as UTF-16 for Windows `GetCommandLineW`.
{
// Construct a command string with all the aguments.
let mut cmd = String::new();
for arg in config.args.iter() {
if !cmd.is_empty() {
cmd.push(' ');
}
cmd.push_str(&*shell_escape::windows::escape(arg.as_str().into()));
}
// Don't forget `0` terminator.
cmd.push(std::char::from_u32(0).unwrap());
let cmd_utf16: Vec<u16> = cmd.encode_utf16().collect();
let cmd_type = tcx.mk_array(tcx.types.u16, cmd_utf16.len() as u64);
let cmd_place = ecx.allocate(ecx.layout_of(cmd_type)?, MiriMemoryKind::Env.into());

View File

@ -1,5 +1,5 @@
use std::{mem, iter};
use std::ffi::{OsStr, OsString};
use std::ffi::OsStr;
use syntax::source_map::DUMMY_SP;
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
@ -453,9 +453,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
/// Helper function to read an OsString from a null-terminated sequence of bytes, which is what
/// the Unix APIs usually handle.
fn read_os_string_from_c_string(&mut self, scalar: Scalar<Tag>) -> InterpResult<'tcx, OsString> {
let bytes = self.eval_context_mut().memory.read_c_str(scalar)?;
Ok(bytes_to_os_str(bytes)?.into())
fn read_os_string_from_c_string<'a>(&'a self, scalar: Scalar<Tag>) -> InterpResult<'tcx, &'a OsStr>
where 'tcx: 'a, 'mir: 'a
{
let this = self.eval_context_ref();
let bytes = this.memory.read_c_str(scalar)?;
bytes_to_os_str(bytes)
}
/// Helper function to write an OsStr as a null-terminated sequence of bytes, which is what
@ -501,7 +504,7 @@ fn os_str_to_bytes<'tcx, 'a>(os_str: &'a OsStr) -> InterpResult<'tcx, &'a [u8]>
}
#[cfg(not(target_os = "unix"))]
fn bytes_to_os_str<'tcx, 'a>(bytes: &'a[u8]) -> InterpResult<'tcx, &'a OsStr> {
fn bytes_to_os_str<'tcx, 'a>(bytes: &'a [u8]) -> InterpResult<'tcx, &'a OsStr> {
let s = std::str::from_utf8(bytes)
.map_err(|_| err_unsup_format!("{:?} is not a valid utf-8 string", bytes))?;
Ok(&OsStr::new(s))

View File

@ -140,8 +140,8 @@ pub type MiriEvalContext<'mir, 'tcx> = InterpCx<'mir, 'tcx, Evaluator<'tcx>>;
/// A little trait that's useful to be inherited by extension traits.
pub trait MiriEvalContextExt<'mir, 'tcx> {
fn eval_context_ref(&self) -> &MiriEvalContext<'mir, 'tcx>;
fn eval_context_mut(&mut self) -> &mut MiriEvalContext<'mir, 'tcx>;
fn eval_context_ref<'a>(&'a self) -> &'a MiriEvalContext<'mir, 'tcx>;
fn eval_context_mut<'a>(&'a mut self) -> &'a mut MiriEvalContext<'mir, 'tcx>;
}
impl<'mir, 'tcx> MiriEvalContextExt<'mir, 'tcx> for MiriEvalContext<'mir, 'tcx> {
#[inline(always)]