| 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)
|
|
|
| -// 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())
|
| 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;
|
| }
|
|
|