Skip to content

Commit 29774e9

Browse files
committed
Pass the dest place into read and move the actual writing to pointer to a free function
1 parent 439ff7d commit 29774e9

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
@@ -538,7 +538,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
538538
buf: Pointer,
539539
count: u64,
540540
offset: Option<i128>,
541-
) -> InterpResult<'tcx, Scalar> {
541+
dest: &MPlaceTy<'tcx>,
542+
) -> InterpResult<'tcx> {
542543
let this = self.eval_context_mut();
543544

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

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

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

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

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)