Skip to content

Commit 85d4f2e

Browse files
committed
Less hacky read/write
1 parent 149a68b commit 85d4f2e

File tree

1 file changed

+47
-30
lines changed

1 file changed

+47
-30
lines changed

src/shims/windows/fs.rs

+47-30
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
432432
throw_unsup_format!("`NtWriteFile` `Key` parameter is not null, which is unsupported");
433433
}
434434

435+
// We have to put the result into io_status_block.
436+
let io_status_information = this.project_field_named(&io_status_block, "Information")?;
437+
435438
let written = match handle {
436439
Handle::Pseudo(pseudo @ (PseudoHandle::Stdout | PseudoHandle::Stderr)) => {
437440
// stdout/stderr
@@ -445,33 +448,39 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
445448
io::Write::write(&mut io::stderr(), buf_cont)
446449
};
447450
// We write at most `n` bytes, which is a `u32`, so we cannot have written more than that.
448-
res.ok().map(|n| u32::try_from(n).unwrap())
451+
if let Ok(n) = res {
452+
this.write_scalar(
453+
Scalar::from_target_usize(n.try_into().unwrap(), this),
454+
&io_status_information,
455+
)?;
456+
true
457+
} else {
458+
false
459+
}
449460
}
450461
Handle::File(fd) => {
451462
let Some(desc) = this.machine.fds.get(fd) else {
452463
this.invalid_handle("NtWriteFile")?
453464
};
454465

455-
let errno_layout = this.machine.layouts.u32;
456-
let out_place = this.allocate(errno_layout, MiriMemoryKind::Machine.into())?;
457-
desc.write(&desc, this.machine.communicate(), buf, n as usize, &out_place, this)?;
458-
let written = this.read_scalar(&out_place)?.to_u32()?;
459-
this.deallocate_ptr(out_place.ptr(), None, MiriMemoryKind::Machine.into())?;
460-
Some(written)
466+
// TODO: Windows expects this function to return its error, not set the global one
467+
desc.write(
468+
&desc,
469+
this.machine.communicate(),
470+
buf,
471+
n as usize,
472+
&io_status_information,
473+
this,
474+
)?;
475+
let written = this.read_scalar(&io_status_information)?.to_i64()?;
476+
written != -1
461477
}
462478
_ => this.invalid_handle("NtWriteFile")?,
463479
};
464480

465-
// We have to put the result into io_status_block.
466-
if let Some(n) = written {
467-
let io_status_information =
468-
this.project_field_named(&io_status_block, "Information")?;
469-
this.write_scalar(Scalar::from_target_usize(n.into(), this), &io_status_information)?;
470-
}
471-
472481
// Return whether this was a success. >= 0 is success.
473482
// For the error code we arbitrarily pick 0xC0000185, STATUS_IO_DEVICE_ERROR.
474-
interp_ok(Scalar::from_u32(if written.is_some() { 0 } else { 0xC0000185u32 }))
483+
interp_ok(Scalar::from_u32(if written { 0 } else { 0xC0000185u32 }))
475484
}
476485

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

539+
let io_status_information = this.project_field_named(&io_status_block, "Information")?;
540+
530541
let read = match handle {
531542
Handle::Pseudo(PseudoHandle::Stdin) => {
532543
// stdout/stderr
533544
let mut buf_cont = vec![0u8; n as usize];
534545
let res = io::Read::read(&mut io::stdin(), &mut buf_cont);
535546
this.write_bytes_ptr(buf, buf_cont)?;
536547
// We write at most `n` bytes, which is a `u32`, so we cannot have written more than that.
537-
res.ok().map(|n| u32::try_from(n).unwrap())
548+
if let Ok(n) = res {
549+
this.write_scalar(
550+
Scalar::from_target_usize(n.try_into().unwrap(), this),
551+
&io_status_information,
552+
)?;
553+
true
554+
} else {
555+
false
556+
}
538557
}
539558
Handle::File(fd) => {
540559
let Some(desc) = this.machine.fds.get(fd) else {
541560
this.invalid_handle("NtReadFile")?
542561
};
543562

544-
let errno_layout = this.machine.layouts.u32;
545-
let out_place = this.allocate(errno_layout, MiriMemoryKind::Machine.into())?;
546-
desc.read(&desc, this.machine.communicate(), buf, n as usize, &out_place, this)?;
547-
let read = this.read_scalar(&out_place)?.to_u32()?;
548-
this.deallocate_ptr(out_place.ptr(), None, MiriMemoryKind::Machine.into())?;
549-
Some(read)
563+
// TODO: Windows expects this function to return its error, not set the global one
564+
desc.read(
565+
&desc,
566+
this.machine.communicate(),
567+
buf,
568+
n as usize,
569+
&io_status_information,
570+
this,
571+
)?;
572+
let read = this.read_scalar(&io_status_information)?.to_i64()?;
573+
read != -1
550574
}
551575
_ => this.invalid_handle("NtReadFile")?,
552576
};
553577

554-
// We have to put the result into io_status_block.
555-
if let Some(n) = read {
556-
let io_status_information =
557-
this.project_field_named(&io_status_block, "Information")?;
558-
this.write_scalar(Scalar::from_target_usize(n.into(), this), &io_status_information)?;
559-
}
560-
561578
// Return whether this was a success. >= 0 is success.
562579
// For the error code we arbitrarily pick 0xC0000185, STATUS_IO_DEVICE_ERROR.
563-
interp_ok(Scalar::from_u32(if read.is_some() { 0 } else { 0xC0000185u32 }))
580+
interp_ok(Scalar::from_u32(if read { 0 } else { 0xC0000185u32 }))
564581
}
565582

566583
fn SetFilePointerEx(

0 commit comments

Comments
 (0)