Index: net/ftp/ftp_directory_listing_parser_vms.cc |
diff --git a/net/ftp/ftp_directory_listing_parser_vms.cc b/net/ftp/ftp_directory_listing_parser_vms.cc |
index 4afb6fb4a39ab53aa936a0981530d42ebafe450f..8f1bfe1dd83193f5934df489428c86a15cd2a652 100644 |
--- a/net/ftp/ftp_directory_listing_parser_vms.cc |
+++ b/net/ftp/ftp_directory_listing_parser_vms.cc |
@@ -6,6 +6,7 @@ |
#include <vector> |
+#include "base/numerics/safe_math.h" |
#include "base/strings/string_number_conversions.h" |
#include "base/strings/string_split.h" |
#include "base/strings/string_util.h" |
@@ -55,6 +56,24 @@ bool ParseVmsFilename(const base::string16& raw_filename, |
return true; |
} |
+// VMS's directory listing gives file size in blocks. The exact file size is |
+// unknown both because it is measured in blocks, but also because the block |
+// size is unknown (but assumed to be 512 bytes). |
+bool ApproximateFilesizeFromBlockCount(int64_t num_blocks, int64_t* out_size) { |
+ if (num_blocks < 0) |
+ return false; |
+ |
+ const int kBlockSize = 512; |
+ base::CheckedNumeric<int64_t> num_bytes = num_blocks; |
+ num_bytes *= kBlockSize; |
+ |
+ if (!num_bytes.IsValid()) |
+ return false; // Block count is too large. |
+ |
+ *out_size = num_bytes.ValueOrDie(); |
+ return true; |
+} |
+ |
bool ParseVmsFilesize(const base::string16& input, int64_t* size) { |
if (base::ContainsOnlyChars(input, base::ASCIIToUTF16("*"))) { |
// Response consisting of asterisks means unknown size. |
@@ -62,17 +81,9 @@ bool ParseVmsFilesize(const base::string16& input, int64_t* size) { |
return true; |
} |
- // VMS's directory listing gives us file size in blocks. We assume that |
- // the block size is 512 bytes. It doesn't give accurate file size, but is the |
- // best information we have. |
- const int kBlockSize = 512; |
- |
- if (base::StringToInt64(input, size)) { |
- if (*size < 0) |
- return false; |
- *size *= kBlockSize; |
- return true; |
- } |
+ int64_t num_blocks; |
+ if (base::StringToInt64(input, &num_blocks)) |
+ return ApproximateFilesizeFromBlockCount(num_blocks, size); |
std::vector<base::StringPiece16> parts = |
base::SplitStringPiece(input, base::ASCIIToUTF16("/"), |
@@ -90,8 +101,7 @@ bool ParseVmsFilesize(const base::string16& input, int64_t* size) { |
if (blocks_used < 0 || blocks_allocated < 0) |
return false; |
- *size = blocks_used * kBlockSize; |
- return true; |
+ return ApproximateFilesizeFromBlockCount(blocks_used, size); |
} |
bool LooksLikeVmsFileProtectionListingPart(const base::string16& input) { |