Index: syzygy/experimental/protect/protect_unittest/integrity_check_transform_unittests.cc |
diff --git a/syzygy/experimental/protect/protect_unittest/integrity_check_transform_unittests.cc b/syzygy/experimental/protect/protect_unittest/integrity_check_transform_unittests.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e9b9363e71b1e0d13b71ca31e9dd4886b0798736 |
--- /dev/null |
+++ b/syzygy/experimental/protect/protect_unittest/integrity_check_transform_unittests.cc |
@@ -0,0 +1,1372 @@ |
+// Copyright 2015 Google Inc. All Rights Reserved. |
+// |
+// Licensed under the Apache License, Version 2.0 (the "License"); |
+// you may not use this file except in compliance with the License. |
+// You may obtain a copy of the License at |
+// |
+// http://www.apache.org/licenses/LICENSE-2.0 |
+// |
+// Unless required by applicable law or agreed to in writing, software |
+// distributed under the License is distributed on an "AS IS" BASIS, |
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+// See the License for the specific language governing permissions and |
+// limitations under the License. |
+ |
+#include "syzygy/experimental/protect/protect_lib/integrity_check_transform.h" |
+ |
+#include <sstream> |
+#include <map> |
+ |
+#include "gtest/gtest.h" |
+#include "syzygy/block_graph/basic_block.h" |
+#include "syzygy/block_graph/basic_block_assembler.h" |
+#include "syzygy/block_graph/basic_block_decomposer.h" |
+#include "syzygy/block_graph/basic_block_subgraph.h" |
+#include "syzygy/block_graph/block_graph.h" |
+#include "syzygy/block_graph/block_util.h" |
+#include "syzygy/block_graph/typed_block.h" |
+#include "syzygy/common/indexed_frequency_data.h" |
+#include "syzygy/instrument/transforms/unittest_util.h" |
+ |
+namespace protect { |
+namespace { |
+ |
+//using base::DictionaryValue; |
+//using base::ListValue; |
+//using base::Value; |
+ |
+using block_graph::BasicBlock; |
+using block_graph::BasicBlockDecomposer; |
+using block_graph::BasicBlockSubGraph; |
+using block_graph::BasicCodeBlock; |
+using block_graph::BlockGraph; |
+using block_graph::Instruction; |
+ |
+//typedef AllocationFilterTransform::Offset Offset; |
+//typedef AllocationFilterTransform::OffsetSet OffsetSet; |
+//typedef AllocationFilterTransform::FunctionNameOffsetMap |
+// FunctionNameOffsetMap; |
+ |
+static wchar_t kConfigBadPathDoesNotExist[] = |
+ L"syzygy/instrument/test_data/" |
+ L"allocation-filter-bad-path-does-not-exist.json"; |
+ |
+class TestIntegrityCheckTransform : public IntegrityCheckTransform { |
+ public: |
+ //using IntegrityCheckTransform::pre_call_hook_ref_; |
+ //using AllocationFilterTransform::post_call_hook_ref_; |
+ using IntegrityCheckTransform::target_names_; |
+ using IntegrityCheckTransform::partition_unit_map_; |
+ using IntegrityCheckTransform::label_name_to_block_; |
+ using IntegrityCheckTransform::dll_id_to_block_reference_; |
+ using IntegrityCheckTransform::nr_pc_relative_refs_; |
+ using IntegrityCheckTransform::is_bb_checked_map_; |
+ using IntegrityCheckTransform::ic_block_chunk_index_map_; |
+ using IntegrityCheckTransform::ic_block_reference_free_chunks; |
+ using IntegrityCheckTransform::ic_chunk_checker_to_checkee_map_; |
+ using IntegrityCheckTransform::precomputed_hashes_; |
+ using IntegrityCheckTransform::checker_to_checkee_map_; |
+ using IntegrityCheckTransform::xhash_block_; |
+ using IntegrityCheckTransform::hash_block_; |
+ using IntegrityCheckTransform::response_block_; |
+ using IntegrityCheckTransform::id_to_label_; |
+ using IntegrityCheckTransform::basic_block_sizes_; |
+ using IntegrityCheckTransform::num_chunks_per_block; |
+ using IntegrityCheckTransform::GetHashBlock;//done mohsen |
+ using IntegrityCheckTransform::SetHashBlock;//done mohsen |
+ using IntegrityCheckTransform::CheckHash;//done mohsen |
+ using IntegrityCheckTransform::FixPrecomputedHashes;//done mohsen |
+ using IntegrityCheckTransform::PatchPrecomputedHashes;//mohsen |
+ using IntegrityCheckTransform::PatchBlockReference;//done mohsen |
+ using IntegrityCheckTransform::RecomputeXorChunks;//done mohsen |
+ using IntegrityCheckTransform::RecomputePivot;//done mohsen |
+ using IntegrityCheckTransform::ComputeAggregatedChunksHash;//done mohsen |
+ using IntegrityCheckTransform::ComputeAggregatedBlocksHash;//done mohsen |
+ using IntegrityCheckTransform::PatchPivot;//done mohsen |
+ using IntegrityCheckTransform::PatchBlockReferencesAndSizes;//done mohsen |
+ using IntegrityCheckTransform::AddChunkIntegrityCheckCode;//done mohsen |
+ using IntegrityCheckTransform::AddIntegrityCheckCode;//done mohsen |
+ using IntegrityCheckTransform::ComputeChunks;//done mohsen |
+ using IntegrityCheckTransform::AddChunkIntoIndexMap;//done mohsen |
+ using IntegrityCheckTransform::GenerateChunkCombinations;//mohsen |
+ using IntegrityCheckTransform::GetChunkUniqueKey;//done mohsen |
+ using IntegrityCheckTransform::PrecomputeHash; |
+ using IntegrityCheckTransform::IsIdInPartitionUnitMap; |
+ using IntegrityCheckTransform::GenerateLabelToBlockMap; |
+ using IntegrityCheckTransform::UpdateLabelToBlockMap; |
+ using IntegrityCheckTransform::PopulatePartitionKey; |
+ using IntegrityCheckTransform::AllBasicBlocksChecked; |
+ using IntegrityCheckTransform::IsBogusBlock; |
+ using IntegrityCheckTransform::PopulateCheckMaps; |
+ using IntegrityCheckTransform::RandomlySelectChecker; |
+ using IntegrityCheckTransform::AddReference; |
+ using IntegrityCheckTransform::GetBasicBlockIdByLabel; |
+ using IntegrityCheckTransform::TransformBasicBlockSubGraph; |
+ using IntegrityCheckTransform::ProcessAllBlocks; |
+ using IntegrityCheckTransform::GenerateBasicBlockCombinations; |
+ using IntegrityCheckTransform::ShouldProcessBlock; |
+ using IntegrityCheckTransform::TransformBlockGraph; |
+ |
+ TestIntegrityCheckTransform() |
+ : IntegrityCheckTransform(std::set<std::string>(),1.0f) { |
+ } |
+ |
+ void ResetTransform(); |
+ |
+}; |
+ |
+ |
+ |
+ |
+// Cleans state of the IntegrityCheckTransform |
+void TestIntegrityCheckTransform::ResetTransform() { |
+ this->hash_block_ = NULL; |
+ this->xhash_block_ = NULL; |
+ this->response_block_ = NULL; |
+ this->nr_hashes_patched_ = 0; |
+ this->nr_pc_relative_refs_ = 0; |
+ this->num_chunks_per_block = 0; |
+ this->chunk_checking_coverage = 0; |
+ this->label_name_to_block_.clear(); |
+ this->dll_id_to_block_reference_.clear(); |
+ this->adjust_label_by_offset_.clear(); |
+ this->target_names_.clear(); |
+ this->subgraph_vector_.clear(); |
+ this->checker_to_checkee_map_.clear(); |
+ this->is_bb_checked_map_.clear(); |
+ this->basic_block_has_ref_.clear(); |
+ this->basic_block_sizes_.clear(); |
+ this->precomputed_hashes_.clear(); |
+ this->partition_map_.clear(); |
+ this->partition_unit_map_.clear(); |
+ this->id_to_label_.clear(); |
+ this->ic_block_reference_free_chunks.clear(); |
+ this->ic_block_chunk_index_map_.clear(); |
+ this->ic_chunk_checker_to_checkee_map_.clear(); |
+} |
+ |
+class IntegrityCheckTransformTest : public testing::TestDllTransformTest { |
+ protected: |
+ TestIntegrityCheckTransform tx_; |
+ //static int *x; |
+ static void SetUpTestCase(){ |
+ //x = new int[10]; |
+ } |
+ static void TearDownTestCase(){ |
+ // delete x; |
+ } |
+}; |
+ |
+} // namespace |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckIsIdInParitionUnitMap) { |
+ ASSERT_FALSE(tx_.IsIdInPartitionUnitMap(0)); |
+ ASSERT_FALSE(tx_.IsIdInPartitionUnitMap(125)); |
+ |
+ std::set<uint64> st; |
+ st.insert(125); |
+ std::pair<int, std::set<uint64>> x(0, st); |
+ tx_.partition_unit_map_.insert(x); |
+ |
+ ASSERT_TRUE(tx_.IsIdInPartitionUnitMap(125)); |
+ ASSERT_FALSE(tx_.IsIdInPartitionUnitMap(123)); |
+ |
+ tx_.partition_unit_map_.erase(tx_.partition_unit_map_.find(0)); |
+ ASSERT_FALSE(tx_.IsIdInPartitionUnitMap(125)); |
+ |
+ tx_.ResetTransform(); |
+} |
+ |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckGenerateLabelToBlockMap) { |
+ BlockGraph *bgraph = NULL; |
+ BlockGraph::Block *test_block_a = NULL; |
+ BlockGraph::Block *test_block_b = NULL; |
+ BlockGraph::Block *test_block_c = NULL; |
+ |
+ bgraph = new BlockGraph(); |
+ test_block_a = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "sample a"); |
+ test_block_b = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "sample b"); |
+ test_block_c = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "sample c"); |
+ test_block_a->SetLabel(10, BlockGraph::Label("test a", BlockGraph::CODE_LABEL)); |
+ test_block_b->SetLabel(20, BlockGraph::Label("test b", BlockGraph::CODE_LABEL)); |
+ test_block_c->SetLabel(500, BlockGraph::Label("test c", BlockGraph::CODE_LABEL)); |
+ |
+ tx_.GenerateLabelToBlockMap(bgraph); |
+ // Check for presence and value |
+ auto res = tx_.label_name_to_block_.find("test a"); |
+ ASSERT_TRUE(res != tx_.label_name_to_block_.end()); |
+ ASSERT_TRUE(res->second.first == test_block_a); |
+ res = tx_.label_name_to_block_.find("test b"); |
+ ASSERT_TRUE(res != tx_.label_name_to_block_.end()); |
+ ASSERT_TRUE(res->second.first == test_block_b); |
+ res = tx_.label_name_to_block_.find("test c"); |
+ ASSERT_TRUE(res != tx_.label_name_to_block_.end()); |
+ ASSERT_TRUE(res->second.first == test_block_c); |
+ |
+ res = tx_.label_name_to_block_.find("test d"); |
+ ASSERT_TRUE(res == tx_.label_name_to_block_.end()); |
+ |
+ tx_.ResetTransform(); |
+ delete bgraph; |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckUpdateLabelToBlockMap) { |
+ BlockGraph *bgraph = NULL; |
+ BlockGraph::Block *test_block = NULL; |
+ |
+ bgraph = new BlockGraph(); |
+ test_block = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "sample"); |
+ test_block->SetLabel(10, BlockGraph::Label("test a", BlockGraph::CODE_LABEL)); |
+ test_block->SetLabel(20, BlockGraph::Label("test b", BlockGraph::CODE_LABEL)); |
+ test_block->SetLabel(500, BlockGraph::Label("test c", BlockGraph::CODE_LABEL)); |
+ |
+ tx_.UpdateLabelToBlockMap(test_block); |
+ |
+ // Check for presence and value |
+ auto res = tx_.label_name_to_block_.find("test a"); |
+ ASSERT_TRUE(res != tx_.label_name_to_block_.end()); |
+ ASSERT_TRUE(res->second.first == test_block); |
+ res = tx_.label_name_to_block_.find("test b"); |
+ ASSERT_TRUE(res != tx_.label_name_to_block_.end()); |
+ ASSERT_TRUE(res->second.first == test_block); |
+ res = tx_.label_name_to_block_.find("test c"); |
+ ASSERT_TRUE(res != tx_.label_name_to_block_.end()); |
+ ASSERT_TRUE(res->second.first == test_block); |
+ |
+ res = tx_.label_name_to_block_.find("test d"); |
+ ASSERT_TRUE(res == tx_.label_name_to_block_.end()); |
+ |
+ tx_.ResetTransform(); |
+ delete bgraph; |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckAllBasicBlocksChecked) { |
+ std::set<uint64> test_set; |
+ test_set.insert(0); |
+ |
+ std::map<std::set<uint64>, int> check_order; |
+ check_order.insert(std::pair<std::set<uint64>, int>(test_set, 0)); |
+ |
+ ASSERT_TRUE(tx_.is_bb_checked_map_[0] == 0); |
+ ASSERT_TRUE(tx_.AllBasicBlocksChecked(check_order) == false); |
+ |
+ tx_.is_bb_checked_map_.insert(std::pair<uint64, int > (0, 1)); |
+ ASSERT_FALSE(tx_.AllBasicBlocksChecked(check_order) == true); |
+ |
+ tx_.ResetTransform(); |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckPopulateCheckMaps) { |
+ // TODO: Understand how it works |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckIsBogusBlock) { |
+ BlockGraph *bgraph = new BlockGraph(); |
+ BlockGraph::Block *test_block = NULL; |
+ test_block = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "sample a"); |
+ |
+ ASSERT_FALSE(tx_.IsBogusBlock(test_block)); |
+ |
+ std::set<uint64> test_set; |
+ test_set.insert(test_block->id()); |
+ std::pair<int, std::set<uint64>> x(0, test_set); |
+ tx_.partition_unit_map_.insert(x); |
+ |
+ ASSERT_TRUE(tx_.IsBogusBlock(test_block)); |
+ |
+ tx_.ResetTransform(); |
+ delete bgraph; |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckPatchBlockReference) { |
+ BlockGraph *bgraph = NULL; |
+ BlockGraph::Block *test_block_a = NULL; |
+ BlockGraph::Block *test_block_b = NULL; |
+ BlockGraph::Block *test_block_c = NULL; |
+ |
+ bgraph = new BlockGraph(); |
+ test_block_a = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_a"); |
+ test_block_b = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_b"); |
+ test_block_c = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "code_block"); |
+ |
+ BasicBlockSubGraph* subgraph = new BasicBlockSubGraph(); |
+ subgraph->set_original_block(test_block_c); |
+ BlockGraph::Section* code_section = bgraph->FindOrAddSection(".text", |
+ 0x60000000); |
+ |
+ subgraph->AddBlockDescription("test_subgraph", code_section->name(), |
+ BlockGraph::CODE_BLOCK, |
+ code_section->id(), 1, 0); |
+ |
+ BasicCodeBlock* bb = subgraph->AddBasicCodeBlock("basic_code_block"); |
+ auto inst_iter = bb->instructions().begin(); |
+ block_graph::BasicBlockAssembler assm(inst_iter, |
+ &bb->instructions()); |
+ |
+ int original_offset = 100; |
+ int label_offset = 10; |
+ assm.push(block_graph::Operand(block_graph::Displacement(test_block_a, |
+ original_offset))); |
+ |
+ // Insert the label and update label_name_to_block_ |
+ test_block_b->SetLabel(label_offset, |
+ BlockGraph::Label("Test Label", |
+ BlockGraph::CODE_LABEL)); |
+ auto lab_it(test_block_b->labels().begin()); |
+ tx_.label_name_to_block_[lab_it->second.name()] = |
+ std::make_pair(test_block_b, lab_it->first); |
+ |
+ // Prepare parameters for calling PatchBlockReference |
+ auto label_to_block_it = tx_.label_name_to_block_.find(lab_it->second.name()); |
+ CHECK(label_to_block_it != tx_.label_name_to_block_.end()); |
+ auto reference_free_block = label_to_block_it->second.first; |
+ uint32 new_bb_ref_offset = label_to_block_it->second.second; |
+ int intermediate_offset = 150; |
+ |
+ // Check initial offset and reference |
+ inst_iter = bb->instructions().begin(); |
+ Instruction::BasicBlockReferenceMap &ref_block_map = |
+ inst_iter->references(); |
+ auto instruction_references_it = ref_block_map.begin(); |
+ BlockGraph::Offset reference_offset = |
+ instruction_references_it->first; |
+ block_graph::BasicBlockReference old_bb_ref = |
+ instruction_references_it->second; |
+ ASSERT_TRUE(old_bb_ref.block() == test_block_a); |
+ ASSERT_TRUE(old_bb_ref.offset() == original_offset); |
+ |
+ // Patch the instruction without changing the block |
+ tx_.PatchBlockReference(inst_iter, reference_free_block, |
+ intermediate_offset, false); |
+ |
+ // Check the modifications |
+ instruction_references_it = inst_iter->references().begin(); |
+ reference_offset = instruction_references_it->first; |
+ block_graph::BasicBlockReference new_bb_ref = |
+ instruction_references_it->second; |
+ |
+ ASSERT_TRUE(new_bb_ref.block() == test_block_a); |
+ ASSERT_TRUE(new_bb_ref.offset() == intermediate_offset); |
+ |
+ // Patch the instruction including changing the block |
+ tx_.PatchBlockReference(inst_iter, reference_free_block, |
+ new_bb_ref_offset, true); |
+ |
+ instruction_references_it = inst_iter->references().begin(); |
+ reference_offset = instruction_references_it->first; |
+ new_bb_ref = instruction_references_it->second; |
+ |
+ ASSERT_TRUE(new_bb_ref.block() == test_block_b); |
+ ASSERT_TRUE((uint32)new_bb_ref.offset() == new_bb_ref_offset); |
+ |
+ tx_.ResetTransform(); |
+ delete bgraph; |
+ delete subgraph; |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckCheckHash) { |
+ BlockGraph *bgraph = new BlockGraph(); |
+ BlockGraph::Block *test_block_b = NULL; |
+ test_block_b = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 2000, "sample b"); |
+ base::StringPiece test_block_tag = "1"; |
+ auto test_block_label = block_graph::BlockGraph::Label( |
+ test_block_tag, |
+ BlockGraph::CODE_LABEL); |
+ uint64 test_block_id = 1; |
+ uint32 test_block_size = 1; |
+ // push eax equals to 0x50 |
+ uint8 test_block_value = 0x50; |
+ //prepare id to label map |
+ tx_.id_to_label_[test_block_id] = test_block_label; |
+ //set the size |
+ tx_.basic_block_sizes_[test_block_id] = test_block_size; |
+ |
+ BasicBlockSubGraph* subgraph = new BasicBlockSubGraph(); |
+ subgraph->set_original_block(test_block_b); |
+ BlockGraph::Section* code_section = bgraph->FindOrAddSection(".text", |
+ 0x60000000); |
+ |
+ subgraph->AddBlockDescription("sample c", code_section->name(), |
+ BlockGraph::CODE_BLOCK, |
+ code_section->id(), 1, 0); |
+ |
+ BasicCodeBlock* bb = subgraph->AddBasicCodeBlock("sample b"); |
+ |
+ auto inst_iter = bb->instructions().begin(); |
+ block_graph::BasicBlockAssembler assm(inst_iter, |
+ &bb->instructions()); |
+ |
+ assm.push(assm::eax); |
+ //add label to the block |
+ auto instr = bb->instructions().begin(); |
+ instr->set_label(test_block_label); |
+ |
+ |
+ std::vector<uint8> test_buffer; |
+ test_buffer.insert(test_buffer.begin(), test_block_value); |
+ //offset in the test buffer |
+ bb->set_offset(0); |
+ tx_.CheckHash(bb, test_buffer); |
+ |
+ //we should have a hash computed for this block |
+ ASSERT_TRUE(tx_.precomputed_hashes_[test_block_id] == test_block_value); |
+ |
+ tx_.ResetTransform(); |
+ delete bgraph; |
+ delete subgraph; |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckFixPrecomputedHashes) { |
+ //what the hell to test here! |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckRecomputeXorChunks){ |
+ uint64 test_block_id = 1; |
+ uint8 test_old_size[1] = { 1 }; |
+ uint8 test_new_size[1] = { 2 }; |
+ uint64 test_chunk_bb_id = 1; |
+ uint32 test_chunk_index = 0; |
+ uint32 test_chunk_size = 1; |
+ uint8 test_chunk_hash = 0x50; |
+ //new hash = old hash ^ old_size ^ new_size |
+ uint8 test_chunk_new_hash = 0x53; |
+ |
+ uint64 test_vector_index = 0; |
+ tx_.ic_block_chunk_index_map_[tx_.GetChunkUniqueKey(test_chunk_bb_id, |
+ test_chunk_index)] = |
+ test_vector_index; |
+ |
+ ChunkInfo test_chunk(test_chunk_bb_id,test_chunk_size, |
+ test_chunk_hash, test_chunk_index,0); |
+ tx_.ic_block_reference_free_chunks.insert( |
+ tx_.ic_block_reference_free_chunks.begin(), test_chunk); |
+ |
+ tx_.RecomputeXorChunks(test_block_id, test_old_size, test_new_size, |
+ test_chunk_bb_id, test_chunk_index); |
+ |
+ //we should have a hash computed for this block |
+ auto updated_chunk = tx_.ic_block_reference_free_chunks[test_vector_index]; |
+ |
+ ASSERT_EQ(updated_chunk.hash_,test_chunk_new_hash); |
+ |
+ tx_.ResetTransform(); |
+} |
+TEST_F(IntegrityCheckTransformTest, CheckGetHashBlock) { |
+ ASSERT_TRUE(tx_.GetHashBlock()==NULL); |
+} |
+TEST_F(IntegrityCheckTransformTest, CheckSetHashBlock) { |
+ BlockGraph *bgraph = NULL; |
+ BlockGraph::Block *test_block_a = NULL; |
+ |
+ bgraph = new BlockGraph(); |
+ test_block_a = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_a"); |
+ |
+ tx_.SetHashBlock(test_block_a); |
+ auto ret_block = tx_.GetHashBlock(); |
+ ASSERT_TRUE(ret_block == test_block_a); |
+ tx_.ResetTransform(); |
+ delete bgraph; |
+} |
+ |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckRecomputePivot){ |
+ BlockGraph *bgraph = new BlockGraph(); |
+ BlockGraph::Block *test_block_b = NULL; |
+ test_block_b = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 2000, "sample b"); |
+ uint8 old_hash = 0x1; |
+ // push eax, pivot, sub al, old hash |
+ uint8 test_block_data[5] = { 0x50, 0x0, 0x2c, old_hash }; |
+ |
+ test_block_b->SetData(test_block_data, sizeof(test_block_data)); |
+ |
+ |
+ uint64 test_block_id = 1; |
+ uint8 test_precomputed_hash = 0x7c; |
+ uint8 test_precomputed_xor = 1; |
+ uint32 test_pivot_offset = 1; |
+ uint32 test_sub_offset = 2; |
+ tx_.RecomputePivot(test_block_id, test_precomputed_hash, test_precomputed_xor, |
+ test_pivot_offset, test_sub_offset, test_block_b); |
+ // pivot + new hash = old hash |
+ uint8 hash_diff = test_block_b->data()[test_pivot_offset] + |
+ test_block_b->data()[test_sub_offset + 1]; |
+ bool is_pivot_correct = hash_diff == old_hash; |
+ |
+ ASSERT_TRUE(is_pivot_correct); |
+ delete bgraph; |
+ |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckComputeAggregatedBlocksHash){ |
+ uint64 test_bb_id = 1; |
+ std::map<uint64, int> test_checkee_map; |
+ test_checkee_map[2] = 1; |
+ test_checkee_map[3] = -1; |
+ tx_.checker_to_checkee_map_[test_bb_id] = test_checkee_map; |
+ tx_.precomputed_hashes_[2] = 0x20; |
+ tx_.precomputed_hashes_[3] = 0x10; |
+ uint8 computed_hash = tx_.ComputeAggregatedBlocksHash(test_bb_id); |
+ ASSERT_EQ(0x10, computed_hash); |
+ |
+ tx_.ResetTransform(); |
+} |
+TEST_F(IntegrityCheckTransformTest, CheckComputeAggregatedChunksHash){ |
+ uint8 hash1 = 0x1; |
+ uint8 hash2 = 0x2; |
+ tx_.ic_block_reference_free_chunks.insert( |
+ tx_.ic_block_reference_free_chunks.begin(), ChunkInfo(1, 1, hash1, 0, 0)); |
+ tx_.ic_block_reference_free_chunks.insert( |
+ tx_.ic_block_reference_free_chunks.begin(), ChunkInfo(1, 1, hash2, 0, 0)); |
+ std::set<uint32> test_chunk_index_set; |
+ test_chunk_index_set.insert(0); |
+ test_chunk_index_set.insert(1); |
+ uint8 computed_hash = tx_.ComputeAggregatedChunksHash(test_chunk_index_set); |
+ ASSERT_EQ(0x3, computed_hash); |
+ |
+ tx_.ResetTransform(); |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckPatchPivot){ |
+ BlockGraph *bgraph = new BlockGraph(); |
+ BlockGraph::Block *test_block_b = NULL; |
+ test_block_b = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 2000, "sample b"); |
+ base::StringPiece test_block_tag = "1"; |
+ auto test_block_label = block_graph::BlockGraph::Label( |
+ test_block_tag, |
+ BlockGraph::CODE_LABEL); |
+ uint64 test_block_id = 1; |
+ uint32 test_block_size = 1; |
+ //prepare id to label map |
+ tx_.id_to_label_[test_block_id] = test_block_label; |
+ //set the size |
+ tx_.basic_block_sizes_[test_block_id] = test_block_size; |
+ |
+ BasicBlockSubGraph* subgraph = new BasicBlockSubGraph(); |
+ subgraph->set_original_block(test_block_b); |
+ BlockGraph::Section* code_section = bgraph->FindOrAddSection(".text", |
+ 0x60000000); |
+ |
+ subgraph->AddBlockDescription("sample c", code_section->name(), |
+ BlockGraph::CODE_BLOCK, |
+ code_section->id(), 1, 0); |
+ |
+ BasicCodeBlock* bb = subgraph->AddBasicCodeBlock("sample b"); |
+ |
+ auto inst_iter = bb->instructions().begin(); |
+ block_graph::BasicBlockAssembler assm(inst_iter, |
+ &bb->instructions()); |
+ |
+ uint8 old_hash = 0x1; |
+ |
+ assm.push(assm::eax); |
+ assm.data(0); |
+ assm.sub(assm::al,block_graph::Immediate(old_hash, |
+ assm::ValueSize::kSize8Bit)); |
+ //add labels to the block |
+ auto instr = bb->instructions().begin(); |
+ instr->set_label(test_block_label); |
+ uint32 test_pivot_offset = 1; |
+ uint32 test_sub_offset = 2; |
+ uint32 test_hash_offset = 3; |
+ tx_.label_name_to_block_["Pivot:1"] = std::make_pair(test_block_b, |
+ test_pivot_offset); |
+ tx_.label_name_to_block_["sub 1"] = std::make_pair(test_block_b, |
+ test_sub_offset); |
+ |
+ uint64 test_bb_id = 1; |
+ std::map<uint64, int> test_checkee_map; |
+ test_checkee_map[2] = 1; |
+ test_checkee_map[3] = -1; |
+ tx_.checker_to_checkee_map_[test_bb_id] = test_checkee_map; |
+ tx_.precomputed_hashes_[2] = 0x20; |
+ tx_.precomputed_hashes_[3] = 0x10; |
+ |
+ |
+ uint8 hash1 = 0x1; |
+ uint8 hash2 = 0x2; |
+ tx_.ic_block_reference_free_chunks.insert( |
+ tx_.ic_block_reference_free_chunks.begin(), ChunkInfo(1, 1, hash1, 0, 0)); |
+ tx_.ic_block_reference_free_chunks.insert( |
+ tx_.ic_block_reference_free_chunks.begin(), ChunkInfo(1, 1, hash2, 0, 0)); |
+ std::set<uint32> test_chunk_index_set; |
+ test_chunk_index_set.insert(0); |
+ test_chunk_index_set.insert(1); |
+ tx_.ic_chunk_checker_to_checkee_map_[test_bb_id] = test_chunk_index_set; |
+ |
+ |
+ // push eax, pivot, sub al, old hash |
+ uint8 test_block_data[5] = { 0x50, 0x0, 0x2c, old_hash }; |
+ |
+ test_block_b->SetData(test_block_data, sizeof(test_block_data)); |
+ |
+ |
+ FILE *file=NULL; |
+ tx_.PatchPivot(bb, subgraph, bgraph, file); |
+ |
+ //hash = precomputed sum + precomputed xor |
+ //hash = 0x10 + 0x3 |
+ ASSERT_EQ(test_block_b->data()[test_hash_offset], 0x13); |
+ |
+ uint8 hash_diff = test_block_b->data()[test_pivot_offset] + |
+ test_block_b->data()[test_hash_offset]; |
+ bool is_pivot_correct = hash_diff == old_hash; |
+ |
+ ASSERT_TRUE(is_pivot_correct); |
+ |
+ tx_.ResetTransform(); |
+ |
+ delete bgraph; |
+ delete subgraph; |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckPatchSizesByLabel){ |
+ BlockGraph *bgraph = new BlockGraph(); |
+ BlockGraph::Block *test_block_b = NULL; |
+ test_block_b = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 2000, "sample b"); |
+ base::StringPiece test_block_tag = "1"; |
+ auto test_block_label = block_graph::BlockGraph::Label( |
+ test_block_tag, |
+ BlockGraph::CODE_LABEL); |
+ uint64 test_block_id = 1; |
+ uint32 test_block_size = 1; |
+ //prepare id to label map |
+ tx_.id_to_label_[test_block_id] = test_block_label; |
+ //set the size |
+ tx_.basic_block_sizes_[test_block_id] = test_block_size; |
+ |
+ BasicBlockSubGraph* subgraph = new BasicBlockSubGraph(); |
+ subgraph->set_original_block(test_block_b); |
+ BlockGraph::Section* code_section = bgraph->FindOrAddSection(".text", |
+ 0x60000000); |
+ |
+ subgraph->AddBlockDescription("sample c", code_section->name(), |
+ BlockGraph::CODE_BLOCK, |
+ code_section->id(), 1, 0); |
+ |
+ BasicCodeBlock* bb = subgraph->AddBasicCodeBlock("sample b"); |
+ |
+ auto inst_iter = bb->instructions().begin(); |
+ block_graph::BasicBlockAssembler assm(inst_iter, |
+ &bb->instructions()); |
+ |
+ uint32 test_old_block_size = 0x10; |
+ uint32 test_new_block_size = 0x11; |
+ uint64 test_reference_block_id = 2; |
+ assm.push(assm::eax); |
+ assm.push(block_graph::Immediate(test_old_block_size, assm::kSize32Bit)); |
+ |
+ |
+ inst_iter = bb->instructions().begin(); |
+ //set chunk finger label |
+ inst_iter->set_label(block_graph::BlockGraph::Label("n 1 0", |
+ BlockGraph::CODE_LABEL)); |
+ ++inst_iter; |
+ inst_iter->set_label(block_graph::BlockGraph::Label("size 2 1", |
+ BlockGraph::CODE_LABEL)); |
+ tx_.basic_block_sizes_[test_reference_block_id] = test_new_block_size; |
+ |
+ uint64 test_chunk_bb_id = 1; |
+ uint32 test_chunk_index = 0; |
+ uint32 test_chunk_size = 1; |
+ uint8 test_chunk_hash = 0x50; |
+ |
+ |
+ uint64 test_vector_index = 0; |
+ tx_.ic_block_chunk_index_map_[tx_.GetChunkUniqueKey(test_chunk_bb_id, |
+ test_chunk_index)] = |
+ test_vector_index; |
+ |
+ ChunkInfo test_chunk(test_chunk_bb_id, test_chunk_size, |
+ test_chunk_hash, test_chunk_index, 0); |
+ tx_.ic_block_reference_free_chunks.insert( |
+ tx_.ic_block_reference_free_chunks.begin(), test_chunk); |
+ |
+ tx_.PatchBlockReferencesAndSizes(bb, subgraph, bgraph); |
+ ASSERT_EQ(inst_iter->data()[1], test_new_block_size); |
+ |
+ tx_.ResetTransform(); |
+ delete bgraph; |
+ delete subgraph; |
+ |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckPatchBlockReferenceByLabel) { |
+ BlockGraph *bgraph = NULL; |
+ BlockGraph::Block *test_block_a = NULL; |
+ |
+ bgraph = new BlockGraph(); |
+ test_block_a = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_a"); |
+ |
+ BasicBlockSubGraph* subgraph = new BasicBlockSubGraph(); |
+ subgraph->set_original_block(test_block_a); |
+ BlockGraph::Section* code_section = bgraph->FindOrAddSection(".text", |
+ 0x60000000); |
+ |
+ subgraph->AddBlockDescription("test_subgraph", code_section->name(), |
+ BlockGraph::CODE_BLOCK, |
+ code_section->id(), 1, 0); |
+ |
+ BasicCodeBlock* bb = subgraph->AddBasicCodeBlock("basic_code_block"); |
+ auto inst_iter = bb->instructions().begin(); |
+ block_graph::BasicBlockAssembler assm(inst_iter, |
+ &bb->instructions()); |
+ |
+ int original_offset = 100; |
+ assm.push(block_graph::Immediate(test_block_a, original_offset)); |
+ inst_iter = bb->instructions().begin(); |
+ inst_iter->set_label(BlockGraph::Label("block 2", |
+ BlockGraph::CODE_LABEL)); |
+ int intermediate_offset = 150; |
+ |
+ //move block offset |
+ tx_.label_name_to_block_["2"] = |
+ std::make_pair(test_block_a, intermediate_offset); |
+ |
+ // Check initial offset and reference |
+ inst_iter = bb->instructions().begin(); |
+ Instruction::BasicBlockReferenceMap &ref_block_map = |
+ inst_iter->references(); |
+ auto instruction_references_it = ref_block_map.begin(); |
+ BlockGraph::Offset reference_offset = instruction_references_it->first; |
+ block_graph::BasicBlockReference old_bb_ref = |
+ instruction_references_it->second; |
+ ASSERT_TRUE(old_bb_ref.block() == test_block_a); |
+ ASSERT_TRUE(old_bb_ref.offset() == original_offset); |
+ |
+ |
+ |
+ tx_.PatchBlockReferencesAndSizes(bb, subgraph, bgraph); |
+ |
+ inst_iter = bb->instructions().begin(); |
+ // Check the modifications |
+ instruction_references_it = inst_iter->references().begin(); |
+ reference_offset = instruction_references_it->first; |
+ block_graph::BasicBlockReference new_bb_ref = |
+ instruction_references_it->second; |
+ |
+ ASSERT_TRUE(new_bb_ref.block() == test_block_a); |
+ ASSERT_TRUE(new_bb_ref.offset() == intermediate_offset); |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckPatchChunkReferenceByLabel) { |
+ BlockGraph *bgraph = NULL; |
+ BlockGraph::Block *test_block_a = NULL; |
+ |
+ bgraph = new BlockGraph(); |
+ test_block_a = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_a"); |
+ |
+ BasicBlockSubGraph* subgraph = new BasicBlockSubGraph(); |
+ subgraph->set_original_block(test_block_a); |
+ BlockGraph::Section* code_section = bgraph->FindOrAddSection(".text", |
+ 0x60000000); |
+ |
+ subgraph->AddBlockDescription("test_subgraph", code_section->name(), |
+ BlockGraph::CODE_BLOCK, |
+ code_section->id(), 1, 0); |
+ |
+ BasicCodeBlock* bb = subgraph->AddBasicCodeBlock("basic_code_block"); |
+ auto inst_iter = bb->instructions().begin(); |
+ block_graph::BasicBlockAssembler assm(inst_iter, |
+ &bb->instructions()); |
+ |
+ int original_offset = 100; |
+ assm.push(block_graph::Immediate(test_block_a, original_offset)); |
+ inst_iter = bb->instructions().begin(); |
+ inst_iter->set_label(BlockGraph::Label("nrc 2 0", |
+ BlockGraph::CODE_LABEL)); |
+ int intermediate_offset = 150; |
+ |
+ //move block offset |
+ tx_.label_name_to_block_["n 2 0"] = |
+ std::make_pair(test_block_a, intermediate_offset); |
+ |
+ // Check initial offset and reference |
+ inst_iter = bb->instructions().begin(); |
+ Instruction::BasicBlockReferenceMap &ref_block_map = |
+ inst_iter->references(); |
+ auto instruction_references_it = ref_block_map.begin(); |
+ BlockGraph::Offset reference_offset = instruction_references_it->first; |
+ block_graph::BasicBlockReference old_bb_ref = |
+ instruction_references_it->second; |
+ ASSERT_TRUE(old_bb_ref.block() == test_block_a); |
+ ASSERT_TRUE(old_bb_ref.offset() == original_offset); |
+ |
+ |
+ |
+ tx_.PatchBlockReferencesAndSizes(bb, subgraph, bgraph); |
+ |
+ inst_iter = bb->instructions().begin(); |
+ // Check the modifications |
+ instruction_references_it = inst_iter->references().begin(); |
+ reference_offset = instruction_references_it->first; |
+ block_graph::BasicBlockReference new_bb_ref = |
+ instruction_references_it->second; |
+ |
+ ASSERT_TRUE(new_bb_ref.block() == test_block_a); |
+ ASSERT_TRUE(new_bb_ref.offset() == intermediate_offset); |
+} |
+TEST_F(IntegrityCheckTransformTest, CheckAddChunkIntegrityCheckCode) { |
+ |
+ uint64 test_bb_id = 1; |
+ //set total chunks |
+ tx_.num_chunks_per_block = 10; |
+ |
+ BlockGraph *bgraph = NULL; |
+ BlockGraph::Block *test_block_a = NULL; |
+ |
+ bgraph = new BlockGraph(); |
+ test_block_a = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_a"); |
+ |
+ BasicBlockSubGraph* subgraph = new BasicBlockSubGraph(); |
+ subgraph->set_original_block(test_block_a); |
+ BlockGraph::Section* code_section = bgraph->FindOrAddSection(".text", |
+ 0x60000000); |
+ |
+ subgraph->AddBlockDescription("test_subgraph", code_section->name(), |
+ BlockGraph::CODE_BLOCK, |
+ code_section->id(), 1, 0); |
+ |
+ BasicCodeBlock* bb = subgraph->AddBasicCodeBlock("basic_code_block"); |
+ auto inst_iter = bb->instructions().begin(); |
+ block_graph::BasicBlockAssembler assm(inst_iter, |
+ &bb->instructions()); |
+ |
+ assm.push(assm::eax); |
+ inst_iter = bb->instructions().begin(); |
+ //set block id label |
+ auto test_block_label = BlockGraph::Label(std::to_string(test_bb_id), |
+ BlockGraph::CODE_LABEL); |
+ inst_iter->set_label(test_block_label); |
+ //set a dummy hash block |
+ tx_.xhash_block_ = test_block_a; |
+ |
+ //prepare id to label map |
+ tx_.id_to_label_[test_bb_id] = test_block_label; |
+ //set block size |
+ uint32 old_size = inst_iter->size(); |
+ tx_.basic_block_sizes_[test_bb_id] = old_size; |
+ |
+ //set checker checkee map |
+ |
+ std::map<uint64, int> test_checkee_map; |
+ test_checkee_map[2] = 1; |
+ test_checkee_map[3] = -1; |
+ tx_.checker_to_checkee_map_[test_bb_id] = test_checkee_map; |
+ tx_.precomputed_hashes_[2] = 0x20; |
+ tx_.precomputed_hashes_[3] = 0x10; |
+ |
+ //set chunk checker map |
+ uint8 hash1 = 0x1; |
+ std::set<uint32> test_chunk_index_set; |
+ for (uint32 i = 0; i < tx_.num_chunks_per_block; ++i){ |
+ tx_.ic_block_reference_free_chunks.insert( |
+ tx_.ic_block_reference_free_chunks.begin(), ChunkInfo(1, 1, hash1, i,0)); |
+ test_chunk_index_set.insert(i); |
+ char *buffersearch = new char[50]; |
+ sprintf_s(buffersearch, 50, "n %llu %lu", test_bb_id, i); |
+ tx_.label_name_to_block_[buffersearch] = std::make_pair(test_block_a, 0); |
+ delete[] buffersearch; |
+ } |
+ tx_.ic_chunk_checker_to_checkee_map_[test_bb_id] = test_chunk_index_set; |
+ |
+ |
+ tx_.AddChunkIntegrityCheckCode(bb, subgraph, bgraph); |
+ |
+ //Ensure basic_block_sizes_[bb_id] is larger than before |
+ ASSERT_GT(tx_.basic_block_sizes_[test_bb_id], old_size); |
+ //Check there are equal number of chunks and nrc labels |
+ inst_iter = bb->instructions().begin(); |
+ uint32 nr_added_labels = 0; |
+ std::string chunk_pointerlabel = "nrc"; |
+ for (; inst_iter != bb->instructions().end(); ++inst_iter){ |
+ if (inst_iter->label().name() |
+ .compare(0, chunk_pointerlabel.length(), chunk_pointerlabel) == 0){ |
+ ++nr_added_labels; |
+ } |
+ } |
+ |
+ //Ensure kNumChunksPerBlock == #chunks |
+ ASSERT_EQ(tx_.num_chunks_per_block, nr_added_labels); |
+ |
+ tx_.ResetTransform(); |
+ delete bgraph; |
+ delete subgraph; |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckAddIntegrityCheckCode) { |
+//check labels block, pivot, size, sub instruction |
+ uint64 test_bb_id = 1; |
+ uint64 test_checkee1_id = 2; |
+ uint64 test_checkee2_id = 3; |
+ BlockGraph *bgraph = NULL; |
+ BlockGraph::Block *test_block_a = NULL; |
+ BlockGraph::Block *test_block_b = NULL; |
+ |
+ bgraph = new BlockGraph(); |
+ test_block_a = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_a"); |
+ test_block_b = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_b"); |
+ |
+ BasicBlockSubGraph* subgraph = new BasicBlockSubGraph(); |
+ subgraph->set_original_block(test_block_a); |
+ BlockGraph::Section* code_section = bgraph->FindOrAddSection(".text", |
+ 0x60000000); |
+ |
+ subgraph->AddBlockDescription("test_subgraph", code_section->name(), |
+ BlockGraph::CODE_BLOCK, |
+ code_section->id(), 1, 0); |
+ |
+ BasicBlockSubGraph* subgraph_b = new BasicBlockSubGraph(); |
+ subgraph_b->set_original_block(test_block_b); |
+ |
+ subgraph_b->AddBlockDescription("test_subgraph", code_section->name(), |
+ BlockGraph::CODE_BLOCK, |
+ code_section->id(), 1, 0); |
+ |
+ |
+ BasicCodeBlock* bb = subgraph->AddBasicCodeBlock("basic_code_block"); |
+ auto inst_iter = bb->instructions().begin(); |
+ block_graph::BasicBlockAssembler assm(inst_iter, |
+ &bb->instructions()); |
+ |
+ assm.push(assm::eax); |
+ inst_iter = bb->instructions().begin(); |
+ //set block id label |
+ auto test_block_label = BlockGraph::Label(std::to_string(test_bb_id), |
+ BlockGraph::CODE_LABEL); |
+ inst_iter->set_label(test_block_label); |
+ //prepare id to label map |
+ tx_.id_to_label_[test_bb_id] = test_block_label; |
+ //set block id label |
+ auto test_checkee1_label = BlockGraph::Label(std::to_string(test_checkee1_id), |
+ BlockGraph::CODE_LABEL); |
+ tx_.id_to_label_[test_checkee1_id] = test_checkee1_label; |
+ tx_.label_name_to_block_[std::to_string(test_checkee1_id)] = |
+ std::make_pair(test_block_b, 0); |
+ auto test_checkee2_label = BlockGraph::Label(std::to_string(test_checkee2_id), |
+ BlockGraph::CODE_LABEL); |
+ tx_.id_to_label_[test_checkee2_id] = test_checkee2_label; |
+ |
+ tx_.label_name_to_block_[std::to_string(test_checkee2_id)] = |
+ std::make_pair(test_block_b, 0); |
+ //set a dummy hash block |
+ tx_.hash_block_ = test_block_a; |
+ //set dummy response block |
+ tx_.response_block_ = test_block_a; |
+ //set block size |
+ uint32 old_size = inst_iter->size(); |
+ tx_.basic_block_sizes_[test_bb_id] = old_size; |
+ tx_.basic_block_sizes_[test_checkee1_id] = 1; |
+ tx_.basic_block_sizes_[test_checkee2_id] = 1; |
+ //set checker checkee map |
+ |
+ std::map<uint64, int> test_checkee_map; |
+ test_checkee_map[test_checkee1_id] = 1; |
+ test_checkee_map[test_checkee2_id] = -1; |
+ tx_.checker_to_checkee_map_[test_bb_id] = test_checkee_map; |
+ tx_.precomputed_hashes_[test_checkee1_id] = 0x20; |
+ tx_.precomputed_hashes_[test_checkee2_id] = 0x10; |
+ |
+ tx_.AddIntegrityCheckCode(bb, subgraph, bgraph); |
+ |
+ //Ensure basic_block_sizes_[bb_id] is larger than before |
+ ASSERT_GT(tx_.basic_block_sizes_[test_bb_id], old_size); |
+ //Check there are equal number of chunks and nrc labels |
+ inst_iter = bb->instructions().begin(); |
+ uint32 nr_added_block_labels = 0; |
+ std::string block_pointerlabel = "block"; |
+ uint32 nr_added_size_labels = 0; |
+ std::string size_pointerlabel = "size"; |
+ uint32 nr_added_pivot_labels = 0; |
+ std::string pivot_pointerlabel = "Pivot"; |
+ uint32 nr_added_sub_labels = 0; |
+ std::string sub_pointerlabel = "sub"; |
+ for (; inst_iter != bb->instructions().end(); ++inst_iter){ |
+ if (inst_iter->label().name() |
+ .compare(0, block_pointerlabel.length(), block_pointerlabel) == 0){ |
+ ++nr_added_block_labels; |
+ } else if (inst_iter->label().name() |
+ .compare(0, size_pointerlabel.length(), size_pointerlabel) == 0){ |
+ ++nr_added_size_labels; |
+ } |
+ else if (inst_iter->label().name().compare(0, pivot_pointerlabel.length(), |
+ pivot_pointerlabel) == 0){ |
+ ++nr_added_pivot_labels; |
+ } else if (inst_iter->label().name().compare(0, sub_pointerlabel.length(), |
+ sub_pointerlabel) == 0){ |
+ ++nr_added_sub_labels; |
+ } |
+ |
+ } |
+ |
+ //Ensure kNumChunksPerBlock == #chunks |
+ ASSERT_EQ(test_checkee_map.size(), nr_added_block_labels); |
+ ASSERT_EQ(test_checkee_map.size(), nr_added_size_labels); |
+ ASSERT_EQ(1, nr_added_pivot_labels); |
+ ASSERT_EQ(1, nr_added_sub_labels); |
+ |
+ tx_.ResetTransform(); |
+ delete bgraph; |
+ delete subgraph; |
+ delete subgraph_b; |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckComputeChunksWhenInstructionHasLabel) { |
+ uint64 test_bb_id = 1; |
+ BlockGraph *bgraph = NULL; |
+ BlockGraph::Block *test_block_a = NULL; |
+ |
+ bgraph = new BlockGraph(); |
+ test_block_a = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_a"); |
+ |
+ BasicBlockSubGraph* subgraph = new BasicBlockSubGraph(); |
+ subgraph->set_original_block(test_block_a); |
+ BlockGraph::Section* code_section = bgraph->FindOrAddSection(".text", |
+ 0x60000000); |
+ |
+ subgraph->AddBlockDescription("test_subgraph", code_section->name(), |
+ BlockGraph::CODE_BLOCK, |
+ code_section->id(), 1, 0); |
+ |
+ BasicCodeBlock* bb = subgraph->AddBasicCodeBlock("basic_code_block"); |
+ auto inst_iter = bb->instructions().begin(); |
+ block_graph::BasicBlockAssembler assm(inst_iter, |
+ &bb->instructions()); |
+ |
+ assm.push(assm::eax); |
+ assm.data(0); |
+ |
+ auto test_label = BlockGraph::Label(std::to_string(test_bb_id), |
+ BlockGraph::CODE_LABEL); |
+ inst_iter = bb->instructions().begin(); |
+ inst_iter->set_label(test_label); |
+ //Every checker comes with a pivot |
+ ++inst_iter; |
+ inst_iter->set_label(BlockGraph::Label("Pivot:", |
+ BlockGraph::CODE_LABEL)); |
+ |
+ tx_.id_to_label_[test_bb_id] = test_label; |
+ |
+ //make the block a checker |
+ |
+ uint64 test_checkee1_id = 2; |
+ uint64 test_checkee2_id = 3; |
+ std::map<uint64, int> test_checkee_map; |
+ test_checkee_map[test_checkee1_id] = 1; |
+ test_checkee_map[test_checkee2_id] = -1; |
+ tx_.checker_to_checkee_map_[test_bb_id] = test_checkee_map; |
+ tx_.precomputed_hashes_[test_checkee1_id] = 0x20; |
+ tx_.precomputed_hashes_[test_checkee2_id] = 0x10; |
+ |
+ |
+ tx_.ComputeChunks(bb); |
+ |
+ //on instructions with label don't set chunk label |
+ ASSERT_EQ(0, tx_.ic_block_reference_free_chunks.size()); |
+ |
+ tx_.ResetTransform(); |
+ delete bgraph; |
+ delete subgraph; |
+} |
+TEST_F(IntegrityCheckTransformTest, CheckComputeChunksWhenLastInstruction) { |
+ uint64 test_bb_id = 1; |
+ BlockGraph *bgraph = NULL; |
+ BlockGraph::Block *test_block_a = NULL; |
+ |
+ bgraph = new BlockGraph(); |
+ test_block_a = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_a"); |
+ |
+ BasicBlockSubGraph* subgraph = new BasicBlockSubGraph(); |
+ subgraph->set_original_block(test_block_a); |
+ BlockGraph::Section* code_section = bgraph->FindOrAddSection(".text", |
+ 0x60000000); |
+ |
+ subgraph->AddBlockDescription("test_subgraph", code_section->name(), |
+ BlockGraph::CODE_BLOCK, |
+ code_section->id(), 1, 0); |
+ |
+ BasicCodeBlock* bb = subgraph->AddBasicCodeBlock("basic_code_block"); |
+ auto inst_iter = bb->instructions().begin(); |
+ block_graph::BasicBlockAssembler assm(inst_iter, |
+ &bb->instructions()); |
+ |
+ assm.push(assm::eax); |
+ assm.data(0); |
+ assm.push(assm::ebx); |
+ |
+ auto test_label = BlockGraph::Label(std::to_string(test_bb_id), |
+ BlockGraph::CODE_LABEL); |
+ inst_iter = bb->instructions().begin(); |
+ inst_iter->set_label(test_label); |
+ //Every checker comes with a pivot |
+ ++inst_iter; |
+ inst_iter->set_label(BlockGraph::Label("Pivot:", |
+ BlockGraph::CODE_LABEL)); |
+ |
+ tx_.id_to_label_[test_bb_id] = test_label; |
+ |
+ //make the block a checker |
+ |
+ uint64 test_checkee1_id = 2; |
+ uint64 test_checkee2_id = 3; |
+ std::map<uint64, int> test_checkee_map; |
+ test_checkee_map[test_checkee1_id] = 1; |
+ test_checkee_map[test_checkee2_id] = -1; |
+ tx_.checker_to_checkee_map_[test_bb_id] = test_checkee_map; |
+ tx_.precomputed_hashes_[test_checkee1_id] = 0x20; |
+ tx_.precomputed_hashes_[test_checkee2_id] = 0x10; |
+ |
+ |
+ tx_.ComputeChunks(bb); |
+ |
+ //last push ebx should be recognized as a chunk |
+ ASSERT_EQ(1, tx_.ic_block_reference_free_chunks.size()); |
+ |
+ tx_.ResetTransform(); |
+ delete bgraph; |
+ delete subgraph; |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckComputeChunksWhenAbsReferenceBetween) { |
+ uint64 test_bb_id = 1; |
+ BlockGraph *bgraph = NULL; |
+ BlockGraph::Block *test_block_a = NULL; |
+ |
+ bgraph = new BlockGraph(); |
+ test_block_a = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_a"); |
+ |
+ BasicBlockSubGraph* subgraph = new BasicBlockSubGraph(); |
+ subgraph->set_original_block(test_block_a); |
+ BlockGraph::Section* code_section = bgraph->FindOrAddSection(".text", |
+ 0x60000000); |
+ |
+ subgraph->AddBlockDescription("test_subgraph", code_section->name(), |
+ BlockGraph::CODE_BLOCK, |
+ code_section->id(), 1, 0); |
+ |
+ BasicCodeBlock* bb = subgraph->AddBasicCodeBlock("basic_code_block"); |
+ auto inst_iter = bb->instructions().begin(); |
+ block_graph::BasicBlockAssembler assm(inst_iter, |
+ &bb->instructions()); |
+ |
+ assm.push(assm::eax); |
+ assm.data(0); |
+ assm.push(assm::ebx); |
+ assm.push(block_graph::Immediate(test_block_a, 0)); |
+ assm.add(assm::eax, assm::ebx); |
+ |
+ auto test_label = BlockGraph::Label(std::to_string(test_bb_id), |
+ BlockGraph::CODE_LABEL); |
+ inst_iter = bb->instructions().begin(); |
+ inst_iter->set_label(test_label); |
+ //Every checker comes with a pivot |
+ ++inst_iter; |
+ inst_iter->set_label(BlockGraph::Label("Pivot:", |
+ BlockGraph::CODE_LABEL)); |
+ |
+ tx_.id_to_label_[test_bb_id] = test_label; |
+ |
+ //make the block a checker |
+ |
+ uint64 test_checkee1_id = 2; |
+ uint64 test_checkee2_id = 3; |
+ std::map<uint64, int> test_checkee_map; |
+ test_checkee_map[test_checkee1_id] = 1; |
+ test_checkee_map[test_checkee2_id] = -1; |
+ tx_.checker_to_checkee_map_[test_bb_id] = test_checkee_map; |
+ tx_.precomputed_hashes_[test_checkee1_id] = 0x20; |
+ tx_.precomputed_hashes_[test_checkee2_id] = 0x10; |
+ |
+ |
+ tx_.ComputeChunks(bb); |
+ |
+ //push ebx and add eax,ebx are two chunks spearated by an abs reference |
+ ASSERT_EQ(2, tx_.ic_block_reference_free_chunks.size()); |
+ |
+ //push ebx is one byte |
+ ASSERT_EQ(1, tx_.ic_block_reference_free_chunks[0].size_); |
+ //add eax,ebx is two bytes |
+ ASSERT_EQ(2, tx_.ic_block_reference_free_chunks[1].size_); |
+ |
+ tx_.ResetTransform(); |
+ delete bgraph; |
+ delete subgraph; |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckAddChunkIntoIndexMap) { |
+ uint64 test_chunk_bb_id = 1; |
+ uint32 test_chunk_index = 0; |
+ uint32 test_vector_index = 0; |
+ tx_.AddChunkIntoIndexMap(test_chunk_bb_id, |
+ test_chunk_index, |
+ test_vector_index); |
+ ASSERT_EQ(test_vector_index, tx_.ic_block_chunk_index_map_[ |
+ tx_.GetChunkUniqueKey(test_chunk_bb_id, test_chunk_index)]); |
+ |
+ tx_.ResetTransform(); |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckGetChunkUniqueKey) { |
+ uint64 test_chunk_bb_id = 1; |
+ uint32 test_chunk_index = 0; |
+ uint64 unique_id = tx_.GetChunkUniqueKey(test_chunk_bb_id, test_chunk_index); |
+ |
+ ASSERT_NE(static_cast<uint64>(0), unique_id); |
+ tx_.ResetTransform(); |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckGenerateChunkCombinations) { |
+ //build 2 checkers in two subgraphs because chunks are assigned to different |
+ //subgraphs |
+ BlockGraph *bgraph = NULL; |
+ BlockGraph::Block *test_block_a = NULL; |
+ BlockGraph::Block *test_block_b = NULL; |
+ uint64 test_bb1_id = 1; |
+ uint64 test_bb2_id = 4; |
+ std::vector<ChunkInfo> test_chunks; |
+ |
+ bgraph = new BlockGraph(); |
+ test_block_a = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_a"); |
+ test_block_b = bgraph->AddBlock(BlockGraph::CODE_BLOCK, 1000, "dest_b"); |
+ |
+ BasicBlockSubGraph* subgraph = new BasicBlockSubGraph(); |
+ subgraph->set_original_block(test_block_a); |
+ BlockGraph::Section* code_section = bgraph->FindOrAddSection(".text", |
+ 0x60000000); |
+ |
+ subgraph->AddBlockDescription("test_subgraph", code_section->name(), |
+ BlockGraph::CODE_BLOCK, |
+ code_section->id(), 1, 0); |
+ |
+ BasicBlockSubGraph* subgraph_b = new BasicBlockSubGraph(); |
+ subgraph_b->set_original_block(test_block_b); |
+ |
+ subgraph_b->AddBlockDescription("test_subgraph", code_section->name(), |
+ BlockGraph::CODE_BLOCK, |
+ code_section->id(), 1, 0); |
+ |
+ |
+ |
+ //set block id label |
+ auto test_block1_label = BlockGraph::Label(std::to_string(test_bb1_id), |
+ BlockGraph::CODE_LABEL); |
+ auto test_block2_label = BlockGraph::Label(std::to_string(test_bb2_id), |
+ BlockGraph::CODE_LABEL); |
+ //prepare id to label map |
+ tx_.id_to_label_[test_bb1_id] = test_block1_label; |
+ tx_.id_to_label_[test_bb2_id] = test_block2_label; |
+ |
+ |
+ //add chunks label |
+ for (uint32 i = 0; i< tx_.num_chunks_per_block; ++i) { |
+ std::string label = "n " + std::to_string(test_bb1_id) |
+ + " " + std::to_string(i); |
+ tx_.label_name_to_block_[label] = std::make_pair(test_block_a, 0); |
+ test_chunks.insert(test_chunks.begin(), ChunkInfo(test_bb1_id, 1, 1, i,0)); |
+ } |
+ for (uint32 i = 0; i< tx_.num_chunks_per_block; ++i) { |
+ std::string label = "n " + std::to_string(test_bb2_id) |
+ + " " + std::to_string(i); |
+ tx_.label_name_to_block_[label] = std::make_pair(test_block_b, 0); |
+ test_chunks.insert(test_chunks.begin(), ChunkInfo(test_bb2_id, 1, 1, i,0)); |
+ } |
+ |
+ tx_.label_name_to_block_[std::to_string(test_bb1_id)] = |
+ std::make_pair(test_block_a, 0); |
+ tx_.label_name_to_block_[std::to_string(test_bb2_id)] = |
+ std::make_pair(test_block_b, 0); |
+ |
+ uint64 test_checkee1_id = 2; |
+ uint64 test_checkee2_id = 3; |
+ std::map<uint64, int> test_checkee_map; |
+ test_checkee_map[test_checkee1_id] = 1; |
+ test_checkee_map[test_checkee2_id] = -1; |
+ tx_.checker_to_checkee_map_[test_bb1_id] = test_checkee_map; |
+ tx_.checker_to_checkee_map_[test_bb2_id] = test_checkee_map; |
+ |
+ //prepare 20 chunks from these two checkers |
+ //20 n labels |
+ float test_chunk_coverage = 0.5; |
+ bool test_force_all = false; |
+ uint32 chunk_per_block = 0; |
+ auto chunk_map = tx_.GenerateChunkCombinations(test_chunks, |
+ test_chunk_coverage, |
+ test_force_all, |
+ &chunk_per_block |
+ ); |
+ |
+ |
+ ASSERT_EQ(2, chunk_map.size()); |
+ ASSERT_EQ(5, chunk_map[test_bb1_id].size()); |
+ ASSERT_EQ(5, chunk_map[test_bb2_id].size()); |
+ ASSERT_EQ(5, chunk_per_block); |
+ |
+ //strictly picking all blocks |
+ test_chunk_coverage = 1; |
+ test_force_all = true; |
+ chunk_per_block = 0; |
+ chunk_map = tx_.GenerateChunkCombinations(test_chunks, |
+ test_chunk_coverage, |
+ test_force_all, |
+ &chunk_per_block); |
+ |
+ ASSERT_EQ(2, chunk_map.size()); |
+ ASSERT_EQ(10, chunk_map[test_bb1_id].size()); |
+ ASSERT_EQ(10, chunk_map[test_bb2_id].size()); |
+ ASSERT_EQ(10, chunk_per_block); |
+ |
+ tx_.ResetTransform(); |
+ delete bgraph; |
+ delete subgraph; |
+ delete subgraph_b; |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckRandomlySelectChecker) { |
+ |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckIsIdInPartitionUnitMap) { |
+ |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckFixAllCheckeesOfBasicBlock) { |
+ |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckPatchInterBlockReferences) { |
+ |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckPrecomputeHash) { |
+ |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckAddReference) { |
+ |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckGetBasicBlockIdByLabel) { |
+ |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckTransformBasicBlockSubGraph) { |
+ |
+} |
+ |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckShouldProcessBlock) { |
+ |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckProcessAllBlocks) { |
+ |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckGenerateBasicBlockCombinations) { |
+ |
+} |
+ |
+TEST_F(IntegrityCheckTransformTest, CheckTransformBlockGraph) { |
+ |
+} |
+} |