Skip to content

Commit 749e9d4

Browse files
address review
1 parent 41dcec7 commit 749e9d4

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
@@ -488,8 +488,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
488488
this.write_null(dest)?;
489489
}
490490

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

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

src/shims/unix/fs.rs

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,6 +1202,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
12021202
}
12031203
}
12041204

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

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

12261222
let Some(fd) = this.machine.fds.get(fd_num) else {
1227-
return interp_ok(ebadf);
1223+
return interp_ok(this.eval_libc("EBADF"));
12281224
};
12291225

12301226
let file = match fd.downcast::<FileHandle>() {
12311227
Some(file_handle) => file_handle,
12321228
// Man page specifies to return ENODEV if `fd` is not a regular file.
1233-
None => return interp_ok(enodev),
1229+
None => return interp_ok(this.eval_libc("ENODEV")),
12341230
};
12351231

12361232
// EINVAL is returned when: "offset was less than 0, or len was less than or equal to 0".
12371233
if offset < 0 || len <= 0 {
1238-
return interp_ok(einval);
1234+
return interp_ok(this.eval_libc("EINVAL"));
12391235
}
12401236

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

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)