Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: handle writing to dest within the foreign item handler #3779

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

oli-obk
Copy link
Contributor

@oli-obk oli-obk commented Jul 31, 2024

alternative to #3777

Some(metadata) => metadata,
None => return Ok(Scalar::from_i32(-1)), // `FileMetadata` has set errno
None => return Ok(EmulateItemResult::NeedsReturn),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
None => return Ok(EmulateItemResult::NeedsReturn),
None => return Ok(EmulateItemResult::NeedsReturn), // `FileMetadata::from_path` has set the return value

But this is a bit odd, seems cleaner to instead have from_path return a Result and do the errno+return handling here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit annoying as I have to return a Result<T, Scalar> to be able to handle both EBADF and io::Error, but generally nicer indeed

src/shims/unix/fs.rs Outdated Show resolved Hide resolved
src/helpers.rs Outdated Show resolved Hide resolved
src/shims/unix/fs.rs Outdated Show resolved Hide resolved
@RalfJung RalfJung added the S-waiting-on-author Status: Waiting for the PR author to address review comments label Aug 17, 2024
@bors
Copy link
Collaborator

bors commented Aug 27, 2024

☔ The latest upstream changes (presumably #3804) made this pull request unmergeable. Please resolve the merge conflicts.

@oli-obk
Copy link
Contributor Author

oli-obk commented Sep 28, 2024

if this is to your liking, I'll port everything

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Waiting for a review to complete and removed S-waiting-on-author Status: Waiting for the PR author to address review comments labels Sep 28, 2024
@bors
Copy link
Collaborator

bors commented Oct 1, 2024

☔ The latest upstream changes (presumably #3923) made this pull request unmergeable. Please resolve the merge conflicts.

Copy link
Member

@RalfJung RalfJung left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I generally like it, modulo the comments here. Note that this has more overlap with #3930 than I thought, so we should be careful to avoid conflicts.

) -> InterpResult<'tcx> {
self.set_last_error(err)?;
self.eval_context_mut().write_int(-1, dest)
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both of these new functions are superseded by the helper that @tiif added and that I extended. You should be able to use set_last_error_and_return now (after a rebase).

/// Helper function that consumes an `std::io::Result<i32>` and writes the `Ok` integer
/// to the destination. In case the result is an error, this function writes
/// `-1` and sets the last OS error accordingly.
fn write_io_result(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move this to the new io_error.rs file, and put it right below try_unwrap_io_result (since it extends that helper).

Some(metadata) => metadata,
None => return Ok(Scalar::from_i32(-1)), // `FileMetadata` has set errno
Ok(metadata) => metadata,
Err(e) => return this.set_last_err_and_return_neg1(e, dest),
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get the feeling we will have this pattern a lot... given an io::Result<T>, call return this.set_last_error_and_return on the error path and unwrap the T otherwise. Do you think that'd be worth a try!-like macro?

@@ -1050,7 +1051,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.reject_in_isolation("`readdir`", reject_with)?;
let eacc = this.eval_libc("EBADF");
this.set_last_error(eacc)?;
return Ok(Scalar::null_ptr(this));
return this.write_scalar(eacc, dest);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changes behavior, doesn't it? We should be returning a null pointer but you made it return eacc now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should fix this one in a separate PR with a test that shows the behaviour change. The previous behaviour is buggy

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it was. readdir returns null on error.

readdir_r works different, but this is readdir.

@@ -1710,9 +1709,9 @@ impl FileMetadata {
fn from_fd_num<'tcx>(
ecx: &mut MiriInterpCx<'tcx>,
fd_num: i32,
) -> InterpResult<'tcx, Option<FileMetadata>> {
) -> InterpResult<'tcx, Result<FileMetadata, Scalar>> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a doc comment explaining the meaning of this return type. (Same for the next function.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessary, I can use your new error enum instead

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, even better :)

@@ -1148,14 +1150,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
// Reject if isolation is enabled.
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
this.reject_in_isolation("`readdir_r`", reject_with)?;
// Set error code as "EBADF" (bad fd)
return Ok(Scalar::from_i32(this.fd_not_found()?));
// return positive error number on error
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// return positive error number on error
// Return positive error number on error (*without* setting errno!)

@@ -27,7 +27,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
flags: &OpTy<'tcx>,
fd: &OpTy<'tcx>,
offset: i128,
) -> InterpResult<'tcx, Scalar> {
dest: &MPlaceTy<'tcx>,
) -> InterpResult<'tcx, EmulateItemResult> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So these here now return EmulateItemResult but the ones in fs.rs do not. As I said here I'd prefer to avoid having the EmulateItemResult for functions that don't need it. It is extremely rare to need this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably just an oversight, I wanted to change all of them back.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-review Status: Waiting for a review to complete
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants