Skip to content

Commit c4e29c8

Browse files
committed
convert dir separators on path load/store
1 parent 4ac9138 commit c4e29c8

File tree

1 file changed

+69
-9
lines changed

1 file changed

+69
-9
lines changed

src/helpers.rs

Lines changed: 69 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
use std::ffi::{OsStr, OsString};
2-
use std::path::Path;
2+
use std::path::{Path, PathBuf};
33
use std::{iter, mem};
44
use std::convert::TryFrom;
55
use std::borrow::Cow;
66

7+
#[cfg(unix)]
8+
use std::os::unix::ffi::{OsStrExt, OsStringExt};
9+
#[cfg(windows)]
10+
use std::os::windows::ffi::{OsStrExt, OsStringExt};
11+
712
use rustc::mir;
813
use rustc::ty::{
914
self,
@@ -479,7 +484,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
479484
{
480485
#[cfg(unix)]
481486
fn bytes_to_os_str<'tcx, 'a>(bytes: &'a [u8]) -> InterpResult<'tcx, &'a OsStr> {
482-
Ok(std::os::unix::ffi::OsStrExt::from_bytes(bytes))
487+
Ok(OsStr::from_bytes(bytes))
483488
}
484489
#[cfg(not(unix))]
485490
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
499504
'tcx: 'a,
500505
'mir: 'a,
501506
{
502-
let os_str = self.read_os_str_from_c_str(scalar)?;
503-
Ok(Cow::Borrowed(Path::new(os_str)))
507+
let this = self.eval_context_ref();
508+
let os_str = this.read_os_str_from_c_str(scalar)?;
509+
510+
#[cfg(windows)]
511+
return Ok(if this.tcx.sess.target.target.target_os == "windows" {
512+
// Windows-on-Windows, all fine.
513+
Cow::Borrowed(Path::new(os_str))
514+
} else {
515+
// Unix target, Windows host. Need to convert target '/' to host '\'.
516+
let converted = os_str
517+
.encode_wide()
518+
.map(|wchar| if wchar == '/' as u16 { '\\' as u16 } else { wchar })
519+
.collect::<Vec<_>>();
520+
Cow::Owned(PathBuf::from(OsString::from_wide(&converted)))
521+
});
522+
#[cfg(unix)]
523+
return Ok(if this.tcx.sess.target.target.target_os == "windows" {
524+
// Windows target, Unix host. Need to convert target '\' to host '/'.
525+
let converted = os_str
526+
.as_bytes()
527+
.iter()
528+
.map(|&wchar| if wchar == '/' as u8 { '\\' as u8 } else { wchar })
529+
.collect::<Vec<_>>();
530+
Cow::Owned(PathBuf::from(OsString::from_vec(converted)))
531+
} else {
532+
// Unix-on-Unix, all is fine.
533+
Cow::Borrowed(Path::new(os_str))
534+
});
504535
}
505536

506537
/// 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
512543
{
513544
#[cfg(windows)]
514545
pub fn u16vec_to_osstring<'tcx, 'a>(u16_vec: Vec<u16>) -> InterpResult<'tcx, OsString> {
515-
Ok(std::os::windows::ffi::OsStringExt::from_wide(&u16_vec[..]))
546+
Ok(OsString::from_wide(&u16_vec[..]))
516547
}
517548
#[cfg(not(windows))]
518549
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
538569
) -> InterpResult<'tcx, (bool, u64)> {
539570
#[cfg(unix)]
540571
fn os_str_to_bytes<'tcx, 'a>(os_str: &'a OsStr) -> InterpResult<'tcx, &'a [u8]> {
541-
Ok(std::os::unix::ffi::OsStrExt::as_bytes(os_str))
572+
Ok(os_str.as_bytes())
542573
}
543574
#[cfg(not(unix))]
544575
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
571602
scalar: Scalar<Tag>,
572603
size: u64,
573604
) -> InterpResult<'tcx, (bool, u64)> {
574-
let os_str = path.as_os_str();
575-
self.write_os_str_to_c_str(os_str, scalar, size)
605+
let this = self.eval_context_mut();
606+
607+
#[cfg(windows)]
608+
let os_str = if this.tcx.sess.target.target.target_os == "windows" {
609+
// Windows-on-Windows, all fine.
610+
Cow::Borrowed(path.as_os_str())
611+
} else {
612+
// Unix target, Windows host. Need to convert host '\\' to target '/'.
613+
let converted = path
614+
.as_os_str()
615+
.encode_wide()
616+
.map(|wchar| if wchar == '\\' as u16 { '/' as u16 } else { wchar })
617+
.collect::<Vec<_>>();
618+
Cow::Owned(OsString::from_wide(&converted))
619+
};
620+
#[cfg(unix)]
621+
let os_str = if this.tcx.sess.target.target.target_os == "windows" {
622+
// Windows target, Unix host. Need to convert host '/' to target '\'.
623+
let converted = path
624+
.as_os_str()
625+
.as_bytes()
626+
.iter()
627+
.map(|&wchar| if wchar == '/' as u8 { '\\' as u8 } else { wchar })
628+
.collect::<Vec<_>>();
629+
Cow::Owned(OsString::from_vec(converted))
630+
} else {
631+
// Unix-on-Unix, all is fine.
632+
Cow::Borrowed(path.as_os_str())
633+
};
634+
635+
this.write_os_str_to_c_str(&os_str, scalar, size)
576636
}
577637

578638
/// 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
588648
) -> InterpResult<'tcx, (bool, u64)> {
589649
#[cfg(windows)]
590650
fn os_str_to_u16vec<'tcx>(os_str: &OsStr) -> InterpResult<'tcx, Vec<u16>> {
591-
Ok(std::os::windows::ffi::OsStrExt::encode_wide(os_str).collect())
651+
Ok(os_str.encode_wide().collect())
592652
}
593653
#[cfg(not(windows))]
594654
fn os_str_to_u16vec<'tcx>(os_str: &OsStr) -> InterpResult<'tcx, Vec<u16>> {

0 commit comments

Comments
 (0)