Index: third_party/crashpad/crashpad/util/file/file_io_win.cc |
diff --git a/third_party/crashpad/crashpad/util/file/file_io_win.cc b/third_party/crashpad/crashpad/util/file/file_io_win.cc |
index 5144869ef42e45d04dfd70cfa3cdbeed38f64790..467fc3c8c0b4e0ef7ec7bb236a9c6feeb7a173cc 100644 |
--- a/third_party/crashpad/crashpad/util/file/file_io_win.cc |
+++ b/third_party/crashpad/crashpad/util/file/file_io_win.cc |
@@ -14,9 +14,11 @@ |
#include "util/file/file_io.h" |
+#include <algorithm> |
+#include <limits> |
+ |
#include "base/files/file_path.h" |
#include "base/logging.h" |
-#include "base/numerics/safe_conversions.h" |
#include "base/strings/utf_string_conversions.h" |
namespace { |
@@ -37,6 +39,16 @@ namespace crashpad { |
namespace { |
+// kMaxReadWriteSize needs to be limited to the range of DWORD for the calls to |
+// ::ReadFile() and ::WriteFile(), and also limited to the range of |
+// FileOperationResult to be able to adequately express the number of bytes read |
+// and written in the return values from ReadFile() and NativeWriteFile(). In a |
+// 64-bit build, the former will control, and the limit will be (2^32)-1. In a |
+// 32-bit build, the latter will control, and the limit will be (2^31)-1. |
+constexpr size_t kMaxReadWriteSize = std::min( |
+ static_cast<size_t>(std::numeric_limits<DWORD>::max()), |
+ static_cast<size_t>(std::numeric_limits<FileOperationResult>::max())); |
+ |
FileHandle OpenFileForOutput(DWORD access, |
const base::FilePath& path, |
FileWriteMode mode, |
@@ -70,51 +82,58 @@ FileHandle OpenFileForOutput(DWORD access, |
} // namespace |
-// TODO(scottmg): Handle > DWORD sized writes if necessary. |
+namespace internal { |
+ |
+const char kNativeReadFunctionName[] = "ReadFile"; |
+const char kNativeWriteFunctionName[] = "WriteFile"; |
+ |
+FileOperationResult NativeWriteFile(FileHandle file, |
+ const void* buffer, |
+ size_t size) { |
+ // TODO(scottmg): This might need to handle the limit for pipes across a |
+ // network in the future. |
+ |
+ const DWORD write_size = |
+ static_cast<DWORD>(std::min(size, kMaxReadWriteSize)); |
+ |
+ DWORD bytes_written; |
+ if (!::WriteFile(file, buffer, write_size, &bytes_written, nullptr)) |
+ return -1; |
+ |
+ CHECK_NE(bytes_written, static_cast<DWORD>(-1)); |
+ DCHECK_LE(static_cast<size_t>(bytes_written), write_size); |
+ return bytes_written; |
+} |
+ |
+} // namespace internal |
FileOperationResult ReadFile(FileHandle file, void* buffer, size_t size) { |
DCHECK(!IsSocketHandle(file)); |
- DWORD size_dword = base::checked_cast<DWORD>(size); |
- DWORD total_read = 0; |
- char* buffer_c = reinterpret_cast<char*>(buffer); |
- while (size_dword > 0) { |
+ |
+ const DWORD read_size = static_cast<DWORD>(std::min(size, kMaxReadWriteSize)); |
+ |
+ while (true) { |
DWORD bytes_read; |
- BOOL success = ::ReadFile(file, buffer_c, size_dword, &bytes_read, nullptr); |
+ BOOL success = ::ReadFile(file, buffer, read_size, &bytes_read, nullptr); |
if (!success) { |
if (GetLastError() == ERROR_BROKEN_PIPE) { |
// When reading a pipe and the write handle has been closed, ReadFile |
// fails with ERROR_BROKEN_PIPE, but only once all pending data has been |
- // read. |
- break; |
- } else if (GetLastError() != ERROR_MORE_DATA) { |
- return -1; |
+ // read. Treat this as EOF. |
+ return 0; |
} |
- } else if (bytes_read == 0 && GetFileType(file) != FILE_TYPE_PIPE) { |
+ return -1; |
+ } |
+ |
+ CHECK_NE(bytes_read, static_cast<DWORD>(-1)); |
+ DCHECK_LE(bytes_read, read_size); |
+ if (bytes_read != 0 || GetFileType(file) != FILE_TYPE_PIPE) { |
// Zero bytes read for a file indicates reaching EOF. Zero bytes read from |
// a pipe indicates only that there was a zero byte WriteFile issued on |
// the other end, so continue reading. |
- break; |
+ return bytes_read; |
} |
- |
- buffer_c += bytes_read; |
- size_dword -= bytes_read; |
- total_read += bytes_read; |
} |
- return total_read; |
-} |
- |
-FileOperationResult WriteFile(FileHandle file, |
- const void* buffer, |
- size_t size) { |
- // TODO(scottmg): This might need to handle the limit for pipes across a |
- // network in the future. |
- DWORD size_dword = base::checked_cast<DWORD>(size); |
- DWORD bytes_written; |
- BOOL rv = ::WriteFile(file, buffer, size_dword, &bytes_written, nullptr); |
- if (!rv) |
- return -1; |
- CHECK_EQ(bytes_written, size_dword); |
- return bytes_written; |
} |
FileHandle OpenFileForRead(const base::FilePath& path) { |
@@ -245,4 +264,26 @@ FileOffset LoggingFileSizeByHandle(FileHandle file) { |
return file_size.QuadPart; |
} |
+FileHandle StdioFileHandle(StdioStream stdio_stream) { |
+ DWORD standard_handle; |
+ switch (stdio_stream) { |
+ case StdioStream::kStandardInput: |
+ standard_handle = STD_INPUT_HANDLE; |
+ break; |
+ case StdioStream::kStandardOutput: |
+ standard_handle = STD_OUTPUT_HANDLE; |
+ break; |
+ case StdioStream::kStandardError: |
+ standard_handle = STD_ERROR_HANDLE; |
+ break; |
+ default: |
+ NOTREACHED(); |
+ return INVALID_HANDLE_VALUE; |
+ } |
+ |
+ HANDLE handle = GetStdHandle(standard_handle); |
+ PLOG_IF(ERROR, handle == INVALID_HANDLE_VALUE) << "GetStdHandle"; |
+ return handle; |
+} |
+ |
} // namespace crashpad |