Repository: google/gvisor
File: test/syscalls/linux/pwrite64.cc (C++)

Code before:
              SyscallFailsWithErrno(EBADF));
}

// Test that pwrite64 with a nullptr buffer fails with EFAULT.
TEST_F(Pwrite64, NullBuffer) {
  int fd;
  ASSERT_THAT(fd = open(name_.c_str(), O_RDWR), SyscallSucceeds());
  EXPECT_THAT(pwrite64(fd, nullptr, 1, 0), SyscallFailsWithErrno(EFAULT));
  EXPECT_THAT(close(fd), SyscallSucceeds());
}

// Test that pwrite64 with zero length and nullptr buffer succeeds.
TEST_F(Pwrite64, ZeroLengthNullBuffer) {
  int fd;
  ASSERT_THAT(fd = open(name_.c_str(), O_RDWR), SyscallSucceeds());
  EXPECT_THAT(pwrite64(fd, nullptr, 0, 0), SyscallSucceedsWithValue(0));
  EXPECT_THAT(close(fd), SyscallSucceeds());
}

// Test that pwrite64 to a closed fd fails with EBADF.
TEST_F(Pwrite64, ClosedFd) {
  int fd;
  ASSERT_THAT(fd = open(name_.c_str(), O_RDWR), SyscallSucceeds());
  ASSERT_THAT(close(fd), SyscallSucceeds());

  char buf[16];
  EXPECT_THAT(pwrite64(fd, buf, sizeof(buf), 0), SyscallFailsWithErrno(EBADF));
}

// Test that pwrite64 to a read-only fd fails with EBADF.
TEST_F(Pwrite64, ReadOnlyFd) {
  int fd;
  ASSERT_THAT(fd = open(name_.c_str(), O_RDONLY), SyscallSucceeds());

  char buf[16];
  EXPECT_THAT(pwrite64(fd, buf, sizeof(buf), 0), SyscallFailsWithErrno(EBADF));
  EXPECT_THAT(close(fd), SyscallSucceeds());
}

// Test that pwrite64 does not change file offset.
TEST_F(Pwrite64, DoesNotChangeOffset) {
  int fd;
  ASSERT_THAT(fd = open(name_.c_str(), O_RDWR), SyscallSucceeds());

  // Set initial offset.
  const off_t initial_offset = 50;
  ASSERT_THAT(lseek(fd, initial_offset, SEEK_SET),
              SyscallSucceedsWithValue(initial_offset));

  char buf[16] = "test data";
  EXPECT_THAT(pwrite64(fd, buf, sizeof(buf), 100),

Review comment (bug):
There are a lot of uninitialized buffers in this PR; passing uninitialized memory to a function that reads it (like write()) is undefined behavior in C++ and will flag errors in MemorySanitizer (MSan) runs. Use `char buf[16] = {};` instead.

Code after:
  std::vector<char> buf(1);
  EXPECT_THAT(PwriteFd(fd.get(), buf.data(), 1, 0),
              SyscallFailsWithErrno(EBADF));
}

// Test that pwrite64 with a nullptr buffer fails with EFAULT.
TEST_F(Pwrite64, NullBuffer) {
  FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(name_.c_str(), O_RDWR));

  // Use raw syscall to bypass libc's nonnull annotation.
  EXPECT_THAT(syscall(SYS_pwrite64, fd.get(), nullptr, 1, 0),
              SyscallFailsWithErrno(EFAULT));
}

// Test that pwrite64 with zero length and nullptr buffer succeeds.
TEST_F(Pwrite64, ZeroLengthNullBuffer) {
  FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(name_.c_str(), O_RDWR));
  EXPECT_THAT(pwrite64(fd.get(), nullptr, 0, 0), SyscallSucceedsWithValue(0));
}

// Test that pwrite64 to a closed fd fails with EBADF.
TEST_F(Pwrite64, ClosedFd) {
  FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(name_.c_str(), O_RDWR));
  int raw_fd = fd.get();
  fd.reset();

  char buf[16] = {};
  EXPECT_THAT(pwrite64(raw_fd, buf, sizeof(buf), 0),
              SyscallFailsWithErrno(EBADF));
}

// Test that pwrite64 to a read-only fd fails with EBADF.
TEST_F(Pwrite64, ReadOnlyFd) {
  FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(name_.c_str(), O_RDONLY));

  char buf[16] = {};
  EXPECT_THAT(pwrite64(fd.get(), buf, sizeof(buf), 0),
              SyscallFailsWithErrno(EBADF));
}

// Test that pwrite64 does not change file offset.
TEST_F(Pwrite64, DoesNotChangeOffset) {
  FileDescriptor fd = ASSERT_NO_ERRNO_AND_VALUE(Open(name_.c_str(), O_RDWR));

  // Set initial offset.
  const off_t initial_offset = 50;
  ASSERT_THAT(lseek(fd.get(), initial_offset, SEEK_SET),
              SyscallSucceedsWithValue(initial_offset));

  char buf[16] = "test data";
  EXPECT_THAT(pwrite64(fd.get(), buf, sizeof(buf), 100),