Skip to content

Commit

Permalink
Less hacky read/write
Browse files Browse the repository at this point in the history
  • Loading branch information
CraftSpider committed Dec 2, 2024
1 parent 149a68b commit 85d4f2e
Showing 1 changed file with 47 additions and 30 deletions.
77 changes: 47 additions & 30 deletions src/shims/windows/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
throw_unsup_format!("`NtWriteFile` `Key` parameter is not null, which is unsupported");
}

// We have to put the result into io_status_block.
let io_status_information = this.project_field_named(&io_status_block, "Information")?;

let written = match handle {
Handle::Pseudo(pseudo @ (PseudoHandle::Stdout | PseudoHandle::Stderr)) => {
// stdout/stderr
Expand All @@ -445,33 +448,39 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
io::Write::write(&mut io::stderr(), buf_cont)
};
// We write at most `n` bytes, which is a `u32`, so we cannot have written more than that.
res.ok().map(|n| u32::try_from(n).unwrap())
if let Ok(n) = res {
this.write_scalar(
Scalar::from_target_usize(n.try_into().unwrap(), this),
&io_status_information,
)?;
true
} else {
false
}
}
Handle::File(fd) => {
let Some(desc) = this.machine.fds.get(fd) else {
this.invalid_handle("NtWriteFile")?
};

let errno_layout = this.machine.layouts.u32;
let out_place = this.allocate(errno_layout, MiriMemoryKind::Machine.into())?;
desc.write(&desc, this.machine.communicate(), buf, n as usize, &out_place, this)?;
let written = this.read_scalar(&out_place)?.to_u32()?;
this.deallocate_ptr(out_place.ptr(), None, MiriMemoryKind::Machine.into())?;
Some(written)
// TODO: Windows expects this function to return its error, not set the global one
desc.write(
&desc,
this.machine.communicate(),
buf,
n as usize,
&io_status_information,
this,
)?;
let written = this.read_scalar(&io_status_information)?.to_i64()?;
written != -1
}
_ => this.invalid_handle("NtWriteFile")?,
};

// We have to put the result into io_status_block.
if let Some(n) = written {
let io_status_information =
this.project_field_named(&io_status_block, "Information")?;
this.write_scalar(Scalar::from_target_usize(n.into(), this), &io_status_information)?;
}

// Return whether this was a success. >= 0 is success.
// For the error code we arbitrarily pick 0xC0000185, STATUS_IO_DEVICE_ERROR.
interp_ok(Scalar::from_u32(if written.is_some() { 0 } else { 0xC0000185u32 }))
interp_ok(Scalar::from_u32(if written { 0 } else { 0xC0000185u32 }))
}

fn NtReadFile(
Expand Down Expand Up @@ -527,40 +536,48 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
throw_unsup_format!("`NtWriteFile` `Key` parameter is not null, which is unsupported");
}

let io_status_information = this.project_field_named(&io_status_block, "Information")?;

let read = match handle {
Handle::Pseudo(PseudoHandle::Stdin) => {
// stdout/stderr
let mut buf_cont = vec![0u8; n as usize];
let res = io::Read::read(&mut io::stdin(), &mut buf_cont);
this.write_bytes_ptr(buf, buf_cont)?;
// We write at most `n` bytes, which is a `u32`, so we cannot have written more than that.
res.ok().map(|n| u32::try_from(n).unwrap())
if let Ok(n) = res {
this.write_scalar(
Scalar::from_target_usize(n.try_into().unwrap(), this),
&io_status_information,
)?;
true
} else {
false
}
}
Handle::File(fd) => {
let Some(desc) = this.machine.fds.get(fd) else {
this.invalid_handle("NtReadFile")?
};

let errno_layout = this.machine.layouts.u32;
let out_place = this.allocate(errno_layout, MiriMemoryKind::Machine.into())?;
desc.read(&desc, this.machine.communicate(), buf, n as usize, &out_place, this)?;
let read = this.read_scalar(&out_place)?.to_u32()?;
this.deallocate_ptr(out_place.ptr(), None, MiriMemoryKind::Machine.into())?;
Some(read)
// TODO: Windows expects this function to return its error, not set the global one
desc.read(
&desc,
this.machine.communicate(),
buf,
n as usize,
&io_status_information,
this,
)?;
let read = this.read_scalar(&io_status_information)?.to_i64()?;
read != -1
}
_ => this.invalid_handle("NtReadFile")?,
};

// We have to put the result into io_status_block.
if let Some(n) = read {
let io_status_information =
this.project_field_named(&io_status_block, "Information")?;
this.write_scalar(Scalar::from_target_usize(n.into(), this), &io_status_information)?;
}

// Return whether this was a success. >= 0 is success.
// For the error code we arbitrarily pick 0xC0000185, STATUS_IO_DEVICE_ERROR.
interp_ok(Scalar::from_u32(if read.is_some() { 0 } else { 0xC0000185u32 }))
interp_ok(Scalar::from_u32(if read { 0 } else { 0xC0000185u32 }))
}

fn SetFilePointerEx(
Expand Down

0 comments on commit 85d4f2e

Please sign in to comment.