1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/files/file_path.h"
#include "base/files/memory_mapped_file.h"
#include "base/path_service.h"
#include "chrome/browser/safe_browsing/pe_image_reader_win.h"
#include "chrome/common/chrome_paths.h"
#include "testing/gtest/include/gtest/gtest.h"
struct TestData {
const char* filename;
safe_browsing::PeImageReader::WordSize word_size;
WORD machine_identifier;
WORD optional_header_size;
size_t number_of_sections;
size_t number_of_debug_entries;
};
// A test fixture parameterized on test data containing the name of a PE image
// to parse and the expected values to be read from it. The file is read from
// the src/chrome/test/data/safe_browsing directory.
class PeImageReaderTest : public testing::TestWithParam<const TestData*> {
protected:
PeImageReaderTest() : expected_data_(GetParam()) {}
virtual void SetUp() override {
ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_file_path_));
data_file_path_ = data_file_path_.AppendASCII("safe_browsing");
data_file_path_ = data_file_path_.AppendASCII(expected_data_->filename);
ASSERT_TRUE(data_file_.Initialize(data_file_path_));
ASSERT_TRUE(image_reader_.Initialize(data_file_.data(),
data_file_.length()));
}
const TestData* expected_data_;
base::FilePath data_file_path_;
base::MemoryMappedFile data_file_;
safe_browsing::PeImageReader image_reader_;
};
TEST_P(PeImageReaderTest, GetWordSize) {
EXPECT_EQ(expected_data_->word_size, image_reader_.GetWordSize());
}
TEST_P(PeImageReaderTest, GetDosHeader) {
const IMAGE_DOS_HEADER* dos_header = image_reader_.GetDosHeader();
ASSERT_NE(reinterpret_cast<const IMAGE_DOS_HEADER*>(NULL), dos_header);
EXPECT_EQ(IMAGE_DOS_SIGNATURE, dos_header->e_magic);
}
TEST_P(PeImageReaderTest, GetCoffFileHeader) {
const IMAGE_FILE_HEADER* file_header = image_reader_.GetCoffFileHeader();
ASSERT_NE(reinterpret_cast<const IMAGE_FILE_HEADER*>(NULL), file_header);
EXPECT_EQ(expected_data_->machine_identifier, file_header->Machine);
EXPECT_EQ(expected_data_->optional_header_size,
file_header->SizeOfOptionalHeader);
}
TEST_P(PeImageReaderTest, GetOptionalHeaderData) {
size_t optional_header_size = 0;
const uint8_t* optional_header_data =
image_reader_.GetOptionalHeaderData(&optional_header_size);
ASSERT_NE(reinterpret_cast<const uint8_t*>(NULL), optional_header_data);
EXPECT_EQ(expected_data_->optional_header_size, optional_header_size);
}
TEST_P(PeImageReaderTest, GetNumberOfSections) {
EXPECT_EQ(expected_data_->number_of_sections,
image_reader_.GetNumberOfSections());
}
TEST_P(PeImageReaderTest, GetSectionHeaderAt) {
size_t number_of_sections = image_reader_.GetNumberOfSections();
for (size_t i = 0; i < number_of_sections; ++i) {
const IMAGE_SECTION_HEADER* section_header =
image_reader_.GetSectionHeaderAt(i);
ASSERT_NE(reinterpret_cast<const IMAGE_SECTION_HEADER*>(NULL),
section_header);
}
}
TEST_P(PeImageReaderTest, InitializeFailTruncatedFile) {
// Compute the size of all headers through the section headers.
const IMAGE_SECTION_HEADER* last_section_header =
image_reader_.GetSectionHeaderAt(image_reader_.GetNumberOfSections() - 1);
const uint8_t* headers_end =
reinterpret_cast<const uint8_t*>(last_section_header) +
sizeof(*last_section_header);
size_t header_size = headers_end - data_file_.data();
safe_browsing::PeImageReader short_reader;
// Initialize should succeed when all headers are present.
EXPECT_TRUE(short_reader.Initialize(data_file_.data(), header_size));
// But fail if anything is missing.
for (size_t i = 0; i < header_size; ++i) {
EXPECT_FALSE(short_reader.Initialize(data_file_.data(), i));
}
}
TEST_P(PeImageReaderTest, GetExportSection) {
size_t section_size = 0;
const uint8_t* export_section = image_reader_.GetExportSection(§ion_size);
ASSERT_NE(reinterpret_cast<const uint8_t*>(NULL), export_section);
EXPECT_NE(0U, section_size);
}
TEST_P(PeImageReaderTest, GetNumberOfDebugEntries) {
EXPECT_EQ(expected_data_->number_of_debug_entries,
image_reader_.GetNumberOfDebugEntries());
}
TEST_P(PeImageReaderTest, GetDebugEntry) {
size_t number_of_debug_entries = image_reader_.GetNumberOfDebugEntries();
for (size_t i = 0; i < number_of_debug_entries; ++i) {
const uint8_t* raw_data = NULL;
size_t raw_data_size = 0;
const IMAGE_DEBUG_DIRECTORY* entry =
image_reader_.GetDebugEntry(i, &raw_data, &raw_data_size);
EXPECT_NE(reinterpret_cast<const IMAGE_DEBUG_DIRECTORY*>(NULL), entry);
EXPECT_NE(reinterpret_cast<const uint8_t*>(NULL), raw_data);
EXPECT_NE(0U, raw_data_size);
}
}
namespace {
const TestData kTestData[] = {
{
"module_with_exports_x86.dll",
safe_browsing::PeImageReader::WORD_SIZE_32,
IMAGE_FILE_MACHINE_I386,
sizeof(IMAGE_OPTIONAL_HEADER32),
4,
1,
}, {
"module_with_exports_x64.dll",
safe_browsing::PeImageReader::WORD_SIZE_64,
IMAGE_FILE_MACHINE_AMD64,
sizeof(IMAGE_OPTIONAL_HEADER64),
5,
1,
},
};
} // namespace
INSTANTIATE_TEST_CASE_P(WordSize32,
PeImageReaderTest,
testing::Values(&kTestData[0]));
INSTANTIATE_TEST_CASE_P(WordSize64,
PeImageReaderTest,
testing::Values(&kTestData[1]));
|