@@ -232,6 +232,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
232232 this. alloc_os_str_as_c_str ( & os_str, memkind)
233233 }
234234
235+ #[ allow( clippy:: get_first) ]
235236 fn convert_path < ' a > (
236237 & self ,
237238 os_str : Cow < ' a , OsStr > ,
@@ -260,20 +261,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
260261 // If this is an absolute Windows path that starts with a drive letter (`C:/...`
261262 // after separator conversion), it would not be considered absolute by Unix
262263 // target code.
263- if converted. get ( 1 ) . copied ( ) == Some ( ':' as u16 )
264- && converted. get ( 2 ) . copied ( ) == Some ( '/' as u16 )
264+ if converted. get ( 1 ) . copied ( ) == Some ( b ':' as u16 )
265+ && converted. get ( 2 ) . copied ( ) == Some ( b '/' as u16 )
265266 {
266267 // We add a `/` at the beginning, to store the absolute Windows
267268 // path in something that looks like an absolute Unix path.
268- converted. insert ( 0 , '/' as u16 ) ;
269+ converted. insert ( 0 , b '/' as u16 ) ;
269270 }
270271 }
271272 PathConversion :: TargetToHost => {
272273 // If the path is `\C:\`, the leading backslash was probably added by the above code
273274 // and we should get rid of it again.
274- if converted. get ( 0 ) . copied ( ) == Some ( '\\' as u16 )
275- && converted. get ( 2 ) . copied ( ) == Some ( ':' as u16 )
276- && converted. get ( 3 ) . copied ( ) == Some ( '\\' as u16 )
275+ if converted. get ( 0 ) . copied ( ) == Some ( b '\\' as u16 )
276+ && converted. get ( 2 ) . copied ( ) == Some ( b ':' as u16 )
277+ && converted. get ( 3 ) . copied ( ) == Some ( b '\\' as u16 )
277278 {
278279 converted. remove ( 0 ) ;
279280 }
@@ -285,16 +286,36 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
285286 return if target_os == "windows" {
286287 // Windows target, Unix host.
287288 let ( from, to) = match direction {
288- PathConversion :: HostToTarget => ( '/' , '\\' ) ,
289- PathConversion :: TargetToHost => ( '\\' , '/' ) ,
289+ PathConversion :: HostToTarget => ( b '/', b '\\') ,
290+ PathConversion :: TargetToHost => ( b '\\', b '/') ,
290291 } ;
291- let converted = os_str
292+ let mut converted = os_str
292293 . as_bytes ( )
293294 . iter ( )
294- . map ( |& wchar| if wchar == from as u8 { to as u8 } else { wchar } )
295+ . map ( |& wchar| if wchar == from { to } else { wchar } )
295296 . collect :: < Vec < _ > > ( ) ;
296- // TODO: Once we actually support file system things on Windows targets, we'll probably
297- // have to also do something clever for absolute path preservation here, like above.
297+ // We also have to ensure that absolute paths remain absolute.
298+ match direction {
299+ PathConversion :: HostToTarget => {
300+ // If this start withs a `\`, we add `\\?` so it starts with `\\?\` which is
301+ // some magic path on Windos that *is* considered absolute.
302+ if converted. get ( 0 ) . copied ( ) == Some ( b'\\' ) {
303+ converted. splice ( 0 ..0 , b"\\ \\ ?" . iter ( ) . copied ( ) ) ;
304+ }
305+ }
306+ PathConversion :: TargetToHost => {
307+ // If this starts with `//?/`, it was probably produced by the above code and we
308+ // remove the `//?` that got added to get the Unix path back out.
309+ if converted. get ( 0 ) . copied ( ) == Some ( b'/' )
310+ && converted. get ( 1 ) . copied ( ) == Some ( b'/' )
311+ && converted. get ( 2 ) . copied ( ) == Some ( b'?' )
312+ && converted. get ( 3 ) . copied ( ) == Some ( b'/' )
313+ {
314+ // Remove first 3 characters
315+ converted. splice ( 0 ..3 , std:: iter:: empty ( ) ) ;
316+ }
317+ }
318+ }
298319 Cow :: Owned ( OsString :: from_vec ( converted) )
299320 } else {
300321 // Unix-on-Unix, all is fine.
0 commit comments