From f0c4689a6dd3036600581c87e6191ede2479556e Mon Sep 17 00:00:00 2001 From: "agl@chromium.org" Date: Fri, 19 Feb 2010 15:38:43 +0000 Subject: Fix the case where the browser livelocks if we cannot open a file. If one tries to upload a file that one doesn't have read access to, the browser livelocks. It tries to read from the file, gets nothing but spins forever because it knows that it hasn't finished reading. To address this, firstly we add a check at stat() time to make sure that we can read the file. However, this doesn't take care of the case where the access() call was incorrect, or the permissions have changed under us. In this case, we replace the missing file with NULs. http://codereview.chromium.org/541022 BUG=30850 TEST=Try to upload a file that isn't readable (i.e. /etc/shadow). The resulting upload should be a 0 byte file. git-svn-id: svn://svn.chromium.org/chrome/trunk/src@39446 0039d316-1c4b-4281-b951-d872f2087c98 --- base/platform_file.h | 37 +++++++++++++++++++++++++++++++++++++ base/platform_file_posix.cc | 8 ++++++++ base/platform_file_win.cc | 8 ++++++++ 3 files changed, 53 insertions(+) (limited to 'base') diff --git a/base/platform_file.h b/base/platform_file.h index 0dbf4e4..4ab1ace 100644 --- a/base/platform_file.h +++ b/base/platform_file.h @@ -12,6 +12,8 @@ #include +#include "base/ref_counted.h" + class FilePath; namespace base { @@ -53,6 +55,41 @@ PlatformFile CreatePlatformFile(const std::wstring& name, // Closes a file handle bool ClosePlatformFile(PlatformFile file); +// Get the length of an underlying file. Returns false on error. Otherwise +// *size is set to the length of the file, in bytes. +bool GetPlatformFileSize(PlatformFile file, uint64* size); + +// This is a reference counted PlatformFile. When the ref count drops to zero, +// the file handle is closed. See the comments in base/ref_counted.h for +// details on how to use it. +class RefCountedPlatformFile : + public base::RefCountedThreadSafe { + public: + RefCountedPlatformFile(PlatformFile f) : file_(f) { } + + ~RefCountedPlatformFile() { + if (file_ != kInvalidPlatformFileValue) { + ClosePlatformFile(file_); + file_ = kInvalidPlatformFileValue; + } + } + + PlatformFile get() const { + return file_; + } + + PlatformFile release() { + PlatformFile f = file_; + file_ = kInvalidPlatformFileValue; + return f; + } + + private: + PlatformFile file_; + + DISALLOW_COPY_AND_ASSIGN(RefCountedPlatformFile); +}; + } // namespace base #endif // BASE_PLATFORM_FILE_H_ diff --git a/base/platform_file_posix.cc b/base/platform_file_posix.cc index 46039b9..bfd40e9 100644 --- a/base/platform_file_posix.cc +++ b/base/platform_file_posix.cc @@ -77,4 +77,12 @@ bool ClosePlatformFile(PlatformFile file) { return close(file); } +bool GetPlatformFileSize(PlatformFile file, uint64* out_size) { + struct stat st; + if (fstat(file, &st)) + return false; + *out_size = st.st_size; + return true; +} + } // namespace base diff --git a/base/platform_file_win.cc b/base/platform_file_win.cc index 1143487..ccaee1e 100644 --- a/base/platform_file_win.cc +++ b/base/platform_file_win.cc @@ -75,4 +75,12 @@ bool ClosePlatformFile(PlatformFile file) { return (CloseHandle(file) == 0); } +bool GetPlatformFileSize(PlatformFile file, uint64* out_size) { + LARGE_INTEGER size; + if (!GetFileSizeEx(file, &size)) + return false; + *out_size = size.QuadPart; + return true; +} + } // namespace disk_cache -- cgit v1.1