@@ -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