@@ -447,10 +447,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
447
447
}
448
448
}
449
449
450
+ /// Dispatches to appropriate implementations for reading an OsString from Memory,
451
+ /// depending on the interpretation target.
450
452
fn read_os_str_from_target_str < ' a > ( & ' a self , scalar : Scalar < Tag > ) -> InterpResult < ' tcx , OsString > {
451
453
let target_os = self . eval_context_ref ( ) . tcx . sess . target . target . target_os . as_str ( ) ;
452
454
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 ( ) ) ,
454
456
"windows" => self . read_os_str_from_wide_str ( scalar) ,
455
457
_ => throw_unsup_format ! ( "support for target OS not yet available" ) ,
456
458
}
@@ -481,11 +483,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
481
483
482
484
/// Helper function to read an OsString from a 0x0000-terminated sequence of u16,
483
485
/// 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 > {
489
487
#[ cfg( target_os = "windows" ) ]
490
488
fn u16vec_to_osstring < ' tcx > ( u16_vec : Vec < u16 > ) -> InterpResult < ' tcx , OsString > {
491
489
Ok ( std:: os:: windows:: ffi:: OsStringExt :: from_wide ( & u16_vec[ ..] ) )
@@ -497,11 +495,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
497
495
Ok ( s. into ( ) )
498
496
}
499
497
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) ?;
502
499
u16vec_to_osstring ( u16_vec)
503
500
}
504
501
502
+ /// Dispatches to appropriate implementations for writing an OsString to Memory,
503
+ /// depending on the interpretation target.
505
504
fn write_os_str_to_target_str (
506
505
& mut self ,
507
506
os_str : & OsStr ,
@@ -510,9 +509,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
510
509
) -> InterpResult < ' tcx , ( bool , u64 ) > {
511
510
let target_os = self . eval_context_ref ( ) . tcx . sess . target . target . target_os . as_str ( ) ;
512
511
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) ,
514
513
"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" ) ,
516
515
}
517
516
}
518
517
@@ -567,15 +566,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
567
566
size : u64 ,
568
567
) -> InterpResult < ' tcx , ( bool , u64 ) > {
569
568
#[ 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 ( ) )
572
571
}
573
572
#[ 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 ( ) )
576
581
}
577
582
578
- let u16_vec = os_str_to_u16vec ( os_str) ;
583
+ let u16_vec = os_str_to_u16vec ( os_str) ? ;
579
584
// If `size` is smaller or equal than `bytes.len()`, writing `bytes` plus the required
580
585
// 0x0000 terminator to memory would cause an out-of-bounds access.
581
586
let string_length = u16_vec. len ( ) as u64 ;
@@ -594,15 +599,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
594
599
Ok ( ( true , string_length) )
595
600
}
596
601
602
+ /// Dispatches to appropriate implementations for allocating & writing OsString in Memory,
603
+ /// depending on the interpretation target.
597
604
fn alloc_os_str_as_target_str (
598
605
& mut self ,
599
606
os_str : & OsStr ,
600
607
memkind : MemoryKind < MiriMemoryKind > ,
601
608
) -> MPlaceTy < ' tcx , Tag > {
602
609
let target_os = self . eval_context_ref ( ) . tcx . sess . target . target . target_os . as_str ( ) ;
603
610
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) ,
605
612
"windows" => self . alloc_os_str_as_wide_str ( os_str, memkind) ,
613
+ _ => panic ! ( "support for target OS not yet available" ) ,
606
614
}
607
615
}
608
616
0 commit comments