1//! Tests for extreme `u64` file offsets. 2//! 3//! POSIX-ish interfaces tend to use signed integers for file offsets, while 4//! Rust APIs tend to use `u64`. Test that extreme `u64` values in APIs that 5//! take file offsets are properly diagnosed. 6//! 7//! These tests are disabled on ios/macos since those platforms kill the 8//! process with `SIGXFSZ` instead of returning an error. 9 10#![cfg(not(any(target_os = "redox", target_os = "wasi")))] 11 12use rustix::io::SeekFrom; 13 14#[test] 15fn invalid_offset_seek() { 16 use rustix::fs::{cwd, openat, seek, Mode, OFlags}; 17 let tmp = tempfile::tempdir().unwrap(); 18 let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap(); 19 let file = openat( 20 &dir, 21 "foo", 22 OFlags::WRONLY | OFlags::TRUNC | OFlags::CREATE, 23 Mode::RUSR | Mode::WUSR, 24 ) 25 .unwrap(); 26 27 seek(&file, SeekFrom::Start(u64::MAX)).unwrap_err(); 28 seek(&file, SeekFrom::Start(i64::MAX as u64 + 1)).unwrap_err(); 29 seek(&file, SeekFrom::End(-1)).unwrap_err(); 30 seek(&file, SeekFrom::End(i64::MIN)).unwrap_err(); 31 seek(&file, SeekFrom::Current(-1)).unwrap_err(); 32 seek(&file, SeekFrom::Current(i64::MIN)).unwrap_err(); 33} 34 35#[cfg(not(any( 36 target_os = "dragonfly", 37 target_os = "illumos", 38 target_os = "netbsd", 39 target_os = "openbsd", 40 target_os = "redox", 41 target_os = "solaris", 42)))] 43#[test] 44fn invalid_offset_fallocate() { 45 use rustix::fs::{cwd, fallocate, openat, FallocateFlags, Mode, OFlags}; 46 let tmp = tempfile::tempdir().unwrap(); 47 let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap(); 48 let file = openat( 49 &dir, 50 "foo", 51 OFlags::WRONLY | OFlags::TRUNC | OFlags::CREATE, 52 Mode::RUSR | Mode::WUSR, 53 ) 54 .unwrap(); 55 56 fallocate(&file, FallocateFlags::empty(), u64::MAX, 1).unwrap_err(); 57 fallocate(&file, FallocateFlags::empty(), i64::MAX as u64 + 1, 1).unwrap_err(); 58 fallocate(&file, FallocateFlags::empty(), 0, u64::MAX).unwrap_err(); 59 fallocate(&file, FallocateFlags::empty(), 0, i64::MAX as u64 + 1).unwrap_err(); 60} 61 62#[cfg(not(any( 63 target_os = "dragonfly", 64 target_os = "haiku", 65 target_os = "illumos", 66 target_os = "ios", 67 target_os = "macos", 68 target_os = "netbsd", 69 target_os = "openbsd", 70 target_os = "redox", 71 target_os = "solaris", 72)))] 73#[test] 74fn invalid_offset_fadvise() { 75 use rustix::fs::{cwd, fadvise, openat, Advice, Mode, OFlags}; 76 let tmp = tempfile::tempdir().unwrap(); 77 let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap(); 78 let file = openat( 79 &dir, 80 "foo", 81 OFlags::WRONLY | OFlags::TRUNC | OFlags::CREATE, 82 Mode::RUSR | Mode::WUSR, 83 ) 84 .unwrap(); 85 86 // `fadvise` never fails on invalid offsets. 87 fadvise(&file, i64::MAX as u64, i64::MAX as u64, Advice::Normal).unwrap(); 88 fadvise(&file, u64::MAX, 0, Advice::Normal).unwrap(); 89 fadvise(&file, i64::MAX as u64, 1, Advice::Normal).unwrap(); 90 fadvise(&file, 1, i64::MAX as u64, Advice::Normal).unwrap(); 91 fadvise(&file, i64::MAX as u64 + 1, 0, Advice::Normal).unwrap(); 92 fadvise(&file, u64::MAX, i64::MAX as u64, Advice::Normal).unwrap(); 93 94 // `fadvise` fails on invalid lengths. 95 fadvise(&file, u64::MAX, u64::MAX, Advice::Normal).unwrap_err(); 96 fadvise(&file, i64::MAX as u64, u64::MAX, Advice::Normal).unwrap_err(); 97 fadvise(&file, 0, u64::MAX, Advice::Normal).unwrap_err(); 98 fadvise(&file, u64::MAX, i64::MAX as u64 + 1, Advice::Normal).unwrap_err(); 99 fadvise(&file, i64::MAX as u64 + 1, u64::MAX, Advice::Normal).unwrap_err(); 100 fadvise(&file, i64::MAX as u64, i64::MAX as u64 + 1, Advice::Normal).unwrap_err(); 101 fadvise(&file, 0, i64::MAX as u64 + 1, Advice::Normal).unwrap_err(); 102} 103 104#[test] 105fn invalid_offset_pread() { 106 use rustix::fs::{cwd, openat, Mode, OFlags}; 107 use rustix::io::pread; 108 let tmp = tempfile::tempdir().unwrap(); 109 let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap(); 110 let file = openat( 111 &dir, 112 "foo", 113 OFlags::RDWR | OFlags::TRUNC | OFlags::CREATE, 114 Mode::RUSR | Mode::WUSR, 115 ) 116 .unwrap(); 117 118 let mut buf = [0_u8; 1]; 119 pread(&file, &mut buf, u64::MAX).unwrap_err(); 120 pread(&file, &mut buf, i64::MAX as u64 + 1).unwrap_err(); 121} 122 123#[cfg(not(any(target_os = "ios", target_os = "macos")))] 124#[test] 125fn invalid_offset_pwrite() { 126 use rustix::fs::{cwd, openat, Mode, OFlags}; 127 use rustix::io::pwrite; 128 let tmp = tempfile::tempdir().unwrap(); 129 let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap(); 130 let file = openat( 131 &dir, 132 "foo", 133 OFlags::WRONLY | OFlags::TRUNC | OFlags::CREATE, 134 Mode::RUSR | Mode::WUSR, 135 ) 136 .unwrap(); 137 138 let buf = [0_u8; 1]; 139 pwrite(&file, &buf, u64::MAX).unwrap_err(); 140 pwrite(&file, &buf, i64::MAX as u64 + 1).unwrap_err(); 141} 142 143#[cfg(any(target_os = "android", target_os = "linux"))] 144#[test] 145fn invalid_offset_copy_file_range() { 146 use rustix::fs::{copy_file_range, cwd, openat, Mode, OFlags}; 147 use rustix::io::write; 148 let tmp = tempfile::tempdir().unwrap(); 149 let dir = openat(cwd(), tmp.path(), OFlags::RDONLY, Mode::empty()).unwrap(); 150 let foo = openat( 151 &dir, 152 "foo", 153 OFlags::RDWR | OFlags::TRUNC | OFlags::CREATE, 154 Mode::RUSR | Mode::WUSR, 155 ) 156 .unwrap(); 157 let bar = openat( 158 &dir, 159 "bar", 160 OFlags::WRONLY | OFlags::TRUNC | OFlags::CREATE, 161 Mode::RUSR | Mode::WUSR, 162 ) 163 .unwrap(); 164 write(&foo, b"a").unwrap(); 165 166 let mut off_in = u64::MAX; 167 let mut off_out = 0; 168 copy_file_range(&foo, Some(&mut off_in), &bar, Some(&mut off_out), 1).unwrap_err(); 169 170 let mut off_in = i64::MAX as u64 + 1; 171 let mut off_out = 0; 172 copy_file_range(&foo, Some(&mut off_in), &bar, Some(&mut off_out), 1).unwrap_err(); 173 174 let mut off_in = 0; 175 let mut off_out = u64::MAX; 176 copy_file_range(&foo, Some(&mut off_in), &bar, Some(&mut off_out), 1).unwrap_err(); 177 178 let mut off_in = 0; 179 let mut off_out = i64::MAX as u64; 180 copy_file_range(&foo, Some(&mut off_in), &bar, Some(&mut off_out), 1).unwrap_err(); 181 182 let mut off_in = 0; 183 let mut off_out = i64::MAX as u64 + 1; 184 copy_file_range(&foo, Some(&mut off_in), &bar, Some(&mut off_out), 1).unwrap_err(); 185} 186