Chromium Code Reviews| Index: chrome/utility/safe_browsing/mac/udif.cc |
| diff --git a/chrome/utility/safe_browsing/mac/udif.cc b/chrome/utility/safe_browsing/mac/udif.cc |
| index 0c4be3fa310747ef84226969a5ea536f630e8b6c..16ba4d35192591382da25446ca42adf67ca39139 100644 |
| --- a/chrome/utility/safe_browsing/mac/udif.cc |
| +++ b/chrome/utility/safe_browsing/mac/udif.cc |
| @@ -28,17 +28,6 @@ namespace dmg { |
| #pragma pack(push, 1) |
|
vakh (use Gerrit instead)
2017/06/12 16:20:28
Do we still need this preprocessor directive here?
mortonm
2017/06/12 16:35:54
Yes -- I've moved the struct definition back into
|
| -// The following structures come from the analysis provided by Jonathan Levin |
| -// at <http://newosxbook.com/DMG.html>. |
| -// |
| -// Note that all fields are stored in big endian. |
| - |
| -struct UDIFChecksum { |
| - uint32_t type; |
| - uint32_t size; |
| - uint32_t data[32]; |
| -}; |
| - |
| static void ConvertBigEndian(UDIFChecksum* checksum) { |
| ConvertBigEndian(&checksum->type); |
| ConvertBigEndian(&checksum->size); |
| @@ -47,46 +36,6 @@ static void ConvertBigEndian(UDIFChecksum* checksum) { |
| } |
| } |
| -// The trailer structure for a UDIF file. |
| -struct UDIFResourceFile { |
| - static const uint32_t kSignature = 'koly'; |
| - static const uint32_t kVersion = 4; |
| - |
| - uint32_t signature; |
| - uint32_t version; |
| - uint32_t header_size; // Size of this structure. |
| - uint32_t flags; |
| - uint64_t running_data_fork_offset; |
| - uint64_t data_fork_offset; |
| - uint64_t data_fork_length; |
| - uint64_t rsrc_fork_offset; |
| - uint64_t rsrc_fork_length; |
| - uint32_t segment_number; |
| - uint32_t segment_count; |
| - uuid_t segment_id; |
| - |
| - UDIFChecksum data_checksum; |
| - |
| - uint64_t plist_offset; // Offset and length of the blkx plist. |
| - uint64_t plist_length; |
| - |
| - uint8_t reserved1[64]; |
| - |
| - uint64_t code_signature_offset; |
| - uint64_t code_signature_length; |
| - |
| - uint8_t reserved2[40]; |
| - |
| - UDIFChecksum master_checksum; |
| - |
| - uint32_t image_variant; |
| - uint64_t sector_count; |
| - |
| - uint32_t reserved3; |
| - uint32_t reserved4; |
| - uint32_t reserved5; |
| -}; |
| - |
| static void ConvertBigEndian(uuid_t* uuid) { |
| // UUID is never consulted, so do not swap. |
| } |
| @@ -348,13 +297,52 @@ UDIFParser::UDIFParser(ReadStream* stream) |
| : stream_(stream), |
| partition_names_(), |
| blocks_(), |
| - block_size_(kSectorSize) { |
| -} |
| + block_size_(kSectorSize), |
| + trailer_successfully_parsed_(false) {} |
| UDIFParser::~UDIFParser() {} |
| +bool UDIFParser::ParseTrailer() { |
| + // Makes sure that trailer is only ever parsed single time during execution of |
| + // constuctor, so position of ReadStream is not moved after constructor runs. |
| + if (trailer_successfully_parsed_) |
| + return true; |
| + |
| + off_t trailer_start = stream_->Seek(-sizeof(trailer_), SEEK_END); |
| + if (trailer_start == -1) |
| + return false; |
| + |
| + if (!stream_->ReadType(&trailer_)) { |
| + DLOG(ERROR) << "Failed to read UDIFResourceFile"; |
| + return false; |
| + } |
| + ConvertBigEndian(&trailer_); |
| + |
| + if (trailer_.signature != trailer_.kSignature) { |
| + DLOG(ERROR) << "blkx signature does not match, is 0x" << std::hex |
| + << trailer_.signature; |
| + return false; |
| + } |
| + if (trailer_.version != trailer_.kVersion) { |
| + DLOG(ERROR) << "blkx version does not match, is " << trailer_.version; |
| + return false; |
| + } |
| + |
| + auto plist_end = base::CheckedNumeric<size_t>(trailer_.plist_offset) + |
| + trailer_.plist_length; |
| + if (!plist_end.IsValid() || |
| + plist_end.ValueOrDie() > base::checked_cast<size_t>(trailer_start)) { |
| + DLOG(ERROR) << "blkx plist extends past UDIF trailer"; |
| + return false; |
| + } |
| + |
| + return true; |
| +} |
| + |
| bool UDIFParser::Parse() { |
| - if (!ParseBlkx()) |
| + // First parses trailer and then parses blocks. |
| + trailer_successfully_parsed_ = ParseTrailer(); |
| + if (!trailer_successfully_parsed_ || !ParseBlkx()) |
|
vakh (use Gerrit instead)
2017/06/12 16:20:28
shortcut this as: return trailer_successfully_pars
mortonm
2017/06/12 16:35:54
Done.
|
| return false; |
| return true; |
| @@ -407,41 +395,15 @@ std::unique_ptr<ReadStream> UDIFParser::GetPartitionReadStream( |
| } |
| bool UDIFParser::ParseBlkx() { |
| - UDIFResourceFile trailer; |
| - off_t trailer_start = stream_->Seek(-sizeof(trailer), SEEK_END); |
| - if (trailer_start == -1) |
| + if (!trailer_successfully_parsed_) |
| return false; |
| - if (!stream_->ReadType(&trailer)) { |
| - DLOG(ERROR) << "Failed to read UDIFResourceFile"; |
| - return false; |
| - } |
| - ConvertBigEndian(&trailer); |
| - |
| - if (trailer.signature != trailer.kSignature) { |
| - DLOG(ERROR) << "blkx signature does not match, is 0x" |
| - << std::hex << trailer.signature; |
| - return false; |
| - } |
| - if (trailer.version != trailer.kVersion) { |
| - DLOG(ERROR) << "blkx version does not match, is " << trailer.version; |
| - return false; |
| - } |
| - |
| - auto plist_end = base::CheckedNumeric<size_t>(trailer.plist_offset) + |
| - trailer.plist_length; |
| - if (!plist_end.IsValid() || |
| - plist_end.ValueOrDie() > base::checked_cast<size_t>(trailer_start)) { |
| - DLOG(ERROR) << "blkx plist extends past UDIF trailer"; |
| - return false; |
| - } |
| - |
| - std::vector<uint8_t> plist_bytes(trailer.plist_length, 0); |
| + std::vector<uint8_t> plist_bytes(trailer_.plist_length, 0); |
| - if (stream_->Seek(trailer.plist_offset, SEEK_SET) == -1) |
| + if (stream_->Seek(trailer_.plist_offset, SEEK_SET) == -1) |
| return false; |
| - if (!stream_->ReadExact(&plist_bytes[0], trailer.plist_length)) { |
| + if (!stream_->ReadExact(&plist_bytes[0], trailer_.plist_length)) { |
| DLOG(ERROR) << "Failed to read blkx plist data"; |
| return false; |
| } |