Skip to content

Commit 6fc1b69

Browse files
committed
Use Scalar consistently in foreign item emulation
1 parent cf63c16 commit 6fc1b69

File tree

10 files changed

+239
-245
lines changed

10 files changed

+239
-245
lines changed

src/tools/miri/src/shims/time.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
9393
Ok(Scalar::from_i32(0))
9494
}
9595

96-
fn gettimeofday(&mut self, tv_op: &OpTy<'tcx>, tz_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
96+
fn gettimeofday(
97+
&mut self,
98+
tv_op: &OpTy<'tcx>,
99+
tz_op: &OpTy<'tcx>,
100+
) -> InterpResult<'tcx, Scalar> {
97101
let this = self.eval_context_mut();
98102

99103
this.assert_target_os_is_unix("gettimeofday");
@@ -106,7 +110,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
106110
if !this.ptr_is_null(tz)? {
107111
let einval = this.eval_libc("EINVAL");
108112
this.set_last_error(einval)?;
109-
return Ok(-1);
113+
return Ok(Scalar::from_i32(-1));
110114
}
111115

112116
let duration = system_time_to_duration(&SystemTime::now())?;
@@ -115,7 +119,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
115119

116120
this.write_int_fields(&[tv_sec.into(), tv_usec.into()], &tv)?;
117121

118-
Ok(0)
122+
Ok(Scalar::from_i32(0))
119123
}
120124

121125
// The localtime() function shall convert the time in seconds since the Epoch pointed to by
@@ -308,7 +312,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
308312
&mut self,
309313
req_op: &OpTy<'tcx>,
310314
_rem: &OpTy<'tcx>, // Signal handlers are not supported, so rem will never be written to.
311-
) -> InterpResult<'tcx, i32> {
315+
) -> InterpResult<'tcx, Scalar> {
312316
let this = self.eval_context_mut();
313317

314318
this.assert_target_os_is_unix("nanosleep");
@@ -320,7 +324,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
320324
None => {
321325
let einval = this.eval_libc("EINVAL");
322326
this.set_last_error(einval)?;
323-
return Ok(-1);
327+
return Ok(Scalar::from_i32(-1));
324328
}
325329
};
326330

@@ -333,7 +337,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
333337
@timeout = |_this| { Ok(()) }
334338
),
335339
);
336-
Ok(0)
340+
Ok(Scalar::from_i32(0))
337341
}
338342

339343
#[allow(non_snake_case)]

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

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
148148
Ok(var_ptr.unwrap_or_else(Pointer::null))
149149
}
150150

151-
fn setenv(&mut self, name_op: &OpTy<'tcx>, value_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
151+
fn setenv(
152+
&mut self,
153+
name_op: &OpTy<'tcx>,
154+
value_op: &OpTy<'tcx>,
155+
) -> InterpResult<'tcx, Scalar> {
152156
let this = self.eval_context_mut();
153157
this.assert_target_os_is_unix("setenv");
154158

@@ -169,16 +173,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
169173
this.deallocate_ptr(var, None, MiriMemoryKind::Runtime.into())?;
170174
}
171175
this.update_environ()?;
172-
Ok(0) // return zero on success
176+
Ok(Scalar::from_i32(0)) // return zero on success
173177
} else {
174178
// name argument is a null pointer, points to an empty string, or points to a string containing an '=' character.
175179
let einval = this.eval_libc("EINVAL");
176180
this.set_last_error(einval)?;
177-
Ok(-1)
181+
Ok(Scalar::from_i32(-1))
178182
}
179183
}
180184

181-
fn unsetenv(&mut self, name_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
185+
fn unsetenv(&mut self, name_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
182186
let this = self.eval_context_mut();
183187
this.assert_target_os_is_unix("unsetenv");
184188

@@ -195,12 +199,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
195199
this.deallocate_ptr(var, None, MiriMemoryKind::Runtime.into())?;
196200
}
197201
this.update_environ()?;
198-
Ok(0)
202+
Ok(Scalar::from_i32(0))
199203
} else {
200204
// name argument is a null pointer, points to an empty string, or points to a string containing an '=' character.
201205
let einval = this.eval_libc("EINVAL");
202206
this.set_last_error(einval)?;
203-
Ok(-1)
207+
Ok(Scalar::from_i32(-1))
204208
}
205209
}
206210

@@ -232,7 +236,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
232236
Ok(Pointer::null())
233237
}
234238

235-
fn chdir(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, i32> {
239+
fn chdir(&mut self, path_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> {
236240
let this = self.eval_context_mut();
237241
this.assert_target_os_is_unix("chdir");
238242

@@ -242,16 +246,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
242246
this.reject_in_isolation("`chdir`", reject_with)?;
243247
this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?;
244248

245-
return Ok(-1);
249+
return Ok(Scalar::from_i32(-1));
246250
}
247251

248-
match env::set_current_dir(path) {
249-
Ok(()) => Ok(0),
250-
Err(e) => {
251-
this.set_last_error_from_io_error(e)?;
252-
Ok(-1)
253-
}
254-
}
252+
let result = env::set_current_dir(path).map(|()| 0);
253+
Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?))
255254
}
256255

257256
/// Updates the `environ` static.
@@ -270,18 +269,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
270269
Ok(())
271270
}
272271

273-
fn getpid(&mut self) -> InterpResult<'tcx, i32> {
272+
fn getpid(&mut self) -> InterpResult<'tcx, Scalar> {
274273
let this = self.eval_context_mut();
275274
this.assert_target_os_is_unix("getpid");
276275

277276
// The reason we need to do this wacky of a conversion is because
278277
// `libc::getpid` returns an i32, however, `std::process::id()` return an u32.
279278
// So we un-do the conversion that stdlib does and turn it back into an i32.
280-
#[allow(clippy::cast_possible_wrap)]
281-
Ok(this.get_pid() as i32)
279+
// In `Scalar` representation, these are the same, so we don't need to anything else.
280+
Ok(Scalar::from_u32(this.get_pid()))
282281
}
283282

284-
fn linux_gettid(&mut self) -> InterpResult<'tcx, i32> {
283+
fn linux_gettid(&mut self) -> InterpResult<'tcx, Scalar> {
285284
let this = self.eval_context_ref();
286285
this.assert_target_os("linux", "gettid");
287286

@@ -290,7 +289,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
290289
// Compute a TID for this thread, ensuring that the main thread has PID == TID.
291290
let tid = this.get_pid().strict_add(index);
292291

293-
#[allow(clippy::cast_possible_wrap)]
294-
Ok(tid as i32)
292+
Ok(Scalar::from_u32(tid))
295293
}
296294
}

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

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -310,20 +310,20 @@ impl FdTable {
310310

311311
impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {}
312312
pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
313-
fn dup(&mut self, old_fd: i32) -> InterpResult<'tcx, i32> {
313+
fn dup(&mut self, old_fd: i32) -> InterpResult<'tcx, Scalar> {
314314
let this = self.eval_context_mut();
315315

316316
let Some(dup_fd) = this.machine.fds.dup(old_fd) else {
317-
return this.fd_not_found();
317+
return Ok(Scalar::from_i32(this.fd_not_found()?));
318318
};
319-
Ok(this.machine.fds.insert_fd_with_min_fd(dup_fd, 0))
319+
Ok(Scalar::from_i32(this.machine.fds.insert_fd_with_min_fd(dup_fd, 0)))
320320
}
321321

322-
fn dup2(&mut self, old_fd: i32, new_fd: i32) -> InterpResult<'tcx, i32> {
322+
fn dup2(&mut self, old_fd: i32, new_fd: i32) -> InterpResult<'tcx, Scalar> {
323323
let this = self.eval_context_mut();
324324

325325
let Some(dup_fd) = this.machine.fds.dup(old_fd) else {
326-
return this.fd_not_found();
326+
return Ok(Scalar::from_i32(this.fd_not_found()?));
327327
};
328328
if new_fd != old_fd {
329329
// Close new_fd if it is previously opened.
@@ -333,7 +333,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
333333
file_description.close(this.machine.communicate())?.ok();
334334
}
335335
}
336-
Ok(new_fd)
336+
Ok(Scalar::from_i32(new_fd))
337337
}
338338

339339
fn flock(&mut self, fd: i32, op: i32) -> InterpResult<'tcx, Scalar> {
@@ -370,7 +370,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
370370
Ok(Scalar::from_i32(this.try_unwrap_io_result(result)?))
371371
}
372372

373-
fn fcntl(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, i32> {
373+
fn fcntl(&mut self, args: &[OpTy<'tcx>]) -> InterpResult<'tcx, Scalar> {
374374
let this = self.eval_context_mut();
375375

376376
if args.len() < 2 {
@@ -388,11 +388,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
388388
// `FD_CLOEXEC` value without checking if the flag is set for the file because `std`
389389
// always sets this flag when opening a file. However we still need to check that the
390390
// file itself is open.
391-
if this.machine.fds.is_fd(fd) {
392-
Ok(this.eval_libc_i32("FD_CLOEXEC"))
391+
Ok(Scalar::from_i32(if this.machine.fds.is_fd(fd) {
392+
this.eval_libc_i32("FD_CLOEXEC")
393393
} else {
394-
this.fd_not_found()
395-
}
394+
this.fd_not_found()?
395+
}))
396396
} else if cmd == this.eval_libc_i32("F_DUPFD")
397397
|| cmd == this.eval_libc_i32("F_DUPFD_CLOEXEC")
398398
{
@@ -409,15 +409,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
409409
let start = this.read_scalar(&args[2])?.to_i32()?;
410410

411411
match this.machine.fds.dup(fd) {
412-
Some(dup_fd) => Ok(this.machine.fds.insert_fd_with_min_fd(dup_fd, start)),
413-
None => this.fd_not_found(),
412+
Some(dup_fd) =>
413+
Ok(Scalar::from_i32(this.machine.fds.insert_fd_with_min_fd(dup_fd, start))),
414+
None => Ok(Scalar::from_i32(this.fd_not_found()?)),
414415
}
415416
} else if this.tcx.sess.target.os == "macos" && cmd == this.eval_libc_i32("F_FULLFSYNC") {
416417
// Reject if isolation is enabled.
417418
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
418419
this.reject_in_isolation("`fcntl`", reject_with)?;
419420
this.set_last_error_from_io_error(ErrorKind::PermissionDenied.into())?;
420-
return Ok(-1);
421+
return Ok(Scalar::from_i32(-1));
421422
}
422423

423424
this.ffullsync_fd(fd)
@@ -462,7 +463,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
462463
buf: Pointer,
463464
count: u64,
464465
offset: Option<i128>,
465-
) -> InterpResult<'tcx, i64> {
466+
) -> InterpResult<'tcx, Scalar> {
466467
let this = self.eval_context_mut();
467468

468469
// Isolation check is done via `FileDescriptor` trait.
@@ -482,7 +483,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
482483
// We temporarily dup the FD to be able to retain mutable access to `this`.
483484
let Some(fd) = this.machine.fds.dup(fd) else {
484485
trace!("read: FD not found");
485-
return this.fd_not_found();
486+
return Ok(Scalar::from_target_isize(this.fd_not_found()?, this));
486487
};
487488

488489
trace!("read: FD mapped to {fd:?}");
@@ -496,7 +497,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
496497
let Ok(offset) = u64::try_from(offset) else {
497498
let einval = this.eval_libc("EINVAL");
498499
this.set_last_error(einval)?;
499-
return Ok(-1);
500+
return Ok(Scalar::from_target_isize(-1, this));
500501
};
501502
fd.borrow_mut().pread(communicate, &mut bytes, offset, this)
502503
}
@@ -513,11 +514,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
513514
buf,
514515
bytes[..usize::try_from(read_bytes).unwrap()].iter().copied(),
515516
)?;
516-
Ok(read_bytes)
517+
Ok(Scalar::from_target_isize(read_bytes, this))
517518
}
518519
Err(e) => {
519520
this.set_last_error_from_io_error(e)?;
520-
Ok(-1)
521+
Ok(Scalar::from_target_isize(-1, this))
521522
}
522523
}
523524
}
@@ -528,7 +529,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
528529
buf: Pointer,
529530
count: u64,
530531
offset: Option<i128>,
531-
) -> InterpResult<'tcx, i64> {
532+
) -> InterpResult<'tcx, Scalar> {
532533
let this = self.eval_context_mut();
533534

534535
// Isolation check is done via `FileDescriptor` trait.
@@ -546,7 +547,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
546547
let bytes = this.read_bytes_ptr_strip_provenance(buf, Size::from_bytes(count))?.to_owned();
547548
// We temporarily dup the FD to be able to retain mutable access to `this`.
548549
let Some(fd) = this.machine.fds.dup(fd) else {
549-
return this.fd_not_found();
550+
return Ok(Scalar::from_target_isize(this.fd_not_found()?, this));
550551
};
551552

552553
let result = match offset {
@@ -555,15 +556,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
555556
let Ok(offset) = u64::try_from(offset) else {
556557
let einval = this.eval_libc("EINVAL");
557558
this.set_last_error(einval)?;
558-
return Ok(-1);
559+
return Ok(Scalar::from_target_isize(-1, this));
559560
};
560561
fd.borrow_mut().pwrite(communicate, &bytes, offset, this)
561562
}
562563
};
563564
drop(fd);
564565

565566
let result = result?.map(|c| i64::try_from(c).unwrap());
566-
this.try_unwrap_io_result(result)
567+
Ok(Scalar::from_target_isize(this.try_unwrap_io_result(result)?, this))
567568
}
568569
}
569570

0 commit comments

Comments
 (0)