Skip to content

Commit 70f9a82

Browse files
committed
Merge pull request #12426 from 0xzre:write-syscall-tests
PiperOrigin-RevId: 856302480
2 parents e0a2f60 + 4f4666f commit 70f9a82

File tree

3 files changed

+403
-6
lines changed

3 files changed

+403
-6
lines changed

test/syscalls/linux/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2136,6 +2136,7 @@ cc_binary(
21362136
linkstatic = 1,
21372137
malloc = "//test/util:errno_safe_allocator",
21382138
deps = select_gtest() + [
2139+
"//test/util:cleanup",
21392140
"//test/util:temp_path",
21402141
"//test/util:test_main",
21412142
"//test/util:test_util",

test/syscalls/linux/pwrite64.cc

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,12 @@
1616
#include <fcntl.h>
1717
#include <linux/unistd.h>
1818
#include <sys/socket.h>
19+
#include <sys/syscall.h>
1920
#include <sys/types.h>
2021
#include <unistd.h>
2122

2223
#include "gtest/gtest.h"
24+
#include "test/util/cleanup.h"
2325
#include "test/util/temp_path.h"
2426
#include "test/util/test_util.h"
2527

@@ -28,7 +30,6 @@ namespace testing {
2830

2931
namespace {
3032

31-
// TODO(gvisor.dev/issue/2370): This test is currently very rudimentary.
3233
class Pwrite64 : public ::testing::Test {
3334
void SetUp() override {
3435
name_ = NewTempAbsPath();
@@ -87,6 +88,87 @@ TEST_F(Pwrite64, Pwrite64WithOpath) {
8788
SyscallFailsWithErrno(EBADF));
8889
}
8990

91+
// Test that pwrite64 with a nullptr buffer fails with EFAULT.
92+
TEST_F(Pwrite64, NullBuffer) {
93+
FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(name_.c_str(), O_RDWR));
94+
95+
// Use raw syscall to bypass libc's nonnull annotation.
96+
EXPECT_THAT(syscall(SYS_pwrite64, fd.get(), nullptr, 1, 0),
97+
SyscallFailsWithErrno(EFAULT));
98+
}
99+
100+
// Test that pwrite64 with zero length and nullptr buffer succeeds.
101+
TEST_F(Pwrite64, ZeroLengthNullBuffer) {
102+
FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(name_.c_str(), O_RDWR));
103+
EXPECT_THAT(pwrite64(fd.get(), nullptr, 0, 0), SyscallSucceedsWithValue(0));
104+
}
105+
106+
// Test that pwrite64 to a closed fd fails with EBADF.
107+
TEST_F(Pwrite64, ClosedFd) {
108+
FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(name_.c_str(), O_RDWR));
109+
int raw_fd = fd.get();
110+
fd.reset();
111+
112+
char buf[16] = {};
113+
EXPECT_THAT(pwrite64(raw_fd, buf, sizeof(buf), 0),
114+
SyscallFailsWithErrno(EBADF));
115+
}
116+
117+
// Test that pwrite64 to a read-only fd fails with EBADF.
118+
TEST_F(Pwrite64, ReadOnlyFd) {
119+
FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(name_.c_str(), O_RDONLY));
120+
121+
char buf[16] = {};
122+
EXPECT_THAT(pwrite64(fd.get(), buf, sizeof(buf), 0),
123+
SyscallFailsWithErrno(EBADF));
124+
}
125+
126+
// Test that pwrite64 does not change file offset.
127+
TEST_F(Pwrite64, DoesNotChangeOffset) {
128+
FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(name_.c_str(), O_RDWR));
129+
130+
// Set initial offset.
131+
const off_t initial_offset = 50;
132+
ASSERT_THAT(lseek(fd.get(), initial_offset, SEEK_SET),
133+
SyscallSucceedsWithValue(initial_offset));
134+
135+
char buf[16] = "test data";
136+
EXPECT_THAT(pwrite64(fd.get(), buf, sizeof(buf), 100),
137+
SyscallSucceedsWithValue(sizeof(buf)));
138+
139+
// Offset should remain unchanged.
140+
EXPECT_THAT(lseek(fd.get(), 0, SEEK_CUR),
141+
SyscallSucceedsWithValue(initial_offset));
142+
}
143+
144+
// Test that pwrite64 to a pipe fails with ESPIPE.
145+
TEST_F(Pwrite64, Pipe) {
146+
int pipe_fds[2];
147+
ASSERT_THAT(pipe(pipe_fds), SyscallSucceeds());
148+
auto cleanup = Cleanup([&pipe_fds] {
149+
close(pipe_fds[0]);
150+
close(pipe_fds[1]);
151+
});
152+
153+
char buf[16] = {};
154+
EXPECT_THAT(pwrite64(pipe_fds[1], buf, sizeof(buf), 0),
155+
SyscallFailsWithErrno(ESPIPE));
156+
}
157+
158+
// Test that pwrite64 to a socket fails with ESPIPE.
159+
TEST_F(Pwrite64, Socket) {
160+
int sock_fds[2];
161+
ASSERT_THAT(socketpair(AF_UNIX, SOCK_STREAM, 0, sock_fds), SyscallSucceeds());
162+
auto cleanup = Cleanup([&sock_fds] {
163+
close(sock_fds[0]);
164+
close(sock_fds[1]);
165+
});
166+
167+
char buf[16] = {};
168+
EXPECT_THAT(pwrite64(sock_fds[0], buf, sizeof(buf), 0),
169+
SyscallFailsWithErrno(ESPIPE));
170+
}
171+
90172
} // namespace
91173

92174
} // namespace testing

0 commit comments

Comments
 (0)