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