@@ -14,72 +14,48 @@ use rustc_target::abi::LayoutOf;
1414use crate :: * ;
1515
1616/// Represent how path separator conversion should be done.
17- enum Pathconversion {
17+ pub enum PathConversion {
1818 HostToTarget ,
1919 TargetToHost ,
2020}
2121
22- /// Perform path separator conversion if needed.
23- fn convert_path_separator < ' a > (
24- os_str : Cow < ' a , OsStr > ,
25- target_os : & str ,
26- direction : Pathconversion ,
27- ) -> Cow < ' a , OsStr > {
28- #[ cfg( windows) ]
29- return if target_os == "windows" {
30- // Windows-on-Windows, all fine.
31- os_str
32- } else {
33- // Unix target, Windows host.
34- let ( from, to) = match direction {
35- Pathconversion :: HostToTarget => ( '\\' , '/' ) ,
36- Pathconversion :: TargetToHost => ( '/' , '\\' ) ,
37- } ;
38- let converted = os_str
39- . encode_wide ( )
40- . map ( |wchar| if wchar == from as u16 { to as u16 } else { wchar } )
41- . collect :: < Vec < _ > > ( ) ;
42- Cow :: Owned ( OsString :: from_wide ( & converted) )
43- } ;
44- #[ cfg( unix) ]
45- return if target_os == "windows" {
46- // Windows target, Unix host.
47- let ( from, to) = match direction {
48- Pathconversion :: HostToTarget => ( '/' , '\\' ) ,
49- Pathconversion :: TargetToHost => ( '\\' , '/' ) ,
50- } ;
51- let converted = os_str
52- . as_bytes ( )
53- . iter ( )
54- . map ( |& wchar| if wchar == from as u8 { to as u8 } else { wchar } )
55- . collect :: < Vec < _ > > ( ) ;
56- Cow :: Owned ( OsString :: from_vec ( converted) )
57- } else {
58- // Unix-on-Unix, all is fine.
59- os_str
60- } ;
22+ #[ cfg( unix) ]
23+ pub fn os_str_to_bytes < ' a , ' tcx > ( os_str : & ' a OsStr ) -> InterpResult < ' tcx , & ' a [ u8 ] > {
24+ Ok ( os_str. as_bytes ( ) )
25+ }
26+
27+ #[ cfg( not( unix) ) ]
28+ pub fn os_str_to_bytes < ' a , ' tcx > ( os_str : & ' a OsStr ) -> InterpResult < ' tcx , & ' a [ u8 ] > {
29+ // On non-unix platforms the best we can do to transform bytes from/to OS strings is to do the
30+ // intermediate transformation into strings. Which invalidates non-utf8 paths that are actually
31+ // valid.
32+ os_str
33+ . to_str ( )
34+ . map ( |s| s. as_bytes ( ) )
35+ . ok_or_else ( || err_unsup_format ! ( "{:?} is not a valid utf-8 string" , os_str) . into ( ) )
36+ }
37+
38+ #[ cfg( unix) ]
39+ pub fn bytes_to_os_str < ' a , ' tcx > ( bytes : & ' a [ u8 ] ) -> InterpResult < ' tcx , & ' a OsStr > {
40+ Ok ( OsStr :: from_bytes ( bytes) )
41+ }
42+ #[ cfg( not( unix) ) ]
43+ pub fn bytes_to_os_str < ' a , ' tcx > ( bytes : & ' a [ u8 ] ) -> InterpResult < ' tcx , & ' a OsStr > {
44+ let s = std:: str:: from_utf8 ( bytes)
45+ . map_err ( |_| err_unsup_format ! ( "{:?} is not a valid utf-8 string" , bytes) ) ?;
46+ Ok ( OsStr :: new ( s) )
6147}
6248
6349impl < ' mir , ' tcx : ' mir > EvalContextExt < ' mir , ' tcx > for crate :: MiriEvalContext < ' mir , ' tcx > { }
6450pub trait EvalContextExt < ' mir , ' tcx : ' mir > : crate :: MiriEvalContextExt < ' mir , ' tcx > {
51+
6552 /// Helper function to read an OsString from a null-terminated sequence of bytes, which is what
6653 /// the Unix APIs usually handle.
6754 fn read_os_str_from_c_str < ' a > ( & ' a self , scalar : Scalar < Tag > ) -> InterpResult < ' tcx , & ' a OsStr >
6855 where
6956 ' tcx : ' a ,
7057 ' mir : ' a ,
7158 {
72- #[ cfg( unix) ]
73- fn bytes_to_os_str < ' tcx , ' a > ( bytes : & ' a [ u8 ] ) -> InterpResult < ' tcx , & ' a OsStr > {
74- Ok ( OsStr :: from_bytes ( bytes) )
75- }
76- #[ cfg( not( unix) ) ]
77- fn bytes_to_os_str < ' tcx , ' a > ( bytes : & ' a [ u8 ] ) -> InterpResult < ' tcx , & ' a OsStr > {
78- let s = std:: str:: from_utf8 ( bytes)
79- . map_err ( |_| err_unsup_format ! ( "{:?} is not a valid utf-8 string" , bytes) ) ?;
80- Ok ( OsStr :: new ( s) )
81- }
82-
8359 let this = self . eval_context_ref ( ) ;
8460 let bytes = this. memory . read_c_str ( scalar) ?;
8561 bytes_to_os_str ( bytes)
@@ -118,20 +94,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
11894 scalar : Scalar < Tag > ,
11995 size : u64 ,
12096 ) -> InterpResult < ' tcx , ( bool , u64 ) > {
121- #[ cfg( unix) ]
122- fn os_str_to_bytes < ' tcx , ' a > ( os_str : & ' a OsStr ) -> InterpResult < ' tcx , & ' a [ u8 ] > {
123- Ok ( os_str. as_bytes ( ) )
124- }
125- #[ cfg( not( unix) ) ]
126- fn os_str_to_bytes < ' tcx , ' a > ( os_str : & ' a OsStr ) -> InterpResult < ' tcx , & ' a [ u8 ] > {
127- // On non-unix platforms the best we can do to transform bytes from/to OS strings is to do the
128- // intermediate transformation into strings. Which invalidates non-utf8 paths that are actually
129- // valid.
130- os_str
131- . to_str ( )
132- . map ( |s| s. as_bytes ( ) )
133- . ok_or_else ( || err_unsup_format ! ( "{:?} is not a valid utf-8 string" , os_str) . into ( ) )
134- }
13597
13698 let bytes = os_str_to_bytes ( os_str) ?;
13799 // If `size` is smaller or equal than `bytes.len()`, writing `bytes` plus the required null
@@ -226,7 +188,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
226188 let this = self . eval_context_ref ( ) ;
227189 let os_str = this. read_os_str_from_c_str ( scalar) ?;
228190
229- Ok ( match convert_path_separator ( Cow :: Borrowed ( os_str) , & this . tcx . sess . target . target . target_os , Pathconversion :: TargetToHost ) {
191+ Ok ( match this . convert_path_separator ( Cow :: Borrowed ( os_str) , PathConversion :: TargetToHost ) {
230192 Cow :: Borrowed ( x) => Cow :: Borrowed ( Path :: new ( x) ) ,
231193 Cow :: Owned ( y) => Cow :: Owned ( PathBuf :: from ( y) ) ,
232194 } )
@@ -237,7 +199,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
237199 let this = self . eval_context_ref ( ) ;
238200 let os_str = this. read_os_str_from_wide_str ( scalar) ?;
239201
240- Ok ( convert_path_separator ( Cow :: Owned ( os_str) , & this . tcx . sess . target . target . target_os , Pathconversion :: TargetToHost ) . into_owned ( ) . into ( ) )
202+ Ok ( this . convert_path_separator ( Cow :: Owned ( os_str) , PathConversion :: TargetToHost ) . into_owned ( ) . into ( ) )
241203 }
242204
243205 /// Write a Path to the machine memory (as a null-terminated sequence of bytes),
@@ -249,7 +211,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
249211 size : u64 ,
250212 ) -> InterpResult < ' tcx , ( bool , u64 ) > {
251213 let this = self . eval_context_mut ( ) ;
252- let os_str = convert_path_separator ( Cow :: Borrowed ( path. as_os_str ( ) ) , & this . tcx . sess . target . target . target_os , Pathconversion :: HostToTarget ) ;
214+ let os_str = this . convert_path_separator ( Cow :: Borrowed ( path. as_os_str ( ) ) , PathConversion :: HostToTarget ) ;
253215 this. write_os_str_to_c_str ( & os_str, scalar, size)
254216 }
255217
@@ -262,7 +224,50 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
262224 size : u64 ,
263225 ) -> InterpResult < ' tcx , ( bool , u64 ) > {
264226 let this = self . eval_context_mut ( ) ;
265- let os_str = convert_path_separator ( Cow :: Borrowed ( path. as_os_str ( ) ) , & this . tcx . sess . target . target . target_os , Pathconversion :: HostToTarget ) ;
227+ let os_str = this . convert_path_separator ( Cow :: Borrowed ( path. as_os_str ( ) ) , PathConversion :: HostToTarget ) ;
266228 this. write_os_str_to_wide_str ( & os_str, scalar, size)
267229 }
230+
231+ fn convert_path_separator < ' a > (
232+ & self ,
233+ os_str : Cow < ' a , OsStr > ,
234+ direction : PathConversion ,
235+ ) -> Cow < ' a , OsStr > {
236+ let this = self . eval_context_ref ( ) ;
237+ let target_os = & this. tcx . sess . target . target . target_os ;
238+ #[ cfg( windows) ]
239+ return if target_os == "windows" {
240+ // Windows-on-Windows, all fine.
241+ os_str
242+ } else {
243+ // Unix target, Windows host.
244+ let ( from, to) = match direction {
245+ PathConversion :: HostToTarget => ( '\\' , '/' ) ,
246+ PathConversion :: TargetToHost => ( '/' , '\\' ) ,
247+ } ;
248+ let converted = os_str
249+ . encode_wide ( )
250+ . map ( |wchar| if wchar == from as u16 { to as u16 } else { wchar } )
251+ . collect :: < Vec < _ > > ( ) ;
252+ Cow :: Owned ( OsString :: from_wide ( & converted) )
253+ } ;
254+ #[ cfg( unix) ]
255+ return if target_os == "windows" {
256+ // Windows target, Unix host.
257+ let ( from, to) = match direction {
258+ PathConversion :: HostToTarget => ( '/' , '\\' ) ,
259+ PathConversion :: TargetToHost => ( '\\' , '/' ) ,
260+ } ;
261+ let converted = os_str
262+ . as_bytes ( )
263+ . iter ( )
264+ . map ( |& wchar| if wchar == from as u8 { to as u8 } else { wchar } )
265+ . collect :: < Vec < _ > > ( ) ;
266+ Cow :: Owned ( OsString :: from_vec ( converted) )
267+ } else {
268+ // Unix-on-Unix, all is fine.
269+ os_str
270+ } ;
271+ }
268272}
273+
0 commit comments