Skip to content

Commit a3844aa

Browse files
committed
Pass the dest place into read and move the actual writing to pointer to a free function
1 parent 7ad60d4 commit a3844aa

File tree

2 files changed

+43
-33
lines changed

2 files changed

+43
-33
lines changed

src/shims/unix/fd.rs

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
537537
buf: Pointer,
538538
count: u64,
539539
offset: Option<i128>,
540-
) -> InterpResult<'tcx, Scalar> {
540+
dest: &MPlaceTy<'tcx>,
541+
) -> InterpResult<'tcx> {
541542
let this = self.eval_context_mut();
542543

543544
// Isolation check is done via `FileDescription` trait.
@@ -557,50 +558,33 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
557558
// We temporarily dup the FD to be able to retain mutable access to `this`.
558559
let Some(fd) = this.machine.fds.get(fd_num) else {
559560
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(());
561564
};
562565

563566
trace!("read: FD mapped to {fd:?}");
564567
// We want to read at most `count` bytes. We are sure that `count` is not negative
565568
// because it was a target's `usize`. Also we are sure that its smaller than
566569
// `usize::MAX` because it is bounded by the host's `isize`.
567570

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.
569572
let mut bytes = vec![0; usize::try_from(count).unwrap()];
570573
let result = match offset {
571574
None => fd.read(&fd, communicate, &mut bytes, buf, this),
572575
Some(offset) => {
573576
let Ok(offset) = u64::try_from(offset) else {
574577
let einval = this.eval_libc("EINVAL");
575578
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(());
577581
};
578582
fd.pread(communicate, &mut bytes, offset, this)
579583
}
580584
};
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(())
604588
}
605589

606590
fn write(
@@ -646,3 +630,32 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
646630
Ok(Scalar::from_target_isize(this.try_unwrap_io_result(result)?, this))
647631
}
648632
}
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+
}

src/shims/unix/foreign_items.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
9292
let fd = this.read_scalar(fd)?.to_i32()?;
9393
let buf = this.read_pointer(buf)?;
9494
let count = this.read_target_usize(count)?;
95-
let result = this.read(fd, buf, count, None)?;
96-
this.write_scalar(result, dest)?;
95+
this.read(fd, buf, count, None, dest)?;
9796
}
9897
"write" => {
9998
let [fd, buf, n] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
@@ -111,8 +110,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
111110
let buf = this.read_pointer(buf)?;
112111
let count = this.read_target_usize(count)?;
113112
let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off_t").size)?;
114-
let result = this.read(fd, buf, count, Some(offset))?;
115-
this.write_scalar(result, dest)?;
113+
this.read(fd, buf, count, Some(offset), dest)?;
116114
}
117115
"pwrite" => {
118116
let [fd, buf, n, offset] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
@@ -131,8 +129,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
131129
let buf = this.read_pointer(buf)?;
132130
let count = this.read_target_usize(count)?;
133131
let offset = this.read_scalar(offset)?.to_int(this.libc_ty_layout("off64_t").size)?;
134-
let result = this.read(fd, buf, count, Some(offset))?;
135-
this.write_scalar(result, dest)?;
132+
this.read(fd, buf, count, Some(offset), dest)?;
136133
}
137134
"pwrite64" => {
138135
let [fd, buf, n, offset] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;

0 commit comments

Comments
 (0)