From c4e29c8646e3836cec79bd17a73ac13a2b90e6e4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 23 Mar 2020 19:57:40 +0100 Subject: [PATCH] convert dir separators on path load/store --- src/helpers.rs | 78 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 69 insertions(+), 9 deletions(-) diff --git a/src/helpers.rs b/src/helpers.rs index d8731b537719..abfe3253ce7b 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -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 @@ fn read_os_str_from_c_str<'a>(&'a self, scalar: Scalar) -> InterpResult<'tc { #[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 @@ fn read_path_from_c_str<'a>(&'a self, scalar: Scalar) -> InterpResult<'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::>(); + 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::>(); + 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 @@ fn read_os_str_from_wide_str<'a>(&'a self, scalar: Scalar) -> InterpResult< { #[cfg(windows)] pub fn u16vec_to_osstring<'tcx, 'a>(u16_vec: Vec) -> 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) -> InterpResult<'tcx, OsString> { @@ -538,7 +569,7 @@ fn write_os_str_to_c_str( ) -> 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 @@ fn write_path_to_c_str( scalar: Scalar, 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::>(); + 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::>(); + 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 @@ fn write_os_str_to_wide_str( ) -> InterpResult<'tcx, (bool, u64)> { #[cfg(windows)] fn os_str_to_u16vec<'tcx>(os_str: &OsStr) -> InterpResult<'tcx, Vec> { - 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> {