| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/utility/safe_browsing/mac/udif.h" | 5 #include "chrome/utility/safe_browsing/mac/udif.h" |
| 6 | 6 |
| 7 #include <CoreFoundation/CoreFoundation.h> | 7 #include <CoreFoundation/CoreFoundation.h> |
| 8 #include <bzlib.h> | 8 #include <bzlib.h> |
| 9 #include <libkern/OSByteOrder.h> | 9 #include <libkern/OSByteOrder.h> |
| 10 #include <uuid/uuid.h> | 10 #include <uuid/uuid.h> |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 ConvertBigEndian(&block->chunk_count); | 183 ConvertBigEndian(&block->chunk_count); |
| 184 // Note: This deliberately does not swap the chunks themselves. | 184 // Note: This deliberately does not swap the chunks themselves. |
| 185 } | 185 } |
| 186 | 186 |
| 187 // UDIFBlock takes a raw, big-endian block data pointer and stores, in host | 187 // UDIFBlock takes a raw, big-endian block data pointer and stores, in host |
| 188 // endian, the data for both the block and the chunk. | 188 // endian, the data for both the block and the chunk. |
| 189 class UDIFBlock { | 189 class UDIFBlock { |
| 190 public: | 190 public: |
| 191 UDIFBlock() : block_() {} | 191 UDIFBlock() : block_() {} |
| 192 | 192 |
| 193 bool ParseBlockData(const UDIFBlockData* block_data, uint16_t sector_size) { | 193 bool ParseBlockData(const UDIFBlockData* block_data, |
| 194 size_t block_data_size, |
| 195 uint16_t sector_size) { |
| 196 if (block_data_size < sizeof(block_)) { |
| 197 DLOG(ERROR) << "UDIF block data is smaller than expected"; |
| 198 return false; |
| 199 } |
| 200 |
| 194 block_ = *block_data; | 201 block_ = *block_data; |
| 195 ConvertBigEndian(&block_); | 202 ConvertBigEndian(&block_); |
| 196 | 203 |
| 197 // Make sure the number of sectors doesn't overflow. | 204 // Make sure the number of sectors doesn't overflow. |
| 198 auto block_size = base::CheckedNumeric<size_t>(sector_count()) * | 205 auto block_size = base::CheckedNumeric<size_t>(sector_count()) * |
| 199 sector_size; | 206 sector_size; |
| 200 if (!block_size.IsValid()) { | 207 if (!block_size.IsValid()) { |
| 201 DLOG(ERROR) << "UDIF block size overflows"; | 208 DLOG(ERROR) << "UDIF block size overflows"; |
| 202 return false; | 209 return false; |
| 203 } | 210 } |
| 204 | 211 |
| 212 // Make sure the block data contains the reported number of chunks. |
| 213 auto block_and_chunks_size = |
| 214 (base::CheckedNumeric<size_t>(sizeof(UDIFBlockChunk)) * |
| 215 block_.chunk_count) + |
| 216 sizeof(block_); |
| 217 if (!block_and_chunks_size.IsValid() || |
| 218 block_data_size < block_and_chunks_size.ValueOrDie()) { |
| 219 DLOG(ERROR) << "UDIF block does not contain reported number of chunks, " |
| 220 << block_and_chunks_size.ValueOrDie() << " bytes expected, " |
| 221 << "got " << block_data_size; |
| 222 return false; |
| 223 } |
| 224 |
| 205 // Make sure that the chunk data isn't larger than the block reports. | 225 // Make sure that the chunk data isn't larger than the block reports. |
| 206 base::CheckedNumeric<size_t> chunk_sectors(0); | 226 base::CheckedNumeric<size_t> chunk_sectors(0); |
| 207 for (uint32_t i = 0; i < block_.chunk_count; ++i) { | 227 for (uint32_t i = 0; i < block_.chunk_count; ++i) { |
| 208 chunks_.push_back(block_data->chunks[i]); | 228 chunks_.push_back(block_data->chunks[i]); |
| 209 UDIFBlockChunk* chunk = &chunks_[i]; | 229 UDIFBlockChunk* chunk = &chunks_[i]; |
| 210 ConvertBigEndian(chunk); | 230 ConvertBigEndian(chunk); |
| 211 | 231 |
| 212 chunk_sectors += chunk->sector_count; | 232 chunk_sectors += chunk->sector_count; |
| 213 if (!chunk_sectors.IsValid() || | 233 if (!chunk_sectors.IsValid() || |
| 214 chunk_sectors.ValueOrDie() > sector_count()) { | 234 chunk_sectors.ValueOrDie() > sector_count()) { |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 479 if (!data) { | 499 if (!data) { |
| 480 DLOG(ERROR) << "Skipping block " << i | 500 DLOG(ERROR) << "Skipping block " << i |
| 481 << " because it has no Data section"; | 501 << " because it has no Data section"; |
| 482 continue; | 502 continue; |
| 483 } | 503 } |
| 484 | 504 |
| 485 // Copy the block table out of the plist. | 505 // Copy the block table out of the plist. |
| 486 std::unique_ptr<UDIFBlock> block(new UDIFBlock()); | 506 std::unique_ptr<UDIFBlock> block(new UDIFBlock()); |
| 487 if (!block->ParseBlockData( | 507 if (!block->ParseBlockData( |
| 488 reinterpret_cast<const UDIFBlockData*>(CFDataGetBytePtr(data)), | 508 reinterpret_cast<const UDIFBlockData*>(CFDataGetBytePtr(data)), |
| 509 base::checked_cast<size_t>(CFDataGetLength(data)), |
| 489 block_size_)) { | 510 block_size_)) { |
| 490 DLOG(ERROR) << "Failed to parse UDIF block data"; | 511 DLOG(ERROR) << "Failed to parse UDIF block data"; |
| 491 return false; | 512 return false; |
| 492 } | 513 } |
| 493 | 514 |
| 494 if (block->signature() != UDIFBlockData::kSignature) { | 515 if (block->signature() != UDIFBlockData::kSignature) { |
| 495 DLOG(ERROR) << "Skipping block " << i << " because its signature does not" | 516 DLOG(ERROR) << "Skipping block " << i << " because its signature does not" |
| 496 << " match, is 0x" << std::hex << block->signature(); | 517 << " match, is 0x" << std::hex << block->signature(); |
| 497 continue; | 518 continue; |
| 498 } | 519 } |
| (...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 836 << chunk_->compressed_offset; | 857 << chunk_->compressed_offset; |
| 837 return false; | 858 return false; |
| 838 } | 859 } |
| 839 return true; | 860 return true; |
| 840 } | 861 } |
| 841 | 862 |
| 842 } // namespace | 863 } // namespace |
| 843 | 864 |
| 844 } // namespace dmg | 865 } // namespace dmg |
| 845 } // namespace safe_browsing | 866 } // namespace safe_browsing |
| OLD | NEW |