@@ -474,35 +474,42 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
474
474
}
475
475
476
476
/// Helper function to write an OsStr as a null-terminated sequence of bytes, which is what
477
- /// the Unix APIs usually handle. This function returns `Ok(false)` without trying to write if
478
- /// `size` is not large enough to fit the contents of `os_string` plus a null terminator. It
479
- /// returns `Ok(true)` if the writing process was successful.
477
+ /// the Unix APIs usually handle. This function returns `Ok((false, length))` without trying
478
+ /// to write if `size` is not large enough to fit the contents of `os_string` plus a null
479
+ /// terminator. It returns `Ok((true, length))` if the writing process was successful. The
480
+ /// string length returned does not include the null terminator.
480
481
fn write_os_str_to_c_str (
481
482
& mut self ,
482
483
os_str : & OsStr ,
483
484
scalar : Scalar < Tag > ,
484
485
size : u64 ,
485
- ) -> InterpResult < ' tcx , bool > {
486
+ ) -> InterpResult < ' tcx , ( bool , u64 ) > {
487
+ #[ cfg( target_os = "unix" ) ]
488
+ fn os_str_to_bytes < ' tcx , ' a > ( os_str : & ' a OsStr ) -> InterpResult < ' tcx , & ' a [ u8 ] > {
489
+ std:: os:: unix:: ffi:: OsStringExt :: into_bytes ( os_str)
490
+ }
491
+ #[ cfg( not( target_os = "unix" ) ) ]
492
+ fn os_str_to_bytes < ' tcx , ' a > ( os_str : & ' a OsStr ) -> InterpResult < ' tcx , & ' a [ u8 ] > {
493
+ // On non-unix platforms the best we can do to transform bytes from/to OS strings is to do the
494
+ // intermediate transformation into strings. Which invalidates non-utf8 paths that are actually
495
+ // valid.
496
+ os_str
497
+ . to_str ( )
498
+ . map ( |s| s. as_bytes ( ) )
499
+ . ok_or_else ( || err_unsup_format ! ( "{:?} is not a valid utf-8 string" , os_str) . into ( ) )
500
+ }
501
+
486
502
let bytes = os_str_to_bytes ( os_str) ?;
487
503
// If `size` is smaller or equal than `bytes.len()`, writing `bytes` plus the required null
488
504
// terminator to memory using the `ptr` pointer would cause an out-of-bounds access.
489
- if size <= bytes. len ( ) as u64 {
490
- return Ok ( false ) ;
505
+ let string_length = bytes. len ( ) as u64 ;
506
+ if size <= string_length {
507
+ return Ok ( ( false , string_length) ) ;
491
508
}
492
509
self . eval_context_mut ( )
493
510
. memory
494
511
. write_bytes ( scalar, bytes. iter ( ) . copied ( ) . chain ( iter:: once ( 0u8 ) ) ) ?;
495
- Ok ( true )
496
- }
497
-
498
- /// Helper function to determine how long an OsStr would be as a C string, not including the
499
- /// null terminator.
500
- fn os_str_length_as_c_str (
501
- & mut self ,
502
- os_str : & OsStr ,
503
- ) -> InterpResult < ' tcx , usize > {
504
- let bytes = os_str_to_bytes ( os_str) ?;
505
- Ok ( bytes. len ( ) )
512
+ Ok ( ( true , string_length) )
506
513
}
507
514
508
515
fn alloc_os_str_as_c_str (
@@ -520,22 +527,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
520
527
}
521
528
}
522
529
523
- #[ cfg( target_os = "unix" ) ]
524
- fn os_str_to_bytes < ' tcx , ' a > ( os_str : & ' a OsStr ) -> InterpResult < ' tcx , & ' a [ u8 ] > {
525
- std:: os:: unix:: ffi:: OsStringExt :: into_bytes ( os_str)
526
- }
527
-
528
- #[ cfg( not( target_os = "unix" ) ) ]
529
- fn os_str_to_bytes < ' tcx , ' a > ( os_str : & ' a OsStr ) -> InterpResult < ' tcx , & ' a [ u8 ] > {
530
- // On non-unix platforms the best we can do to transform bytes from/to OS strings is to do the
531
- // intermediate transformation into strings. Which invalidates non-utf8 paths that are actually
532
- // valid.
533
- os_str
534
- . to_str ( )
535
- . map ( |s| s. as_bytes ( ) )
536
- . ok_or_else ( || err_unsup_format ! ( "{:?} is not a valid utf-8 string" , os_str) . into ( ) )
537
- }
538
-
539
530
pub fn immty_from_int_checked < ' tcx > (
540
531
int : impl Into < i128 > ,
541
532
layout : TyLayout < ' tcx > ,
0 commit comments