Skip to content

Commit

Permalink
[base] Fix base::CallFtruncate and base::File::SetLength
Browse files Browse the repository at this point in the history
Use ftruncate64 instead of ftruncate on POSIX systems supporting it.

This fixes an unchecked narrowing integer conversion from 64-bit length
to 32-bit off_t on systems where the type off_t has only 32 bits. On
those systems, trying to create a big file (4+GB) by using
File::SetLength resulted in a file of the wrong length due to the
integer overflow.

BUG=chromium:1236860
TEST=base_unittests --gtest_filter="FileTest.Length"

Change-Id: I3e0c4700a03ab0b556bc38e6a93d5188eb5debbc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3070952
Commit-Queue: François Degros <[email protected]>
Auto-Submit: François Degros <[email protected]>
Reviewed-by: Daniel Cheng <[email protected]>
Cr-Commit-Position: refs/heads/main@{#916237}
  • Loading branch information
fdegros authored and Chromium LUCI CQ committed Aug 28, 2021
1 parent 8b20050 commit c591d11
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 0 deletions.
6 changes: 6 additions & 0 deletions base/files/file_posix.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,13 @@ bool IsOpenAppend(PlatformFile file) {
}

int CallFtruncate(PlatformFile file, int64_t length) {
#if defined(OS_BSD) || defined(OS_APPLE) || defined(OS_FUCHSIA)
static_assert(sizeof(off_t) >= sizeof(int64_t),
"off_t is not a 64-bit integer");
return HANDLE_EINTR(ftruncate(file, length));
#else
return HANDLE_EINTR(ftruncate64(file, length));
#endif
}

int CallFutimes(PlatformFile file, const struct timeval times[2]) {
Expand Down
9 changes: 9 additions & 0 deletions base/files/file_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,15 @@ TEST(FileTest, Length) {
for (int i = 0; i < file_size; i++)
EXPECT_EQ(data_to_write[i], data_read[i]);

#if !defined(OS_FUCHSIA) // Fuchsia doesn't seem to support big files.
// Expand the file past the 4 GB limit.
const int64_t kBigFileLength = 5'000'000'000;
EXPECT_TRUE(file.SetLength(kBigFileLength));
EXPECT_EQ(kBigFileLength, file.GetLength());
EXPECT_TRUE(GetFileSize(file_path, &file_size));
EXPECT_EQ(kBigFileLength, file_size);
#endif

// Close the file and reopen with base::File::FLAG_CREATE_ALWAYS, and make
// sure the file is empty (old file was overridden).
file.Close();
Expand Down

0 comments on commit c591d11

Please sign in to comment.