Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(339)

Unified Diff: chrome/utility/safe_browsing/mac/udif.cc

Issue 2926473002: Mac Archive Type Sniffing (Closed)
Patch Set: adding tester for download protection service Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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;
}

Powered by Google App Engine
This is Rietveld 408576698