@@ -537,7 +537,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
537
537
buf : Pointer ,
538
538
count : u64 ,
539
539
offset : Option < i128 > ,
540
- ) -> InterpResult < ' tcx , Scalar > {
540
+ dest : & MPlaceTy < ' tcx > ,
541
+ ) -> InterpResult < ' tcx > {
541
542
let this = self . eval_context_mut ( ) ;
542
543
543
544
// Isolation check is done via `FileDescription` trait.
@@ -557,50 +558,33 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
557
558
// We temporarily dup the FD to be able to retain mutable access to `this`.
558
559
let Some ( fd) = this. machine . fds . get ( fd_num) else {
559
560
trace ! ( "read: FD not found" ) ;
560
- return Ok ( Scalar :: from_target_isize ( this. fd_not_found ( ) ?, this) ) ;
561
+ let res = Scalar :: from_target_isize ( this. fd_not_found ( ) ?, this) ;
562
+ this. write_scalar ( res, dest) ?;
563
+ return Ok ( ( ) ) ;
561
564
} ;
562
565
563
566
trace ! ( "read: FD mapped to {fd:?}" ) ;
564
567
// We want to read at most `count` bytes. We are sure that `count` is not negative
565
568
// because it was a target's `usize`. Also we are sure that its smaller than
566
569
// `usize::MAX` because it is bounded by the host's `isize`.
567
570
568
- // TODO: shouldn't pass vec, just pass pointer and write it.
571
+ // TODO: shouldn't pass vec, just pass pointer and directly write to it.
569
572
let mut bytes = vec ! [ 0 ; usize :: try_from( count) . unwrap( ) ] ;
570
573
let result = match offset {
571
574
None => fd. read ( & fd, communicate, & mut bytes, buf, this) ,
572
575
Some ( offset) => {
573
576
let Ok ( offset) = u64:: try_from ( offset) else {
574
577
let einval = this. eval_libc ( "EINVAL" ) ;
575
578
this. set_last_error ( einval) ?;
576
- return Ok ( Scalar :: from_target_isize ( -1 , this) ) ;
579
+ this. write_scalar ( Scalar :: from_target_isize ( -1 , this) , dest) ?;
580
+ return Ok ( ( ) ) ;
577
581
} ;
578
582
fd. pread ( communicate, & mut bytes, offset, this)
579
583
}
580
584
} ;
581
-
582
- // `File::read` never returns a value larger than `count`, so this cannot fail.
583
- match result?. map ( |c| i64:: try_from ( c) . unwrap ( ) ) {
584
- // TODO: get the byte out the result, then write the ptr.
585
- // try to pass this the write_ptr inside write
586
- // Pass the pointer inside the write function.
587
- Ok ( read_bytes) => {
588
- // If reading to `bytes` did not fail, we write those bytes to the buffer.
589
- // Crucially, if fewer than `bytes.len()` bytes were read, only write
590
- // that much into the output buffer!
591
-
592
- // TODO: write to pointer here.
593
- this. write_bytes_ptr (
594
- buf,
595
- bytes[ ..usize:: try_from ( read_bytes) . unwrap ( ) ] . iter ( ) . copied ( ) ,
596
- ) ?;
597
- Ok ( Scalar :: from_target_isize ( read_bytes, this) )
598
- }
599
- Err ( e) => {
600
- this. set_last_error_from_io_error ( e) ?;
601
- Ok ( Scalar :: from_target_isize ( -1 , this) )
602
- }
603
- }
585
+ let res = write_byte_helper ( buf, bytes, result, this) ?;
586
+ this. write_scalar ( res, dest) ?;
587
+ Ok ( ( ) )
604
588
}
605
589
606
590
fn write (
@@ -646,3 +630,32 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
646
630
Ok ( Scalar :: from_target_isize ( this. try_unwrap_io_result ( result) ?, this) )
647
631
}
648
632
}
633
+ // TODO: move this as a free function later
634
+ fn write_byte_helper < ' tcx > (
635
+ buf : Pointer ,
636
+ bytes : Vec < u8 > ,
637
+ result : InterpResult < ' tcx , io:: Result < usize > > ,
638
+ ecx : & mut MiriInterpCx < ' tcx > ,
639
+ ) -> InterpResult < ' tcx , Scalar > {
640
+ // `File::read` never returns a value larger than `count`, so this cannot fail.
641
+ match result?. map ( |c| i64:: try_from ( c) . unwrap ( ) ) {
642
+ // TODO: get the byte out the result, then write the ptr.
643
+ // try to pass this the write_ptr inside write
644
+ // Pass the pointer inside the write function.
645
+ Ok ( read_bytes) => {
646
+ // If reading to `bytes` did not fail, we write those bytes to the buffer.
647
+ // Crucially, if fewer than `bytes.len()` bytes were read, only write
648
+ // that much into the output buffer!
649
+ // TODO: write to pointer here.
650
+ ecx. write_bytes_ptr (
651
+ buf,
652
+ bytes[ ..usize:: try_from ( read_bytes) . unwrap ( ) ] . iter ( ) . copied ( ) ,
653
+ ) ?;
654
+ Ok ( Scalar :: from_target_isize ( read_bytes, ecx) )
655
+ }
656
+ Err ( e) => {
657
+ ecx. set_last_error_from_io_error ( e) ?;
658
+ Ok ( Scalar :: from_target_isize ( -1 , ecx) )
659
+ }
660
+ }
661
+ }
0 commit comments