@@ -447,10 +447,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
447447 }
448448 }
449449
450+ /// Dispatches to appropriate implementations for reading an OsString from Memory,
451+ /// depending on the interpretation target.
450452 fn read_os_str_from_target_str < ' a > ( & ' a self , scalar : Scalar < Tag > ) -> InterpResult < ' tcx , OsString > {
451453 let target_os = self . eval_context_ref ( ) . tcx . sess . target . target . target_os . as_str ( ) ;
452454 match target_os {
453- "linux" => self . read_os_str_from_c_str ( scalar) . map ( |x| x. to_os_string ( ) ) ,
455+ "linux" | "macos" => self . read_os_str_from_c_str ( scalar) . map ( |x| x. to_os_string ( ) ) ,
454456 "windows" => self . read_os_str_from_wide_str ( scalar) ,
455457 _ => throw_unsup_format ! ( "support for target OS not yet available" ) ,
456458 }
@@ -481,11 +483,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
481483
482484 /// Helper function to read an OsString from a 0x0000-terminated sequence of u16,
483485 /// which is what the Windows APIs usually handle.
484- fn read_os_str_from_wide_str < ' a > ( & ' a self , scalar : Scalar < Tag > ) -> InterpResult < ' tcx , OsString >
485- where
486- ' tcx : ' a ,
487- ' mir : ' a ,
488- {
486+ fn read_os_str_from_wide_str < ' a > ( & ' a self , scalar : Scalar < Tag > ) -> InterpResult < ' tcx , OsString > {
489487 #[ cfg( target_os = "windows" ) ]
490488 fn u16vec_to_osstring < ' tcx > ( u16_vec : Vec < u16 > ) -> InterpResult < ' tcx , OsString > {
491489 Ok ( std:: os:: windows:: ffi:: OsStringExt :: from_wide ( & u16_vec[ ..] ) )
@@ -497,11 +495,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
497495 Ok ( s. into ( ) )
498496 }
499497
500- let this = self . eval_context_ref ( ) ;
501- let u16_vec = this. memory . read_wide_str ( scalar) ?;
498+ let u16_vec = self . eval_context_ref ( ) . memory . read_wide_str ( scalar) ?;
502499 u16vec_to_osstring ( u16_vec)
503500 }
504501
502+ /// Dispatches to appropriate implementations for writing an OsString to Memory,
503+ /// depending on the interpretation target.
505504 fn write_os_str_to_target_str (
506505 & mut self ,
507506 os_str : & OsStr ,
@@ -510,9 +509,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
510509 ) -> InterpResult < ' tcx , ( bool , u64 ) > {
511510 let target_os = self . eval_context_ref ( ) . tcx . sess . target . target . target_os . as_str ( ) ;
512511 match target_os {
513- "linux" => self . write_os_str_to_c_str ( os_str, mplace. ptr , size) ,
512+ "linux" | "macos" => self . write_os_str_to_c_str ( os_str, mplace. ptr , size) ,
514513 "windows" => self . write_os_str_to_wide_str ( os_str, mplace, size) ,
515- _ => panic ! ( "support for target OS not yet available" ) ,
514+ _ => throw_unsup_format ! ( "support for target OS not yet available" ) ,
516515 }
517516 }
518517
@@ -567,15 +566,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
567566 size : u64 ,
568567 ) -> InterpResult < ' tcx , ( bool , u64 ) > {
569568 #[ cfg( target_os = "windows" ) ]
570- fn os_str_to_u16vec ( os_str : & OsStr ) -> Vec < u16 > {
571- std:: os:: windows:: ffi:: OsStrExt :: encode_wide ( os_str) . collect ( )
569+ fn os_str_to_u16vec < ' tcx > ( os_str : & OsStr ) -> InterpResult < ' tcx , Vec < u16 > > {
570+ Ok ( std:: os:: windows:: ffi:: OsStrExt :: encode_wide ( os_str) . collect ( ) )
572571 }
573572 #[ cfg( not( target_os = "windows" ) ) ]
574- fn os_str_to_u16vec ( os_str : & OsStr ) -> Vec < u16 > {
575- os_str. to_str ( ) . unwrap ( ) . encode_utf16 ( ) . collect ( )
573+ fn os_str_to_u16vec < ' tcx > ( os_str : & OsStr ) -> InterpResult < ' tcx , Vec < u16 > > {
574+ // On non-unix platforms the best we can do to transform Vec<u16> from/to OS strings is to do the
575+ // intermediate transformation into strings. Which invalidates non-utf8 paths that are actually
576+ // valid.
577+ os_str
578+ . to_str ( )
579+ . map ( |s| s. encode_utf16 ( ) . collect ( ) )
580+ . ok_or_else ( || err_unsup_format ! ( "{:?} is not a valid utf-8 string" , os_str) . into ( ) )
576581 }
577582
578- let u16_vec = os_str_to_u16vec ( os_str) ;
583+ let u16_vec = os_str_to_u16vec ( os_str) ? ;
579584 // If `size` is smaller or equal than `bytes.len()`, writing `bytes` plus the required
580585 // 0x0000 terminator to memory would cause an out-of-bounds access.
581586 let string_length = u16_vec. len ( ) as u64 ;
@@ -594,15 +599,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
594599 Ok ( ( true , string_length) )
595600 }
596601
602+ /// Dispatches to appropriate implementations for allocating & writing OsString in Memory,
603+ /// depending on the interpretation target.
597604 fn alloc_os_str_as_target_str (
598605 & mut self ,
599606 os_str : & OsStr ,
600607 memkind : MemoryKind < MiriMemoryKind > ,
601608 ) -> MPlaceTy < ' tcx , Tag > {
602609 let target_os = self . eval_context_ref ( ) . tcx . sess . target . target . target_os . as_str ( ) ;
603610 match target_os {
604- "linux" => self . alloc_os_str_as_c_str ( os_str, memkind) ,
611+ "linux" | "macos" => self . alloc_os_str_as_c_str ( os_str, memkind) ,
605612 "windows" => self . alloc_os_str_as_wide_str ( os_str, memkind) ,
613+ _ => panic ! ( "support for target OS not yet available" ) ,
606614 }
607615 }
608616
0 commit comments