summaryrefslogtreecommitdiffstats
path: root/chrome/browser/safe_browsing/pe_image_reader_win_unittest.cc
blob: 63e6826dfe681d95f3fe70736c4f85c7dede65cb (plain)
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(&section_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]));