Skip to content

Commit 2d8cb4d

Browse files
address review
1 parent 64be5bb commit 2d8cb4d

File tree

3 files changed

+47
-38
lines changed

3 files changed

+47
-38
lines changed

src/shims/unix/foreign_items.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -487,8 +487,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
487487
this.write_null(dest)?;
488488
}
489489

490-
// only macos doesn't support `posix_fallocate`
491-
"posix_fallocate" if &*this.tcx.sess.target.os != "macos" => {
490+
"posix_fallocate" => {
491+
// posix_fallocate is not supported by macos.
492+
this.check_target_os(
493+
&["linux", "freebsd", "solaris", "illumos", "android"],
494+
link_name,
495+
)?;
492496
let [fd, offset, len] = this.check_shim_sig(
493497
shim_sig!(extern "C" fn(i32, libc::off_t, libc::off_t) -> i32),
494498
link_name,
@@ -504,8 +508,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
504508
this.write_scalar(result, dest)?;
505509
}
506510

507-
// only macos doesn't support `posix_fallocate`
508-
"posix_fallocate64" if &*this.tcx.sess.target.os != "macos" => {
511+
"posix_fallocate64" => {
512+
// posix_fallocate is not supported by macos.
513+
this.check_target_os(
514+
&["linux", "freebsd", "solaris", "illumos", "android"],
515+
link_name,
516+
)?;
509517
let [fd, offset, len] = this.check_shim_sig(
510518
shim_sig!(extern "C" fn(i32, libc::off64_t, libc::off64_t) -> i32),
511519
link_name,

src/shims/unix/fs.rs

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,6 +1197,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
11971197
}
11981198
}
11991199

1200+
/// NOTE: According to the man page of `possix_fallocate`, it returns the error code instead
1201+
/// of setting `errno`.
12001202
fn posix_fallocate(
12011203
&mut self,
12021204
fd_num: i32,
@@ -1205,54 +1207,56 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
12051207
) -> InterpResult<'tcx, Scalar> {
12061208
let this = self.eval_context_mut();
12071209

1208-
// According to the man page of `possix_fallocate`, it returns the error code instead
1209-
// of setting `errno`.
1210-
let ebadf = Scalar::from_i32(this.eval_libc_i32("EBADF"));
1211-
let einval = Scalar::from_i32(this.eval_libc_i32("EINVAL"));
1212-
let enodev = Scalar::from_i32(this.eval_libc_i32("ENODEV"));
1213-
12141210
// Reject if isolation is enabled.
12151211
if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
12161212
this.reject_in_isolation("`posix_fallocate`", reject_with)?;
1217-
// Set error code as "EBADF" (bad fd)
1218-
return interp_ok(ebadf);
1213+
// Return error code "EBADF" (bad fd).
1214+
return interp_ok(this.eval_libc("EBADF"));
12191215
}
12201216

12211217
let Some(fd) = this.machine.fds.get(fd_num) else {
1222-
return interp_ok(ebadf);
1218+
return interp_ok(this.eval_libc("EBADF"));
12231219
};
12241220

12251221
let file = match fd.downcast::<FileHandle>() {
12261222
Some(file_handle) => file_handle,
12271223
// Man page specifies to return ENODEV if `fd` is not a regular file.
1228-
None => return interp_ok(enodev),
1224+
None => return interp_ok(this.eval_libc("ENODEV")),
12291225
};
12301226

12311227
// EINVAL is returned when: "offset was less than 0, or len was less than or equal to 0".
12321228
if offset < 0 || len <= 0 {
1233-
return interp_ok(einval);
1229+
return interp_ok(this.eval_libc("EINVAL"));
12341230
}
12351231

1236-
if file.writable {
1237-
let current_size = match file.file.metadata() {
1238-
Ok(metadata) => metadata.len(),
1239-
Err(err) => return this.io_error_to_errnum(err),
1240-
};
1241-
let new_size = match offset.checked_add(len) {
1242-
Some(size) => size.try_into().unwrap(), // We just checked negative `offset` and `len`.
1243-
None => return interp_ok(einval),
1232+
if !file.writable {
1233+
// The file is not writable.
1234+
return interp_ok(this.eval_libc("EBADF"));
1235+
}
1236+
1237+
let current_size = match file.file.metadata() {
1238+
Ok(metadata) => metadata.len(),
1239+
Err(err) => return this.io_error_to_errnum(err),
1240+
};
1241+
let new_size = match offset.checked_add(len) {
1242+
// u64::from(i128) can fail if:
1243+
// - the value is negative, but we checed this above with `offset < 0 || len <= 0`
1244+
// - the value is too big/small to fit in u64, this should not happen since the callers
1245+
// check if the value is a `i32` or `i64`.
1246+
// So this unwrap is safe to do.
1247+
Some(size) => u64::try_from(size).unwrap(),
1248+
None => return interp_ok(this.eval_libc("EFBIG")), // Size to big
1249+
};
1250+
// `posix_fallocate` only specifies increasing the file size.
1251+
if current_size < new_size {
1252+
let result = match file.file.set_len(new_size) {
1253+
Ok(()) => Scalar::from_i32(0),
1254+
Err(e) => this.io_error_to_errnum(e)?,
12441255
};
1245-
// `posix_fallocate` only specifies increasing the file size.
1246-
if current_size < new_size {
1247-
let result = file.file.set_len(new_size);
1248-
let result = this.try_unwrap_io_result(result.map(|_| 0i32))?;
1249-
interp_ok(Scalar::from_i32(result))
1250-
} else {
1251-
interp_ok(Scalar::from_i32(0))
1252-
}
1256+
1257+
interp_ok(result)
12531258
} else {
1254-
// The file is not writable.
1255-
interp_ok(ebadf)
1259+
interp_ok(Scalar::from_i32(0))
12561260
}
12571261
}
12581262

tests/pass-dep/libc/libc-fs.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,7 @@ fn main() {
3636
test_posix_realpath_errors();
3737
#[cfg(target_os = "linux")]
3838
test_posix_fadvise();
39-
#[cfg(target_os = "linux")]
4039
test_posix_fallocate::<libc::off_t>(libc::posix_fallocate);
41-
#[cfg(target_os = "linux")]
4240
test_posix_fallocate::<libc::off64_t>(libc::posix_fallocate64);
4341
#[cfg(target_os = "linux")]
4442
test_sync_file_range();
@@ -339,7 +337,6 @@ fn test_posix_fadvise() {
339337
assert_eq!(result, 0);
340338
}
341339

342-
#[cfg(target_os = "linux")]
343340
fn test_posix_fallocate<T: From<i32>>(
344341
posix_fallocate: unsafe extern "C" fn(fd: libc::c_int, offset: T, len: T) -> libc::c_int,
345342
) {
@@ -351,7 +348,7 @@ fn test_posix_fallocate<T: From<i32>>(
351348
let ret = unsafe { posix_fallocate(42, T::from(0), T::from(10)) };
352349
assert_eq!(ret, libc::EBADF);
353350

354-
let path = utils::prepare("miri_test_libc_possix_fallocate_errors.txt");
351+
let path = utils::prepare("miri_test_libc_posix_fallocate_errors.txt");
355352
let file = File::create(&path).unwrap();
356353

357354
// invalid offset
@@ -371,7 +368,7 @@ fn test_posix_fallocate<T: From<i32>>(
371368

372369
let test = || {
373370
let bytes = b"hello";
374-
let path = utils::prepare("miri_test_libc_fs_ftruncate.txt");
371+
let path = utils::prepare("miri_test_libc_posix_fallocate.txt");
375372
let mut file = File::create(&path).unwrap();
376373
file.write_all(bytes).unwrap();
377374
file.sync_all().unwrap();

0 commit comments

Comments
 (0)