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
12 use rustix::io::SeekFrom;
13
14 #[test]
invalid_offset_seek()15 fn 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]
invalid_offset_fallocate()44 fn 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]
invalid_offset_fadvise()74 fn 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]
invalid_offset_pread()105 fn 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]
invalid_offset_pwrite()125 fn 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]
invalid_offset_copy_file_range()145 fn 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