Skip to content

Commit 19acb93

Browse files
committed
Less hacky read/write
1 parent d8720c9 commit 19acb93

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
@@ -433,6 +433,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
433433
throw_unsup_format!("`NtWriteFile` `Key` parameter is not null, which is unsupported");
434434
}
435435

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

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

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

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

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

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

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

567584
fn SetFilePointerEx(

0 commit comments

Comments
 (0)