michael@0: // All rights reserved. michael@0: // michael@0: // Redistribution and use in source and binary forms, with or without michael@0: // modification, are permitted provided that the following conditions are michael@0: // met: michael@0: // michael@0: // * Redistributions of source code must retain the above copyright michael@0: // notice, this list of conditions and the following disclaimer. michael@0: // * Redistributions in binary form must reproduce the above michael@0: // copyright notice, this list of conditions and the following disclaimer michael@0: // in the documentation and/or other materials provided with the michael@0: // distribution. michael@0: // * Neither the name of Google Inc. nor the names of its michael@0: // contributors may be used to endorse or promote products derived from michael@0: // this software without specific prior written permission. michael@0: // michael@0: // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS michael@0: // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT michael@0: // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR michael@0: // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT michael@0: // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, michael@0: // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT michael@0: // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, michael@0: // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY michael@0: // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT michael@0: // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE michael@0: // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE// michael@0: // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS michael@0: // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT michael@0: // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR michael@0: // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT michael@0: // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, michael@0: // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT michael@0: // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, michael@0: // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY michael@0: // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT michael@0: // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE michael@0: // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. michael@0: michael@0: #include michael@0: #include michael@0: michael@0: #include michael@0: michael@0: #include "breakpad_googletest_includes.h" michael@0: #include "common/using_std_string.h" michael@0: #include "google_breakpad/processor/basic_source_line_resolver.h" michael@0: #include "google_breakpad/processor/call_stack.h" michael@0: #include "google_breakpad/processor/code_module.h" michael@0: #include "google_breakpad/processor/code_modules.h" michael@0: #include "google_breakpad/processor/minidump.h" michael@0: #include "google_breakpad/processor/minidump_processor.h" michael@0: #include "google_breakpad/processor/process_state.h" michael@0: #include "google_breakpad/processor/stack_frame.h" michael@0: #include "google_breakpad/processor/symbol_supplier.h" michael@0: michael@0: namespace google_breakpad { michael@0: class MockMinidump : public Minidump { michael@0: public: michael@0: MockMinidump() : Minidump("") { michael@0: } michael@0: michael@0: MOCK_METHOD0(Read, bool()); michael@0: MOCK_CONST_METHOD0(path, string()); michael@0: MOCK_CONST_METHOD0(header, const MDRawHeader*()); michael@0: MOCK_METHOD0(GetThreadList, MinidumpThreadList*()); michael@0: }; michael@0: } michael@0: michael@0: namespace { michael@0: michael@0: using google_breakpad::BasicSourceLineResolver; michael@0: using google_breakpad::CallStack; michael@0: using google_breakpad::CodeModule; michael@0: using google_breakpad::MinidumpProcessor; michael@0: using google_breakpad::MinidumpThreadList; michael@0: using google_breakpad::MinidumpThread; michael@0: using google_breakpad::MockMinidump; michael@0: using google_breakpad::ProcessState; michael@0: using google_breakpad::SymbolSupplier; michael@0: using google_breakpad::SystemInfo; michael@0: michael@0: class TestSymbolSupplier : public SymbolSupplier { michael@0: public: michael@0: TestSymbolSupplier() : interrupt_(false) {} michael@0: michael@0: virtual SymbolResult GetSymbolFile(const CodeModule *module, michael@0: const SystemInfo *system_info, michael@0: string *symbol_file); michael@0: michael@0: virtual SymbolResult GetSymbolFile(const CodeModule *module, michael@0: const SystemInfo *system_info, michael@0: string *symbol_file, michael@0: string *symbol_data); michael@0: michael@0: virtual SymbolResult GetCStringSymbolData(const CodeModule *module, michael@0: const SystemInfo *system_info, michael@0: string *symbol_file, michael@0: char **symbol_data); michael@0: michael@0: virtual void FreeSymbolData(const CodeModule *module) { } michael@0: // When set to true, causes the SymbolSupplier to return INTERRUPT michael@0: void set_interrupt(bool interrupt) { interrupt_ = interrupt; } michael@0: michael@0: private: michael@0: bool interrupt_; michael@0: }; michael@0: michael@0: SymbolSupplier::SymbolResult TestSymbolSupplier::GetSymbolFile( michael@0: const CodeModule *module, michael@0: const SystemInfo *system_info, michael@0: string *symbol_file) { michael@0: michael@0: if (interrupt_) { michael@0: return INTERRUPT; michael@0: } michael@0: michael@0: return NOT_FOUND; michael@0: } michael@0: michael@0: SymbolSupplier::SymbolResult TestSymbolSupplier::GetCStringSymbolData( michael@0: const CodeModule *module, michael@0: const SystemInfo *system_info, michael@0: string *symbol_file, michael@0: char **symbol_data) { michael@0: return GetSymbolFile(module, system_info, symbol_file); michael@0: } michael@0: michael@0: SymbolSupplier::SymbolResult TestSymbolSupplier::GetSymbolFile( michael@0: const CodeModule *module, michael@0: const SystemInfo *system_info, michael@0: string *symbol_file, michael@0: string *symbol_data) { michael@0: return GetSymbolFile(module, system_info, symbol_file); michael@0: } michael@0: michael@0: TEST(ExploitabilityTest, TestWindowsEngine) { michael@0: TestSymbolSupplier supplier; michael@0: BasicSourceLineResolver resolver; michael@0: MinidumpProcessor processor(&supplier, &resolver, true); michael@0: ProcessState state; michael@0: michael@0: string minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") + michael@0: "/src/processor/testdata/ascii_read_av.dmp"; michael@0: ASSERT_EQ(processor.Process(minidump_file, &state), michael@0: google_breakpad::PROCESS_OK); michael@0: ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, michael@0: state.exploitability()); michael@0: michael@0: minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") + michael@0: "/src/processor/testdata/ascii_read_av_block_write.dmp"; michael@0: ASSERT_EQ(processor.Process(minidump_file, &state), michael@0: google_breakpad::PROCESS_OK); michael@0: ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, michael@0: state.exploitability()); michael@0: michael@0: minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") + michael@0: "/src/processor/testdata/ascii_read_av_clobber_write.dmp"; michael@0: ASSERT_EQ(processor.Process(minidump_file, &state), michael@0: google_breakpad::PROCESS_OK); michael@0: ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, michael@0: state.exploitability()); michael@0: michael@0: minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") + michael@0: "/src/processor/testdata/ascii_read_av_conditional.dmp"; michael@0: ASSERT_EQ(processor.Process(minidump_file, &state), michael@0: google_breakpad::PROCESS_OK); michael@0: ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, michael@0: state.exploitability()); michael@0: michael@0: minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") + michael@0: "/src/processor/testdata/ascii_read_av_then_jmp.dmp"; michael@0: ASSERT_EQ(processor.Process(minidump_file, &state), michael@0: google_breakpad::PROCESS_OK); michael@0: ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, michael@0: state.exploitability()); michael@0: michael@0: minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") + michael@0: "/src/processor/testdata/ascii_read_av_xchg_write.dmp"; michael@0: ASSERT_EQ(processor.Process(minidump_file, &state), michael@0: google_breakpad::PROCESS_OK); michael@0: ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, michael@0: state.exploitability()); michael@0: michael@0: minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") + michael@0: "/src/processor/testdata/ascii_write_av.dmp"; michael@0: ASSERT_EQ(processor.Process(minidump_file, &state), michael@0: google_breakpad::PROCESS_OK); michael@0: ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, michael@0: state.exploitability()); michael@0: michael@0: minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") + michael@0: "/src/processor/testdata/ascii_write_av_arg_to_call.dmp"; michael@0: ASSERT_EQ(processor.Process(minidump_file, &state), michael@0: google_breakpad::PROCESS_OK); michael@0: ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, michael@0: state.exploitability()); michael@0: michael@0: minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") + michael@0: "/src/processor/testdata/null_read_av.dmp"; michael@0: ASSERT_EQ(processor.Process(minidump_file, &state), michael@0: google_breakpad::PROCESS_OK); michael@0: ASSERT_EQ(google_breakpad::EXPLOITABILITY_NONE, michael@0: state.exploitability()); michael@0: michael@0: minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") + michael@0: "/src/processor/testdata/null_write_av.dmp"; michael@0: ASSERT_EQ(processor.Process(minidump_file, &state), michael@0: google_breakpad::PROCESS_OK); michael@0: ASSERT_EQ(google_breakpad::EXPLOITABILITY_NONE, michael@0: state.exploitability()); michael@0: michael@0: minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") + michael@0: "/src/processor/testdata/stack_exhaustion.dmp"; michael@0: ASSERT_EQ(processor.Process(minidump_file, &state), michael@0: google_breakpad::PROCESS_OK); michael@0: ASSERT_EQ(google_breakpad::EXPLOITABILITY_NONE, michael@0: state.exploitability()); michael@0: michael@0: minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") + michael@0: "/src/processor/testdata/exec_av_on_stack.dmp"; michael@0: ASSERT_EQ(processor.Process(minidump_file, &state), michael@0: google_breakpad::PROCESS_OK); michael@0: ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, michael@0: state.exploitability()); michael@0: michael@0: minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") + michael@0: "/src/processor/testdata/write_av_non_null.dmp"; michael@0: ASSERT_EQ(processor.Process(minidump_file, &state), michael@0: google_breakpad::PROCESS_OK); michael@0: ASSERT_EQ(google_breakpad::EXPLOITABLITY_MEDIUM, michael@0: state.exploitability()); michael@0: michael@0: minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") + michael@0: "/src/processor/testdata/read_av_non_null.dmp"; michael@0: ASSERT_EQ(processor.Process(minidump_file, &state), michael@0: google_breakpad::PROCESS_OK); michael@0: ASSERT_EQ(google_breakpad::EXPLOITABILITY_LOW, michael@0: state.exploitability()); michael@0: michael@0: minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") + michael@0: "/src/processor/testdata/read_av_clobber_write.dmp"; michael@0: ASSERT_EQ(processor.Process(minidump_file, &state), michael@0: google_breakpad::PROCESS_OK); michael@0: ASSERT_EQ(google_breakpad::EXPLOITABILITY_LOW, michael@0: state.exploitability()); michael@0: michael@0: minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") + michael@0: "/src/processor/testdata/read_av_conditional.dmp"; michael@0: ASSERT_EQ(processor.Process(minidump_file, &state), michael@0: google_breakpad::PROCESS_OK); michael@0: ASSERT_EQ(google_breakpad::EXPLOITABILITY_LOW, michael@0: state.exploitability()); michael@0: } michael@0: }