// Copyright (c) 2011 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 #include #include "courgette/base_test_unittest.h" #include "courgette/courgette.h" #include "courgette/courgette_flow.h" #include "courgette/streams.h" namespace courgette { class EncodeDecodeTest : public BaseTest { public: void TestAssembleToStreamDisassemble(const std::string& file, size_t expected_encoded_length) const; }; void EncodeDecodeTest::TestAssembleToStreamDisassemble( const std::string& file, size_t expected_encoded_length) const { const uint8_t* original_data = reinterpret_cast(file.data()); size_t original_length = file.length(); CourgetteFlow flow; // Convert executable to encoded assembly. RegionBuffer original_buffer(Region(original_data, original_length)); flow.ReadDisassemblerFromBuffer(flow.ONLY, original_buffer); EXPECT_EQ(C_OK, flow.status()); EXPECT_TRUE(nullptr != flow.data(flow.ONLY)->disassembler.get()); flow.CreateAssemblyProgramFromDisassembler(flow.ONLY, false); EXPECT_EQ(C_OK, flow.status()); EXPECT_TRUE(nullptr != flow.data(flow.ONLY)->program.get()); flow.CreateEncodedProgramFromDisassemblerAndAssemblyProgram(flow.ONLY); EXPECT_EQ(C_OK, flow.status()); EXPECT_TRUE(nullptr != flow.data(flow.ONLY)->encoded.get()); flow.DestroyAssemblyProgram(flow.ONLY); EXPECT_EQ(C_OK, flow.status()); EXPECT_TRUE(nullptr == flow.data(flow.ONLY)->program.get()); flow.DestroyDisassembler(flow.ONLY); EXPECT_EQ(C_OK, flow.status()); EXPECT_TRUE(nullptr == flow.data(flow.ONLY)->disassembler.get()); flow.WriteSinkStreamSetFromEncodedProgram(flow.ONLY); EXPECT_EQ(C_OK, flow.status()); flow.DestroyEncodedProgram(flow.ONLY); EXPECT_EQ(C_OK, flow.status()); EXPECT_TRUE(nullptr == flow.data(flow.ONLY)->encoded.get()); SinkStream sink; flow.WriteSinkStreamFromSinkStreamSet(flow.ONLY, &sink); EXPECT_EQ(C_OK, flow.status()); const void* encoded_data = sink.Buffer(); size_t encoded_length = sink.Length(); EXPECT_EQ(expected_encoded_length, encoded_length); // Convert encoded assembly back to executable. RegionBuffer encoded_buffer(Region(encoded_data, encoded_length)); flow.ReadSourceStreamSetFromBuffer(flow.ONLY, encoded_buffer); EXPECT_EQ(C_OK, flow.status()); flow.ReadEncodedProgramFromSourceStreamSet(flow.ONLY); EXPECT_EQ(C_OK, flow.status()); EXPECT_TRUE(nullptr != flow.data(flow.ONLY)->encoded.get()); SinkStream executable; flow.WriteExecutableFromEncodedProgram(flow.ONLY, &executable); EXPECT_EQ(C_OK, flow.status()); flow.DestroyEncodedProgram(flow.ONLY); EXPECT_EQ(C_OK, flow.status()); EXPECT_TRUE(nullptr == flow.data(flow.ONLY)->encoded.get()); EXPECT_TRUE(flow.ok()); EXPECT_FALSE(flow.failed()); const void* executable_data = executable.Buffer(); size_t executable_length = executable.Length(); EXPECT_EQ(original_length, executable_length); EXPECT_EQ(0, memcmp(original_data, executable_data, original_length)); } TEST_F(EncodeDecodeTest, PE) { std::string file = FileContents("setup1.exe"); TestAssembleToStreamDisassemble(file, 972845); } TEST_F(EncodeDecodeTest, PE64) { std::string file = FileContents("chrome64_1.exe"); TestAssembleToStreamDisassemble(file, 810090); } TEST_F(EncodeDecodeTest, Elf_Small) { std::string file = FileContents("elf-32-1"); TestAssembleToStreamDisassemble(file, 136201); } TEST_F(EncodeDecodeTest, Elf_HighBSS) { std::string file = FileContents("elf-32-high-bss"); TestAssembleToStreamDisassemble(file, 7308); } } // namespace courgette