convert dir separators on path load/store

This commit is contained in:
Ralf Jung 2020-03-23 19:57:40 +01:00
parent 4ac91384ff
commit c4e29c8646

View File

@ -1,9 +1,14 @@
use std::ffi::{OsStr, OsString};
use std::path::Path;
use std::path::{Path, PathBuf};
use std::{iter, mem};
use std::convert::TryFrom;
use std::borrow::Cow;
#[cfg(unix)]
use std::os::unix::ffi::{OsStrExt, OsStringExt};
#[cfg(windows)]
use std::os::windows::ffi::{OsStrExt, OsStringExt};
use rustc::mir;
use rustc::ty::{
self,
@ -479,7 +484,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
{
#[cfg(unix)]
fn bytes_to_os_str<'tcx, 'a>(bytes: &'a [u8]) -> InterpResult<'tcx, &'a OsStr> {
Ok(std::os::unix::ffi::OsStrExt::from_bytes(bytes))
Ok(OsStr::from_bytes(bytes))
}
#[cfg(not(unix))]
fn bytes_to_os_str<'tcx, 'a>(bytes: &'a [u8]) -> InterpResult<'tcx, &'a OsStr> {
@ -499,8 +504,34 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
'tcx: 'a,
'mir: 'a,
{
let os_str = self.read_os_str_from_c_str(scalar)?;
Ok(Cow::Borrowed(Path::new(os_str)))
let this = self.eval_context_ref();
let os_str = this.read_os_str_from_c_str(scalar)?;
#[cfg(windows)]
return Ok(if this.tcx.sess.target.target.target_os == "windows" {
// Windows-on-Windows, all fine.
Cow::Borrowed(Path::new(os_str))
} else {
// Unix target, Windows host. Need to convert target '/' to host '\'.
let converted = os_str
.encode_wide()
.map(|wchar| if wchar == '/' as u16 { '\\' as u16 } else { wchar })
.collect::<Vec<_>>();
Cow::Owned(PathBuf::from(OsString::from_wide(&converted)))
});
#[cfg(unix)]
return Ok(if this.tcx.sess.target.target.target_os == "windows" {
// Windows target, Unix host. Need to convert target '\' to host '/'.
let converted = os_str
.as_bytes()
.iter()
.map(|&wchar| if wchar == '/' as u8 { '\\' as u8 } else { wchar })
.collect::<Vec<_>>();
Cow::Owned(PathBuf::from(OsString::from_vec(converted)))
} else {
// Unix-on-Unix, all is fine.
Cow::Borrowed(Path::new(os_str))
});
}
/// Helper function to read an OsString from a 0x0000-terminated sequence of u16,
@ -512,7 +543,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
{
#[cfg(windows)]
pub fn u16vec_to_osstring<'tcx, 'a>(u16_vec: Vec<u16>) -> InterpResult<'tcx, OsString> {
Ok(std::os::windows::ffi::OsStringExt::from_wide(&u16_vec[..]))
Ok(OsString::from_wide(&u16_vec[..]))
}
#[cfg(not(windows))]
pub fn u16vec_to_osstring<'tcx, 'a>(u16_vec: Vec<u16>) -> InterpResult<'tcx, OsString> {
@ -538,7 +569,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
) -> InterpResult<'tcx, (bool, u64)> {
#[cfg(unix)]
fn os_str_to_bytes<'tcx, 'a>(os_str: &'a OsStr) -> InterpResult<'tcx, &'a [u8]> {
Ok(std::os::unix::ffi::OsStrExt::as_bytes(os_str))
Ok(os_str.as_bytes())
}
#[cfg(not(unix))]
fn os_str_to_bytes<'tcx, 'a>(os_str: &'a OsStr) -> InterpResult<'tcx, &'a [u8]> {
@ -571,8 +602,37 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
scalar: Scalar<Tag>,
size: u64,
) -> InterpResult<'tcx, (bool, u64)> {
let os_str = path.as_os_str();
self.write_os_str_to_c_str(os_str, scalar, size)
let this = self.eval_context_mut();
#[cfg(windows)]
let os_str = if this.tcx.sess.target.target.target_os == "windows" {
// Windows-on-Windows, all fine.
Cow::Borrowed(path.as_os_str())
} else {
// Unix target, Windows host. Need to convert host '\\' to target '/'.
let converted = path
.as_os_str()
.encode_wide()
.map(|wchar| if wchar == '\\' as u16 { '/' as u16 } else { wchar })
.collect::<Vec<_>>();
Cow::Owned(OsString::from_wide(&converted))
};
#[cfg(unix)]
let os_str = if this.tcx.sess.target.target.target_os == "windows" {
// Windows target, Unix host. Need to convert host '/' to target '\'.
let converted = path
.as_os_str()
.as_bytes()
.iter()
.map(|&wchar| if wchar == '/' as u8 { '\\' as u8 } else { wchar })
.collect::<Vec<_>>();
Cow::Owned(OsString::from_vec(converted))
} else {
// Unix-on-Unix, all is fine.
Cow::Borrowed(path.as_os_str())
};
this.write_os_str_to_c_str(&os_str, scalar, size)
}
/// Helper function to write an OsStr as a 0x0000-terminated u16-sequence, which is what
@ -588,7 +648,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
) -> InterpResult<'tcx, (bool, u64)> {
#[cfg(windows)]
fn os_str_to_u16vec<'tcx>(os_str: &OsStr) -> InterpResult<'tcx, Vec<u16>> {
Ok(std::os::windows::ffi::OsStrExt::encode_wide(os_str).collect())
Ok(os_str.encode_wide().collect())
}
#[cfg(not(windows))]
fn os_str_to_u16vec<'tcx>(os_str: &OsStr) -> InterpResult<'tcx, Vec<u16>> {