@@ -445,6 +445,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
445
445
' tcx : ' a ,
446
446
' mir : ' a ,
447
447
{
448
+ #[ cfg( target_os = "unix" ) ]
449
+ fn bytes_to_os_str < ' tcx , ' a > ( bytes : & ' a [ u8 ] ) -> InterpResult < ' tcx , & ' a OsStr > {
450
+ Ok ( std:: os:: unix:: ffi:: OsStringExt :: from_bytes ( bytes) )
451
+ }
452
+ #[ cfg( not( target_os = "unix" ) ) ]
453
+ fn bytes_to_os_str < ' tcx , ' a > ( bytes : & ' a [ u8 ] ) -> InterpResult < ' tcx , & ' a OsStr > {
454
+ let s = std:: str:: from_utf8 ( bytes)
455
+ . map_err ( |_| err_unsup_format ! ( "{:?} is not a valid utf-8 string" , bytes) ) ?;
456
+ Ok ( & OsStr :: new ( s) )
457
+ }
458
+
448
459
let this = self . eval_context_ref ( ) ;
449
460
let bytes = this. memory . read_c_str ( scalar) ?;
450
461
bytes_to_os_str ( bytes)
@@ -460,6 +471,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
460
471
scalar : Scalar < Tag > ,
461
472
size : u64 ,
462
473
) -> InterpResult < ' tcx , bool > {
474
+ #[ cfg( target_os = "unix" ) ]
475
+ fn os_str_to_bytes < ' tcx , ' a > ( os_str : & ' a OsStr ) -> InterpResult < ' tcx , & ' a [ u8 ] > {
476
+ std:: os:: unix:: ffi:: OsStringExt :: into_bytes ( os_str)
477
+ }
478
+ #[ cfg( not( target_os = "unix" ) ) ]
479
+ fn os_str_to_bytes < ' tcx , ' a > ( os_str : & ' a OsStr ) -> InterpResult < ' tcx , & ' a [ u8 ] > {
480
+ // On non-unix platforms the best we can do to transform bytes from/to OS strings is to do the
481
+ // intermediate transformation into strings. Which invalidates non-utf8 paths that are actually
482
+ // valid.
483
+ os_str
484
+ . to_str ( )
485
+ . map ( |s| s. as_bytes ( ) )
486
+ . ok_or_else ( || err_unsup_format ! ( "{:?} is not a valid utf-8 string" , os_str) . into ( ) )
487
+ }
488
+
463
489
let bytes = os_str_to_bytes ( os_str) ?;
464
490
// If `size` is smaller or equal than `bytes.len()`, writing `bytes` plus the required null
465
491
// terminator to memory using the `ptr` pointer would cause an out-of-bounds access.
@@ -473,63 +499,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
473
499
}
474
500
}
475
501
476
- #[ cfg( target_os = "unix" ) ]
477
- fn os_str_to_bytes < ' tcx , ' a > ( os_str : & ' a OsStr ) -> InterpResult < ' tcx , & ' a [ u8 ] > {
478
- std:: os:: unix:: ffi:: OsStringExt :: into_bytes ( os_str)
479
- }
480
-
481
- #[ cfg( target_os = "unix" ) ]
482
- fn bytes_to_os_str < ' tcx , ' a > ( bytes : & ' a [ u8 ] ) -> InterpResult < ' tcx , & ' a OsStr > {
483
- Ok ( std:: os:: unix:: ffi:: OsStringExt :: from_bytes ( bytes) )
484
- }
485
-
486
- // On non-unix platforms the best we can do to transform bytes from/to OS strings is to do the
487
- // intermediate transformation into strings. Which invalidates non-utf8 paths that are actually
488
- // valid.
489
- #[ cfg( not( target_os = "unix" ) ) ]
490
- fn os_str_to_bytes < ' tcx , ' a > ( os_str : & ' a OsStr ) -> InterpResult < ' tcx , & ' a [ u8 ] > {
491
- os_str
492
- . to_str ( )
493
- . map ( |s| s. as_bytes ( ) )
494
- . ok_or_else ( || err_unsup_format ! ( "{:?} is not a valid utf-8 string" , os_str) . into ( ) )
495
- }
496
-
497
- #[ cfg( not( target_os = "unix" ) ) ]
498
- fn bytes_to_os_str < ' tcx , ' a > ( bytes : & ' a [ u8 ] ) -> InterpResult < ' tcx , & ' a OsStr > {
499
- let s = std:: str:: from_utf8 ( bytes)
500
- . map_err ( |_| err_unsup_format ! ( "{:?} is not a valid utf-8 string" , bytes) ) ?;
501
- Ok ( & OsStr :: new ( s) )
502
- }
503
-
504
- // FIXME: change `ImmTy::from_int` so it returns an `InterpResult` instead and remove this
505
- // function.
506
502
pub fn immty_from_int_checked < ' tcx > (
507
503
int : impl Into < i128 > ,
508
504
layout : TyLayout < ' tcx > ,
509
505
) -> InterpResult < ' tcx , ImmTy < ' tcx , Tag > > {
510
506
let int = int. into ( ) ;
511
- // If `int` does not fit in `size` bits, we error instead of letting
512
- // `ImmTy::from_int` panic.
513
- let size = layout. size ;
514
- let truncated = truncate ( int as u128 , size) ;
515
- if sign_extend ( truncated, size) as i128 != int {
516
- throw_unsup_format ! ( "Signed value {:#x} does not fit in {} bits" , int, size. bits( ) )
517
- }
518
- Ok ( ImmTy :: from_int ( int, layout) )
507
+ Ok ( ImmTy :: try_from_int ( int, layout) . ok_or_else ( ||
508
+ err_unsup_format ! ( "Signed value {:#x} does not fit in {} bits" , int, layout. size. bits( ) )
509
+ ) ?)
519
510
}
520
511
521
- // FIXME: change `ImmTy::from_uint` so it returns an `InterpResult` instead and remove this
522
- // function.
523
512
pub fn immty_from_uint_checked < ' tcx > (
524
513
int : impl Into < u128 > ,
525
514
layout : TyLayout < ' tcx > ,
526
515
) -> InterpResult < ' tcx , ImmTy < ' tcx , Tag > > {
527
516
let int = int. into ( ) ;
528
- // If `int` does not fit in `size` bits, we error instead of letting
529
- // `ImmTy::from_int` panic.
530
- let size = layout. size ;
531
- if truncate ( int, size) != int {
532
- throw_unsup_format ! ( "Unsigned value {:#x} does not fit in {} bits" , int, size. bits( ) )
533
- }
534
- Ok ( ImmTy :: from_uint ( int, layout) )
517
+ Ok ( ImmTy :: try_from_uint ( int, layout) . ok_or_else ( ||
518
+ err_unsup_format ! ( "Signed value {:#x} does not fit in {} bits" , int, layout. size. bits( ) )
519
+ ) ?)
535
520
}
0 commit comments