Skip to content

Commit ca0e5df

Browse files
authored
Merge pull request rust-lang#3995 from RalfJung/readdir_r
fix error returned from readdir_r when isolation is enabled, and uses of raw_os_error
2 parents d1530f0 + 4a34e27 commit ca0e5df

File tree

1 file changed

+16
-26
lines changed
  • src/tools/miri/src/shims/unix

1 file changed

+16
-26
lines changed

src/tools/miri/src/shims/unix/fs.rs

+16-26
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,8 @@ impl FileDescription for FileHandle {
231231
TRUE => Ok(()),
232232
FALSE => {
233233
let mut err = io::Error::last_os_error();
234+
// This only runs on Windows hosts so we can use `raw_os_error`.
235+
// We have to be careful not to forward that error code to target code.
234236
let code: u32 = err.raw_os_error().unwrap().try_into().unwrap();
235237
if matches!(code, ERROR_IO_PENDING | ERROR_LOCK_VIOLATION) {
236238
if lock_nb {
@@ -339,15 +341,10 @@ trait EvalContextExtPrivate<'tcx>: crate::MiriInterpCxExt<'tcx> {
339341
_ => interp_ok(this.eval_libc("DT_UNKNOWN").to_u8()?.into()),
340342
}
341343
}
342-
Err(e) =>
343-
match e.raw_os_error() {
344-
Some(error) => interp_ok(error),
345-
None =>
346-
throw_unsup_format!(
347-
"the error {} couldn't be converted to a return value",
348-
e
349-
),
350-
},
344+
Err(_) => {
345+
// Fallback on error
346+
interp_ok(this.eval_libc("DT_UNKNOWN").to_u8()?.into())
347+
}
351348
}
352349
}
353350
}
@@ -1132,14 +1129,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
11321129
// Reject if isolation is enabled.
11331130
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
11341131
this.reject_in_isolation("`readdir_r`", reject_with)?;
1135-
// Set error code as "EBADF" (bad fd)
1136-
return this.set_last_error_and_return_i32(LibcError("EBADF"));
1132+
// Return error code, do *not* set `errno`.
1133+
return interp_ok(this.eval_libc("EBADF"));
11371134
}
11381135

11391136
let open_dir = this.machine.dirs.streams.get_mut(&dirp).ok_or_else(|| {
11401137
err_unsup_format!("the DIR pointer passed to readdir_r did not come from opendir")
11411138
})?;
1142-
interp_ok(Scalar::from_i32(match open_dir.read_dir.next() {
1139+
interp_ok(match open_dir.read_dir.next() {
11431140
Some(Ok(dir_entry)) => {
11441141
// Write into entry, write pointer to result, return 0 on success.
11451142
// The name is written with write_os_str_to_c_str, while the rest of the
@@ -1217,25 +1214,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
12171214
let result_place = this.deref_pointer(result_op)?;
12181215
this.write_scalar(this.read_scalar(entry_op)?, &result_place)?;
12191216

1220-
0
1217+
Scalar::from_i32(0)
12211218
}
12221219
None => {
12231220
// end of stream: return 0, assign *result=NULL
12241221
this.write_null(&this.deref_pointer(result_op)?)?;
1225-
0
1222+
Scalar::from_i32(0)
12261223
}
1227-
Some(Err(e)) =>
1228-
match e.raw_os_error() {
1229-
// return positive error number on error
1230-
Some(error) => error,
1231-
None => {
1232-
throw_unsup_format!(
1233-
"the error {} couldn't be converted to a return value",
1234-
e
1235-
)
1236-
}
1237-
},
1238-
}))
1224+
Some(Err(e)) => {
1225+
// return positive error number on error (do *not* set last error)
1226+
this.io_error_to_errnum(e)?
1227+
}
1228+
})
12391229
}
12401230

12411231
fn closedir(&mut self, dirp_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {

0 commit comments

Comments
 (0)