From: Rick Payne <[email protected]>
Committer: Nadav Har'El <[email protected]>
Branch: master
sendfile: don't try to send beyond the end of file
Ensure that sendfile doesn't try to send beyond the end of the source
file. Added some tests, and ensured that the same result is observed under
both Linux and OSv.
Fixes #815
Signed-off-by: Rick Payne <[email protected]>
Message-Id: <[email protected]>
---
diff --git a/fs/vfs/main.cc b/fs/vfs/main.cc
--- a/fs/vfs/main.cc
+++ b/fs/vfs/main.cc
@@ -2039,6 +2039,21 @@ int sendfile(int out_fd, int in_fd, off_t *_offset,
size_t count)
offset = lseek(in_fd, 0, SEEK_CUR);
}
+ // Constrain count to the extent of the file...
+ struct stat st;
+ if (fstat(in_fd, &st) < 0) {
+ return -1;
+ } else {
+ if (offset >= st.st_size) {
+ return 0;
+ } else if ((offset + count) >= st.st_size) {
+ count = st.st_size - offset;
+ if (count == 0) {
+ return 0;
+ }
+ }
+ }
+
size_t bytes_to_mmap = count + (offset % mmu::page_size);
off_t offset_for_mmap = align_down(offset, (off_t)mmu::page_size);
diff --git a/tests/tst-sendfile.cc b/tests/tst-sendfile.cc
--- a/tests/tst-sendfile.cc
+++ b/tests/tst-sendfile.cc
@@ -163,6 +163,22 @@ int test_sendfile_on_socket(off_t *offset, size_t
count)
return listener_result == 0 ? ret : -1;
}
+int test_extents(int testfile_readfd, size_t offset, size_t count)
+{
+ const char *out_file = "testdata_sendfile_output";
+ off_t off;
+ int write_fd = open(out_file, O_RDWR | O_TRUNC | O_CREAT, S_IRWXU);
+ if (write_fd == -1) {
+ printf("\topen() failed with error message
= %s\n",strerror(errno));
+ return -1;
+ }
+ lseek(testfile_readfd, 0 , SEEK_CUR);
+ off = offset;
+ int ret = sendfile(write_fd, testfile_readfd, &off, count);
+ close(write_fd);
+ return ret;
+}
+
int main()
{
int ret;
@@ -200,12 +216,22 @@ int main()
report(test_functions[i](offset_p[j], count_array[k]) ==
count_array[k], message.c_str());
}
offset = 0;
- report(lseek(testfile_readfd, 0, SEEK_SET) == 0, "set readfd to
beginning of file");
+ report(lseek(testfile_readfd, 0, SEEK_SET) == 0, "set readfd
to beginning of file");
report(test_functions[i](offset_p[j], size_test_file) ==
size_test_file, "copy entire file");
printf("\n\n");
}
}
+ // Test extents...
+ report(lseek(testfile_readfd, 0, SEEK_SET) == 0, "set readfd to
beginning of file");
+ report(test_extents(testfile_readfd, 0, size_test_file + 1) ==
size_test_file, "file size extent");
+ report(lseek(testfile_readfd, 0, SEEK_SET) == 0, "set readfd to
beginning of file");
+ report(test_extents(testfile_readfd, 10, size_test_file) ==
(size_test_file - 10), "file size extent with offset");
+ report(lseek(testfile_readfd, 0, SEEK_SET) == 0, "set readfd to
beginning of file");
+ report(test_extents(testfile_readfd, size_test_file - 1, 1) ==
1, "file size extent with offset (tail)");
+ report(lseek(testfile_readfd, 0, SEEK_SET) == 0, "set readfd to
beginning of file");
+ report(test_extents(testfile_readfd, size_test_file, 1) == 0, "file
size extent with offset (tail, no bytes)");
+
/* force sendfile to fail in rest of test cases */
ret = sendfile(100, testfile_readfd, NULL, 10);
report(ret == -1 && errno == EBADF, "test for bad out_fd");
--
You received this message because you are subscribed to the Google Groups "OSv
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.