diff --git a/.clang-tidy b/.clang-tidy index 3e95f2eaea..3308a915db 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -61,7 +61,7 @@ CheckOptions: - key: readability-identifier-naming.ParameterIgnoredRegexp value: (d|d1|d2|d3|d4|d5|eP|f|n) - key: readability-identifier-naming.FunctionIgnoredRegexp - value: (try_emplace|from_json|to_json|equal_to|to_string|DToString|NToString|FToString|LToString|hash_value) + value: (try_emplace|from_json|to_json|equal_to|to_string|DToString|NToString|FToString|LToString|hash_value|dyn_cast) - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor value: 1 - key: cppcoreguidelines-special-member-functions.AllowMissingMoveFunctions diff --git a/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h b/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h index 534357f5bb..fe1827b661 100644 --- a/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h +++ b/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h @@ -1616,7 +1616,7 @@ class IDESolver } else { // Get the fact-ID D1FactId = G.getFactID(D1Fact); - std::string D1Label = DToString(D1Fact); + std::string D1Label{DToString(D1Fact)}; // Get or create the fact subgraph D1FSG = FG->getOrCreateFactSG(D1FactId, D1Label); @@ -1634,7 +1634,7 @@ class IDESolver if (!IDEProblem.isZeroValue(D2Fact)) { // Get the fact-ID D2FactId = G.getFactID(D2Fact); - std::string D2Label = DToString(D2Fact); + std::string D2Label{DToString(D2Fact)}; DOTNode D2 = {FuncName, D2Label, N2StmtId, D2FactId, false, true}; std::string EFLabel; auto EFVec = IntermediateEdgeFunctions[std::make_tuple( @@ -1719,7 +1719,7 @@ class IDESolver } else { // Get the fact-ID D1FactId = G.getFactID(D1Fact); - std::string D1Label = DToString(D1Fact); + std::string D1Label{DToString(D1Fact)}; D1 = {FNameOfN1, D1Label, N1StmtId, D1FactId, false, true}; // FG should already exist even for single statement functions if (!G.containsFactSG(FNameOfN1, D1FactId)) { @@ -1738,7 +1738,7 @@ class IDESolver } else { // Get the fact-ID D2FactId = G.getFactID(D2Fact); - std::string D2Label = DToString(D2Fact); + std::string D2Label{DToString(D2Fact)}; D2 = {FNameOfN2, D2Label, N2StmtId, D2FactId, false, true}; // FG should already exist even for single statement functions if (!G.containsFactSG(FNameOfN2, D2FactId)) { diff --git a/include/phasar/Domain/LatticeDomain.h b/include/phasar/Domain/LatticeDomain.h index d45f7bc45a..560409f370 100644 --- a/include/phasar/Domain/LatticeDomain.h +++ b/include/phasar/Domain/LatticeDomain.h @@ -11,6 +11,7 @@ #define PHASAR_DOMAIN_LATTICEDOMAIN_H #include "phasar/Utils/ByRef.h" +#include "phasar/Utils/DebugOutput.h" #include "phasar/Utils/JoinLattice.h" #include "phasar/Utils/TypeTraits.h" @@ -100,9 +101,7 @@ struct LatticeDomain : public std::variant { } }; -template () - << std::declval())>> +template inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const LatticeDomain &LD) { if (LD.isBottom()) { @@ -114,7 +113,11 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const auto *Val = LD.getValueOrNull(); assert(Val && "Only alternative remaining is L"); - return OS << *Val; + if constexpr (is_llvm_printable_v) { + return OS << *Val; + } else { + return OS << PrettyPrinter{*Val}; + } } template diff --git a/include/phasar/Utils/BitVectorSet.h b/include/phasar/Utils/BitVectorSet.h index c64f8f41bf..b11786e847 100644 --- a/include/phasar/Utils/BitVectorSet.h +++ b/include/phasar/Utils/BitVectorSet.h @@ -292,9 +292,9 @@ class BitVectorSet { [[nodiscard]] size_t size() const noexcept { return Bits.count(); } - [[nodiscard]] const BitVectorTy &getBits() const &noexcept { return Bits; } - [[nodiscard]] BitVectorTy &getBits() &noexcept { return Bits; } - [[nodiscard]] BitVectorTy &&getBits() &&noexcept { return std::move(Bits); } + [[nodiscard]] const BitVectorTy &getBits() const & noexcept { return Bits; } + [[nodiscard]] BitVectorTy &getBits() & noexcept { return Bits; } + [[nodiscard]] BitVectorTy &&getBits() && noexcept { return std::move(Bits); } friend bool operator==(const BitVectorSet &Lhs, const BitVectorSet &Rhs) { bool LeftEmpty = Lhs.empty(); @@ -392,6 +392,11 @@ class BitVectorSet { EndIter.setBits(Bits); return EndIter; } + + static void clearPosition() { + Position.left.clear(); + Position.right.clear(); + } }; // Overloads with the other intersectWith functions from Utilities.h diff --git a/lib/PhasarLLVM/Utils/LLVMIRToSrc.cpp b/lib/PhasarLLVM/Utils/LLVMIRToSrc.cpp index 09abf5fecd..af8b41bf76 100644 --- a/lib/PhasarLLVM/Utils/LLVMIRToSrc.cpp +++ b/lib/PhasarLLVM/Utils/LLVMIRToSrc.cpp @@ -101,15 +101,19 @@ static llvm::DISubprogram *getDISubprogram(const llvm::Value *V) { llvm::DILocation *psr::getDILocation(const llvm::Value *V) { // Arguments and Instruction such as AllocaInst - if (auto *DbgIntr = getDbgVarIntrinsic(V)) { - if (auto *MN = DbgIntr->getMetadata(llvm::LLVMContext::MD_dbg)) { + + if (const auto *I = llvm::dyn_cast(V)) { + if (auto *MN = I->getMetadata(llvm::LLVMContext::MD_dbg)) { return llvm::dyn_cast(MN); } - } else if (const auto *I = llvm::dyn_cast(V)) { - if (auto *MN = I->getMetadata(llvm::LLVMContext::MD_dbg)) { + } + + if (auto *DbgIntr = getDbgVarIntrinsic(V)) { + if (auto *MN = DbgIntr->getMetadata(llvm::LLVMContext::MD_dbg)) { return llvm::dyn_cast(MN); } } + return nullptr; } diff --git a/test/llvm_test_code/general_linear_constant/CMakeLists.txt b/test/llvm_test_code/general_linear_constant/CMakeLists.txt index c1da0c9533..d0e555ccf6 100644 --- a/test/llvm_test_code/general_linear_constant/CMakeLists.txt +++ b/test/llvm_test_code/general_linear_constant/CMakeLists.txt @@ -14,5 +14,5 @@ set(Sources ) foreach(TEST_SRC ${Sources}) - generate_ll_file(FILE ${TEST_SRC}) + generate_ll_file(FILE ${TEST_SRC} DEBUG) endforeach(TEST_SRC) diff --git a/test/llvm_test_code/general_linear_constant/NullTest.c b/test/llvm_test_code/general_linear_constant/NullTest.c index 7858875af1..550254165f 100644 --- a/test/llvm_test_code/general_linear_constant/NullTest.c +++ b/test/llvm_test_code/general_linear_constant/NullTest.c @@ -2,4 +2,7 @@ char *foo(char *str) { return str; } extern void puts(const char *); -int main() { puts(foo(0)); } +int main() { + puts(foo(0)); + return 0; +} diff --git a/test/llvm_test_code/inst_interaction/CMakeLists.txt b/test/llvm_test_code/inst_interaction/CMakeLists.txt index 6fdfa88e8b..e5307f4949 100644 --- a/test/llvm_test_code/inst_interaction/CMakeLists.txt +++ b/test/llvm_test_code/inst_interaction/CMakeLists.txt @@ -41,9 +41,9 @@ set(SourcesOpt ) foreach(TEST_SRC ${Sources}) - generate_ll_file(FILE ${TEST_SRC}) + generate_ll_file(FILE ${TEST_SRC} DEBUG) endforeach(TEST_SRC) foreach(TEST_SRC ${SourcesOpt}) - generate_ll_file(FILE ${TEST_SRC} O1) + generate_ll_file(FILE ${TEST_SRC} DEBUG O1) endforeach(TEST_SRC) diff --git a/test/llvm_test_code/openssl/key_derivation/CMakeLists.txt b/test/llvm_test_code/openssl/key_derivation/CMakeLists.txt index 7565aeef5e..39770d7dbf 100644 --- a/test/llvm_test_code/openssl/key_derivation/CMakeLists.txt +++ b/test/llvm_test_code/openssl/key_derivation/CMakeLists.txt @@ -2,5 +2,5 @@ file(GLOB openssl_files *.c *.cpp) foreach(TEST_SRC ${openssl_files}) get_filename_component(TEST_SRC_FILE ${TEST_SRC} NAME) - generate_ll_file(FILE ${TEST_SRC_FILE}) + generate_ll_file(FILE ${TEST_SRC_FILE} DEBUG) endforeach(TEST_SRC) diff --git a/test/llvm_test_code/openssl/secure_heap/CMakeLists.txt b/test/llvm_test_code/openssl/secure_heap/CMakeLists.txt index 7565aeef5e..39770d7dbf 100644 --- a/test/llvm_test_code/openssl/secure_heap/CMakeLists.txt +++ b/test/llvm_test_code/openssl/secure_heap/CMakeLists.txt @@ -2,5 +2,5 @@ file(GLOB openssl_files *.c *.cpp) foreach(TEST_SRC ${openssl_files}) get_filename_component(TEST_SRC_FILE ${TEST_SRC} NAME) - generate_ll_file(FILE ${TEST_SRC_FILE}) + generate_ll_file(FILE ${TEST_SRC_FILE} DEBUG) endforeach(TEST_SRC) diff --git a/test/llvm_test_code/openssl/secure_memory/CMakeLists.txt b/test/llvm_test_code/openssl/secure_memory/CMakeLists.txt index 7565aeef5e..39770d7dbf 100644 --- a/test/llvm_test_code/openssl/secure_memory/CMakeLists.txt +++ b/test/llvm_test_code/openssl/secure_memory/CMakeLists.txt @@ -2,5 +2,5 @@ file(GLOB openssl_files *.c *.cpp) foreach(TEST_SRC ${openssl_files}) get_filename_component(TEST_SRC_FILE ${TEST_SRC} NAME) - generate_ll_file(FILE ${TEST_SRC_FILE}) + generate_ll_file(FILE ${TEST_SRC_FILE} DEBUG) endforeach(TEST_SRC) diff --git a/test/llvm_test_code/taint_analysis/CMakeLists.txt b/test/llvm_test_code/taint_analysis/CMakeLists.txt index cbefe33821..1c3ff627f7 100644 --- a/test/llvm_test_code/taint_analysis/CMakeLists.txt +++ b/test/llvm_test_code/taint_analysis/CMakeLists.txt @@ -38,7 +38,7 @@ set(NoMem2regSources ) foreach(TEST_SRC ${NoMem2regSources}) - generate_ll_file(FILE ${TEST_SRC}) + generate_ll_file(FILE ${TEST_SRC} DEBUG) endforeach(TEST_SRC) add_subdirectory(dummy_source_sink) diff --git a/test/llvm_test_code/typestate_analysis_fileio/CMakeLists.txt b/test/llvm_test_code/typestate_analysis_fileio/CMakeLists.txt index 9da0ecdc68..ef2be35b66 100644 --- a/test/llvm_test_code/typestate_analysis_fileio/CMakeLists.txt +++ b/test/llvm_test_code/typestate_analysis_fileio/CMakeLists.txt @@ -1,10 +1,5 @@ file(GLOB typestate_files *.c *.cpp) -foreach(TEST_SRC ${typestate_files}) - get_filename_component(TEST_SRC_FILE ${TEST_SRC} NAME) - generate_ll_file(FILE ${TEST_SRC_FILE}) -endforeach(TEST_SRC) - foreach(TEST_SRC ${typestate_files}) get_filename_component(TEST_SRC_FILE ${TEST_SRC} NAME) generate_ll_file(FILE ${TEST_SRC_FILE} DEBUG) diff --git a/test/llvm_test_code/xtaint/CMakeLists.txt b/test/llvm_test_code/xtaint/CMakeLists.txt index ad1fa8702f..c3f8041798 100644 --- a/test/llvm_test_code/xtaint/CMakeLists.txt +++ b/test/llvm_test_code/xtaint/CMakeLists.txt @@ -1,5 +1,6 @@ -set(XTAINT_SOURCES +set(XTAINT_DBG_SOURCES xtaint01.cpp + xtaint01_json.cpp # xtaint01_json.cpp xtaint02.cpp xtaint03.cpp @@ -24,14 +25,6 @@ set(XTAINT_SOURCES xtaint21.cpp ) -set(XTAINT_DBG_SOURCES - xtaint01_json.cpp -) - -foreach(TEST_SRC ${XTAINT_SOURCES}) - generate_ll_file(FILE ${TEST_SRC}) -endforeach(TEST_SRC) - foreach(TEST_SRC ${XTAINT_DBG_SOURCES}) generate_ll_file(FILE ${TEST_SRC} DEBUG) endforeach(TEST_SRC) diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp index 51af9f3058..3237404bbf 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp @@ -11,35 +11,26 @@ #include "phasar/DataFlow/IfdsIde/Solver/IDESolver.h" #include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" -#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/HelperAnalyses.h" -#include "phasar/PhasarLLVM/Passes/ValueAnnotationPass.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h" #include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" #include "phasar/PhasarLLVM/TaintConfig/LLVMTaintConfig.h" -#include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" -#include "phasar/Utils/DebugOutput.h" #include "phasar/Utils/Utilities.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Demangle/Demangle.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/InstrTypes.h" #include "llvm/IR/Instructions.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/Casting.h" +#include "SrcCodeLocationEntry.h" #include "TestConfig.h" #include "gtest/gtest.h" -#include "nlohmann/json.hpp" #include -#include #include #include -using namespace std; using namespace psr; -using json = nlohmann::json; +using namespace psr::unittest; using CallBackPairTy = std::pair::config_callback_t, IDEExtendedTaintAnalysis<>::config_callback_t>; @@ -51,14 +42,14 @@ class IDETaintAnalysisTest : public ::testing::Test { static constexpr auto PathToLLFiles = PHASAR_BUILD_SUBFOLDER("xtaint/"); const std::vector EntryPoints = {"main"}; - IDETaintAnalysisTest() = default; - ~IDETaintAnalysisTest() override = default; + using TaintSetT = std::set; void doAnalysis( - const llvm::Twine &IRFile, const map> &GroundTruth, + const llvm::Twine &IRFilePath, + const std::map &GroundTruth, std::variant Config, bool DumpResults = true) { - HelperAnalyses HA(IRFile, EntryPoints); + HelperAnalyses HA(PathToLLFiles + IRFilePath, EntryPoints); auto TC = std::visit(Overloaded{[&](std::monostate) { @@ -93,34 +84,26 @@ class IDETaintAnalysisTest : public ::testing::Test { compareResults(TaintProblem, Solver, GroundTruth); } - void SetUp() override { ValueAnnotationPass::resetValueID(); } + void + compareResults(IDEExtendedTaintAnalysis<> &TaintProblem, + IDESolver_P> &Solver, + const std::map &GroundTruth) { + auto GroundTruthEntries = convertTestingLocationSetMapInIR( + GroundTruth, *TaintProblem.getProjectIRDB()); - void TearDown() override {} + std::map> + FoundLeaks; - void compareResults(IDEExtendedTaintAnalysis<> &TaintProblem, - IDESolver_P> &Solver, - const map> &GroundTruth) { - - map> FoundLeaks; - for (const auto &Leak : + for (const auto &[LeakInst, LeakVals] : TaintProblem.getAllLeaks(Solver.getSolverResults())) { - llvm::errs() << "Leak: " << PrettyPrinter{Leak} << '\n'; - int SinkId = stoi(getMetaDataID(Leak.first)); - set LeakedValueIds; - for (const auto &LV : Leak.second) { - LeakedValueIds.insert(getMetaDataID(LV)); - } - FoundLeaks.emplace(SinkId, LeakedValueIds); + FoundLeaks[LeakInst].insert(LeakVals.begin(), LeakVals.end()); } - EXPECT_EQ(FoundLeaks, GroundTruth); + + EXPECT_EQ(FoundLeaks, GroundTruthEntries); } }; // Test Fixture TEST_F(IDETaintAnalysisTest, XTaint01_Json) { - map> Gt; - - Gt[7] = {"6"}; - TaintConfigData Config; FunctionData FuncDataMain; @@ -134,192 +117,184 @@ TEST_F(IDETaintAnalysisTest, XTaint01_Json) { Config.Functions.push_back(std::move(FuncDataMain)); Config.Functions.push_back(std::move(FuncDataPrint)); - doAnalysis({PathToLLFiles + "xtaint01_json_cpp_dbg.ll"}, Gt, &Config); + std::map GroundTruth = {{ + LineColFun{8, 3, "main"}, + {LineColFunOp{8, 9, "main", llvm::Instruction::Load}}, + }}; + + doAnalysis("xtaint01_json_cpp_dbg.ll", GroundTruth, &Config); } TEST_F(IDETaintAnalysisTest, XTaint01) { - map> Gt; - - Gt[13] = {"12"}; + std::map GroundTruth = { + {LineColFun{8, 3, "main"}, + {LineColFunOp{8, 9, "main", llvm::Instruction::Load}}}}; - doAnalysis({PathToLLFiles + "xtaint01_cpp.ll"}, Gt, std::monostate{}); + doAnalysis("xtaint01_cpp_dbg.ll", GroundTruth, std::monostate{}); } TEST_F(IDETaintAnalysisTest, XTaint02) { - map> Gt; - - Gt[18] = {"17"}; + std::map GroundTruth = { + {LineColFun{9, 3, "main"}, + {LineColFunOp{9, 9, "main", llvm::Instruction::Load}}}}; - doAnalysis({PathToLLFiles + "xtaint02_cpp.ll"}, Gt, std::monostate{}, true); + doAnalysis("xtaint02_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } -TEST_F(IDETaintAnalysisTest, XTaint03) { - map> Gt; - Gt[21] = {"20"}; +TEST_F(IDETaintAnalysisTest, XTaint03) { + std::map GroundTruth = { + {LineColFun{10, 3, "main"}, + {LineColFunOp{10, 9, "main", llvm::Instruction::Load}}}}; - doAnalysis({PathToLLFiles + "xtaint03_cpp.ll"}, Gt, std::monostate{}); + doAnalysis("xtaint03_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint04) { - map> Gt; + auto Call = LineColFun{6, 3, "_Z3barPi"}; - Gt[16] = {"15"}; + std::map GroundTruth = { + {Call, {OperandOf{0, Call}}}}; - doAnalysis({PathToLLFiles + "xtaint04_cpp.ll"}, Gt, std::monostate{}); + doAnalysis("xtaint04_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } // XTaint05 is similar to 06, but even harder TEST_F(IDETaintAnalysisTest, XTaint06) { - map> Gt; - - // no leaks expected + std::map GroundTruth = { + // no leaks expected + }; - doAnalysis({PathToLLFiles + "xtaint06_cpp.ll"}, Gt, std::monostate{}); + doAnalysis("xtaint06_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } -/// In the new TaintConfig specifying source/sink/sanitizer properties for extra -/// parameters of C-style variadic functions is not (yet?) supported. So, the -/// tests XTaint07 and XTaint08 are disabled. +/// In the new TaintConfig specifying source/sink/sanitizer properties for +/// extra parameters of C-style variadic functions is not (yet?) supported. +/// So, the tests XTaint07 and XTaint08 are disabled. TEST_F(IDETaintAnalysisTest, DISABLED_XTaint07) { - map> Gt; + std::map GroundTruth = { + {LineColFun{10, 0, "main"}, + {LineColFunOp{10, 18, "main", llvm::Instruction::Load}}}}; - Gt[21] = {"20"}; - - doAnalysis({PathToLLFiles + "xtaint07_cpp.ll"}, Gt, std::monostate{}); + doAnalysis("xtaint07_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, DISABLED_XTaint08) { - map> Gt; - - Gt[24] = {"23"}; + std::map GroundTruth = { + {LineColFun{20, 3, "main"}, + {LineColFunOp{20, 18, "main", llvm::Instruction::Load}}}}; - doAnalysis({PathToLLFiles + "xtaint08_cpp.ll"}, Gt, std::monostate{}); + doAnalysis("xtaint08_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint09_1) { - map> Gt; - - Gt[25] = {"24"}; + std::map GroundTruth = { + {LineColFun{14, 3, "main"}, {LineColFun{14, 8, "main"}}}}; - doAnalysis({PathToLLFiles + "xtaint09_1_cpp.ll"}, Gt, std::monostate{}); + doAnalysis("xtaint09_1_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint09) { - map> Gt; + auto SinkCall = LineColFun{16, 3, "main"}; + std::map GroundTruth = { + {SinkCall, {OperandOf{0, SinkCall}}}}; - Gt[24] = {"23"}; - - doAnalysis({PathToLLFiles + "xtaint09_cpp.ll"}, Gt, std::monostate{}); + doAnalysis("xtaint09_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, DISABLED_XTaint10) { - map> Gt; - - // undefined behaviour: sometimes this test fails, but most of the time - // it passes. It only fails when executed together with other tests. It - // never failed (so far) for ./IDEExtendedTaintAnalysisTest - // --Gtest_filter=*XTaint10 - // UPDATE: With the fixed k-limiting, this test - // almost always fails due to aliasing issues, so disable it. - // TODO: Also update the Gt - Gt[33] = {"32"}; - - doAnalysis({PathToLLFiles + "xtaint10_cpp.ll"}, Gt, std::monostate{}); + std::map GroundTruth = { + // no leaks expected + }; + + doAnalysis("xtaint10_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, DISABLED_XTaint11) { - map> Gt; - - // no leaks expected; actually finds "27" at 28 + std::map GroundTruth = { + // no leaks expected + }; - doAnalysis({PathToLLFiles + "xtaint11_cpp.ll"}, Gt, std::monostate{}); + doAnalysis("xtaint11_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint12) { - map> Gt; + std::map GroundTruth = { + {LineColFun{19, 3, "main"}, {LineColFun{19, 8, "main"}}}}; - // We sanitize an alias - since we don't have must-alias relations, we cannot - // kill aliases at all - Gt[28] = {"27"}; - - doAnalysis({PathToLLFiles + "xtaint12_cpp.ll"}, Gt, std::monostate{}); + doAnalysis("xtaint12_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint13) { - map> Gt; - - Gt[30] = {"29"}; + std::map GroundTruth = { + {LineColFun{17, 3, "main"}, {LineColFun{17, 8, "main"}}}}; - doAnalysis({PathToLLFiles + "xtaint13_cpp.ll"}, Gt, std::monostate{}); + doAnalysis("xtaint13_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint14) { - map> Gt; - - Gt[33] = {"32"}; + std::map GroundTruth = { + {LineColFun{24, 3, "main"}, {LineColFun{24, 8, "main"}}}}; - doAnalysis({PathToLLFiles + "xtaint14_cpp.ll"}, Gt, std::monostate{}); + doAnalysis("xtaint14_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } /// The TaintConfig fails to get all call-sites of Source::get, because it has /// no CallGraph information TEST_F(IDETaintAnalysisTest, DISABLED_XTaint15) { - map> Gt; + std::map GroundTruth = { + // no leaks expected + }; - Gt[47] = {"46"}; - - doAnalysis({PathToLLFiles + "xtaint15_cpp.ll"}, Gt, std::monostate{}); + doAnalysis("xtaint15_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint16) { - map> Gt; - - Gt[24] = {"23"}; + std::map GroundTruth = { + {LineColFun{13, 3, "main"}, {LineColFun{13, 8, "main"}}}}; - doAnalysis({PathToLLFiles + "xtaint16_cpp.ll"}, Gt, std::monostate{}); + doAnalysis("xtaint16_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint17) { - map> Gt; - - Gt[27] = {"26"}; + std::map GroundTruth = { + {LineColFun{17, 3, "main"}, {LineColFun{17, 8, "main"}}}}; - doAnalysis({PathToLLFiles + "xtaint17_cpp.ll"}, Gt, std::monostate{}); + doAnalysis("xtaint17_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint18) { - map> Gt; + std::map GroundTruth = { + // no leaks expected + }; - // Gt[26] = {"25"}; - - doAnalysis({PathToLLFiles + "xtaint18_cpp.ll"}, Gt, std::monostate{}); + doAnalysis("xtaint18_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } PHASAR_SKIP_TEST(TEST_F(IDETaintAnalysisTest, XTaint19) { // Is now the same as XTaint17 GTEST_SKIP(); - map> Gt; - Gt[22] = {"21"}; + std::map GroundTruth = { + {LineColFun{17, 3, "main"}, {LineColFun{17, 8, "main"}}}}; - doAnalysis({PathToLLFiles + "xtaint19_cpp.ll"}, Gt, std::monostate{}); + doAnalysis("xtaint19_cpp_dbg.ll", GroundTruth, std::monostate{}, true); }) TEST_F(IDETaintAnalysisTest, XTaint20) { - map> Gt; - - Gt[22] = {"14"}; - Gt[24] = {"23"}; + std::map GroundTruth = { + {LineColFun{12, 3, "main"}, {LineColFun{6, 7, "main"}}}, + {LineColFun{13, 3, "main"}, {LineColFun{13, 8, "main"}}}, + }; - doAnalysis({PathToLLFiles + "xtaint20_cpp.ll"}, Gt, std::monostate{}); + doAnalysis("xtaint20_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint21) { - map> Gt; - - Gt[10] = {"2"}; - Gt[12] = {"11"}; + std::map GroundTruth = { + {LineColFun{17, 3, "main"}, {LineColFun{11, 7, "main"}}}, + {LineColFun{18, 3, "main"}, {LineColFun{18, 8, "main"}}}, + }; IDEExtendedTaintAnalysis<>::config_callback_t SourceCB = [](const llvm::Instruction *Inst) { @@ -343,7 +318,7 @@ TEST_F(IDETaintAnalysisTest, XTaint21) { return Ret; }; - doAnalysis({PathToLLFiles + "xtaint21_cpp.ll"}, Gt, + doAnalysis("xtaint21_cpp_dbg.ll", GroundTruth, CallBackPairTy{std::move(SourceCB), std::move(SinkCB)}); } diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEFeatureTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEFeatureTaintAnalysisTest.cpp index 243cb2d6a7..2b98d117b1 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEFeatureTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEFeatureTaintAnalysisTest.cpp @@ -1,30 +1,35 @@ #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEFeatureTaintAnalysis.h" -#include "phasar/Config/Configuration.h" #include "phasar/DataFlow/IfdsIde/Solver/IDESolver.h" #include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" #include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" -#include "phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMSolverResults.h" +#include "phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMSolverResults.h" // for resultsAtInLLVMSSA #include "phasar/PhasarLLVM/HelperAnalyses.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h" #include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "phasar/Utils/BitVectorSet.h" -#include "phasar/Utils/Logger.h" +#include "phasar/Utils/Fn.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/Twine.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instruction.h" +#include "SrcCodeLocationEntry.h" #include "TestConfig.h" #include "gtest/gtest.h" +#include + namespace { using namespace psr; +using namespace psr::unittest; + +using TaintSetT = std::set; -static std::string printSet(const std::set &EdgeFact) { +static std::string printSet(const TaintSetT &EdgeFact) { std::string Ret; llvm::raw_string_ostream ROS(Ret); llvm::interleaveComma(EdgeFact, ROS << '<'); @@ -38,9 +43,10 @@ class IDEFeatureTaintAnalysisTest : public ::testing::Test { static constexpr auto PathToLlFiles = PHASAR_BUILD_SUBFOLDER("inst_interaction/"); + using VarNameT = std::variant; // Function - Line Nr - Variable - Values using IIACompactResult_t = - std::tuple>; + std::tuple>; std::optional HA; LLVMProjectIRDB *IRDB{}; @@ -50,17 +56,52 @@ class IDEFeatureTaintAnalysisTest : public ::testing::Test { HA.emplace(PathToLlFiles + LlvmFilePath, EntryPoints, HelperAnalysisConfig{}.withCGType(CallGraphAnalysisType::CHA)); IRDB = &HA->getProjectIRDB(); + } - for (const auto &Glob : IRDB->getModule()->globals()) { - BitVectorSet BV; - BV.insert(getMetaDataID(&Glob)); - } + [[nodiscard]] bool matchesVar(const llvm::Value *Fact, + const VarNameT &VarName) { + return std::visit( + psr::Overloaded{ + [&](const std::string &Name) { + if (!llvm::isa(Fact) && + !llvm::isa(Fact)) { + return false; + } + auto FactName = psr::getVarNameFromIR(Fact); + return FactName == Name; + }, + [&](RetVal R) { + return llvm::any_of(Fact->users(), [R](const auto *V) { + const auto *Ret = llvm::dyn_cast(V); + return Ret && Ret->getFunction()->getName() == R.InFunction; + }); + }, + }, + VarName); + } + [[nodiscard]] std::string printVar(const VarNameT &VarName) { + return std::visit(psr::Overloaded{ + [](const std::string &Name) { return Name; }, + [](RetVal R) { return R.str(); }, + }, + VarName); + } - // Initialze IDs - for (const auto *Inst : IRDB->getAllInstructions()) { - BitVectorSet BV; - BV.insert(getMetaDataID(Inst)); + static TaintSetT generateTaintsAtInst(const llvm::Instruction *Inst) { + TaintSetT Labels; + auto [Line, Col] = getLineAndColFromIR(Inst); + if (Col == 0 && llvm::isa(Inst)) { + std::tie(Line, Col) = getLineAndColFromIR( + Inst->getOperand(llvm::StoreInst::getPointerOperandIndex())); + } + if (Line != 0) { + Labels.insert(LineColFun{ + Line, + Col, + Inst->getFunction()->getName(), + }); } + return Labels; } void @@ -70,27 +111,16 @@ class IDEFeatureTaintAnalysisTest : public ::testing::Test { bool PrintDump = false) { initializeIR(LlvmFilePath, EntryPoints); - // IDEInstInteractionAnalysisT IIAProblem(IRDB, &ICFG, - // &PT, - // EntryPoints); - // use Phasar's instruction ids as testing labels auto Generator = [](std::variant - Current) -> std::set { + Current) -> TaintSetT { return std::visit( - [](const auto *InstOrGlob) -> std::set { - std::set Labels; - if (InstOrGlob->hasMetadata()) { - std::string Label = - llvm::cast( - InstOrGlob->getMetadata(PhasarConfig::MetaDataKind()) - ->getOperand(0)) - ->getString() - .str(); - Labels.insert(Label); - } - return Labels; + psr::Overloaded{ + [](const llvm::GlobalVariable *Glob) { + return TaintSetT{GlobalVar{Glob->getName()}}; + }, + fn<&generateTaintsAtInst>, }, Current); }; @@ -98,44 +128,29 @@ class IDEFeatureTaintAnalysisTest : public ::testing::Test { auto IIAProblem = createAnalysisProblem( *HA, EntryPoints, Generator); - // if (PrintDump) { - // psr::Logger::initializeStderrLogger(SeverityLevel::DEBUG); - // } - IDESolver IIASolver(IIAProblem, &HA->getICFG()); IIASolver.solve(); - // if (PrintDump) { - // // IRDB->emitPreprocessedIR(llvm::outs()); - // IIASolver.dumpResults(); - // llvm::errs() - // << "\n======================================================\n"; - // printDump(HA->getProjectIRDB(), IIASolver.getSolverResults()); - // } + // do the comparison - for (const auto &[FunName, SrcLine, VarName, LatticeVal] : GroundTruth) { - const auto *Fun = IRDB->getFunctionDefinition(FunName); - const auto *IRLine = getNthInstruction(Fun, SrcLine); - auto ResultMap = IIASolver.resultsAt(IRLine); - assert(IRLine && "Could not retrieve IR line!"); + for (const auto &[InstLoc, VarName, ExpectedVal] : GroundTruth) { + const auto *IRLoc = testingLocInIR(InstLoc, *IRDB); + ASSERT_TRUE(IRLoc) << "Could not retrieve IR Loc: " << InstLoc.str(); + ASSERT_TRUE(llvm::isa(IRLoc)); + auto ResultMap = + IIASolver.resultsAt(llvm::cast(IRLoc)); bool FactFound = false; - for (auto &[Fact, Value] : ResultMap) { - std::string FactStr; - llvm::raw_string_ostream RSO(FactStr); - RSO << *Fact; - llvm::StringRef FactRef(FactStr); - if (FactRef.ltrim().startswith("%" + VarName + " ") || - FactRef.ltrim().startswith("@" + VarName + " ")) { - PHASAR_LOG_LEVEL(DFADEBUG, "Checking variable: " << FactStr); - EXPECT_EQ(LatticeVal, Value.toSet()) - << "Value do not match for Variable '" << VarName - << "': Expected " << printSet(LatticeVal) - << "; got: " << LToString(Value.toBVSet()); + for (auto &[Fact, ComputedVal] : ResultMap) { + if (matchesVar(Fact, VarName)) { + EXPECT_EQ(ExpectedVal, ComputedVal.toSet()) + << "Unexpected taint-set at " << InstLoc << " for variable '" + << printVar(VarName) << "' (" << llvmIRToString(Fact) << ")"; FactFound = true; } } - EXPECT_TRUE(FactFound) << "Variable '" << VarName << "' missing at '" - << llvmIRToString(IRLine) << "'."; + EXPECT_TRUE(FactFound) + << "Variable '" << printVar(VarName) << "' missing at '" + << llvmIRToString(IRLoc) << "'."; } if (PrintDump || HasFailure()) { @@ -146,10 +161,12 @@ class IDEFeatureTaintAnalysisTest : public ::testing::Test { } } - void TearDown() override {} + void TearDown() override { + BitVectorSet::clearPosition(); + } // See vara::PhasarTaintAnalysis::taintsForInst - [[nodiscard]] inline std::set + [[nodiscard]] inline TaintSetT taintsForInst(const llvm::Instruction *Inst, SolverResults SR) { @@ -162,27 +179,28 @@ class IDEFeatureTaintAnalysisTest : public ::testing::Test { return {}; } - std::set AggregatedTaints; + TaintSetT AggregatedTaints; - if (Inst->getType()->isVoidTy()) { // For void types, we need to look what - // taints flow into the inst + if (Inst->getType()->isVoidTy()) { + // For void types, we need to look what + // taints flow into the inst - // auto Results = SR.resultsAt(Inst); assert(Inst->getNumOperands() >= 1 && "Found case without first operand."); AggregatedTaints = - SR.resultAt(Inst, Inst->getOperand(0)).toSet(); + SR.resultAt(Inst, Inst->getOperand(0)).toSet(); } else { auto Results = SR.resultsAtInLLVMSSA(Inst); auto SearchPosTaints = Results.find(Inst); if (SearchPosTaints != Results.end()) { - AggregatedTaints = SearchPosTaints->second.toSet(); + AggregatedTaints = SearchPosTaints->second.toSet(); } } // additionalStaticTaints - AggregatedTaints.insert(getMetaDataID(Inst)); + auto AdditionalTaints = generateTaintsAtInst(Inst); + AggregatedTaints.insert(AdditionalTaints.begin(), AdditionalTaints.end()); return AggregatedTaints; } @@ -207,343 +225,726 @@ class IDEFeatureTaintAnalysisTest : public ::testing::Test { TEST_F(IDEFeatureTaintAnalysisTest, HandleBasicTest_01) { std::set GroundTruth; - GroundTruth.emplace("main", 9, "i", std::set{"4"}); - GroundTruth.emplace("main", 9, "j", - std::set{"4", "5", "6", "7"}); - GroundTruth.emplace("main", 9, "retval", std::set{"3"}); - doAnalysisAndCompareResults("basic_01_cpp.ll", {"main"}, GroundTruth, false); + auto Main9 = LineColFun{4, 3, "main"}; + GroundTruth.emplace(Main9, "i", TaintSetT{LineColFun{2, 7, "main"}}); + GroundTruth.emplace(Main9, "j", + TaintSetT{ + LineColFun{2, 7, "main"}, + LineColFun{3, 11, "main"}, + LineColFun{3, 13, "main"}, + LineColFun{3, 7, "main"}, + }); + + doAnalysisAndCompareResults("basic_01_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEFeatureTaintAnalysisTest, HandleBasicTest_02) { std::set GroundTruth; - GroundTruth.emplace("main", 24, "retval", std::set{"6"}); - GroundTruth.emplace("main", 24, "argc.addr", std::set{"7"}); - GroundTruth.emplace("main", 24, "argv.addr", std::set{"8"}); - GroundTruth.emplace("main", 24, "i", std::set{"16", "18"}); - GroundTruth.emplace("main", 24, "j", - std::set{"9", "10", "11", "12"}); - GroundTruth.emplace("main", 24, "k", - std::set{"21", "16", "18", "20"}); - doAnalysisAndCompareResults("basic_02_cpp.ll", {"main"}, GroundTruth, false); + auto Main24 = LineColFun{10, 3, "main"}; + + GroundTruth.emplace(Main24, "argc", TaintSetT{LineColFun{1, 14, "main"}}); + GroundTruth.emplace(Main24, "argv", TaintSetT{LineColFun{1, 27, "main"}}); + GroundTruth.emplace(Main24, "i", + TaintSetT{ + LineColFun{5, 7, "main"}, + LineColFun{7, 7, "main"}, + }); + GroundTruth.emplace(Main24, "j", + TaintSetT{ + LineColFun{2, 7, "main"}, + LineColFun{3, 11, "main"}, + LineColFun{3, 13, "main"}, + LineColFun{3, 7, "main"}, + }); + GroundTruth.emplace(Main24, "k", + TaintSetT{ + LineColFun{5, 7, "main"}, + LineColFun{7, 7, "main"}, + LineColFun{9, 11, "main"}, + LineColFun{9, 7, "main"}, + }); + + doAnalysisAndCompareResults("basic_02_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEFeatureTaintAnalysisTest, HandleBasicTest_03) { std::set GroundTruth; - GroundTruth.emplace("main", 20, "retval", std::set{"3"}); - GroundTruth.emplace("main", 20, "i", - std::set{"4", "10", "11", "12"}); - GroundTruth.emplace("main", 20, "x", - std::set{"5", "14", "15", "16"}); - doAnalysisAndCompareResults("basic_03_cpp.ll", {"main"}, GroundTruth, false); + + auto Main20 = LineColFun{6, 3, "main"}; + + GroundTruth.emplace(Main20, "i", + TaintSetT{ + LineColFun{2, 7, "main"}, + LineColFun{4, 5, "main"}, + }); + GroundTruth.emplace(Main20, "x", + TaintSetT{ + LineColFun{3, 12, "main"}, + LineColFun{3, 28, "main"}, + }); + + doAnalysisAndCompareResults("basic_03_cpp_dbg.ll", {"main"}, GroundTruth, + false); } -PHASAR_SKIP_TEST(TEST_F(IDEFeatureTaintAnalysisTest, HandleBasicTest_04) { - // If we use libcxx this won't work since internal implementation is different +TEST_F(IDEFeatureTaintAnalysisTest, HandleBasicTest_04) { + LIBCPP_GTEST_SKIP; std::set GroundTruth; - GroundTruth.emplace("main", 23, "retval", std::set{"7"}); - GroundTruth.emplace("main", 23, "argc.addr", std::set{"8"}); - GroundTruth.emplace("main", 23, "argv.addr", std::set{"9"}); - GroundTruth.emplace("main", 23, "i", std::set{"10"}); - GroundTruth.emplace("main", 23, "j", - std::set{"10", "11", "12", "13"}); - GroundTruth.emplace( - "main", 23, "k", - std::set{"10", "11", "12", "13", "14", "18", "19"}); - doAnalysisAndCompareResults("basic_04_cpp.ll", {"main"}, GroundTruth, false); -}) + auto Main23 = LineColFun{11, 3, "main"}; + + GroundTruth.emplace(Main23, "argc", + TaintSetT{ + LineColFun{3, 14, "main"}, + }); + GroundTruth.emplace(Main23, "argv", + TaintSetT{ + LineColFun{3, 27, "main"}, + }); + GroundTruth.emplace(Main23, "i", + TaintSetT{ + LineColFun{4, 7, "main"}, + }); + GroundTruth.emplace(Main23, "j", + TaintSetT{ + LineColFun{4, 7, "main"}, + LineColFun{5, 11, "main"}, + LineColFun{5, 13, "main"}, + LineColFun{5, 7, "main"}, + }); + GroundTruth.emplace(Main23, "k", + TaintSetT{ + LineColFun{4, 7, "main"}, + LineColFun{5, 11, "main"}, + LineColFun{5, 13, "main"}, + LineColFun{5, 7, "main"}, + LineColFun{6, 7, "main"}, + LineColFun{8, 9, "main"}, + LineColFun{8, 7, "main"}, + }); + + doAnalysisAndCompareResults("basic_04_cpp_dbg.ll", {"main"}, GroundTruth, + false); +} TEST_F(IDEFeatureTaintAnalysisTest, HandleBasicTest_05) { std::set GroundTruth; - GroundTruth.emplace("main", 11, "i", std::set{"5", "7"}); - GroundTruth.emplace("main", 11, "retval", std::set{"2"}); - doAnalysisAndCompareResults("basic_05_cpp.ll", {"main"}, GroundTruth, false); + auto Main11 = LineColFun{10, 3, "main"}; + GroundTruth.emplace(Main11, "i", + TaintSetT{ + LineColFun{6, 7, "main"}, + LineColFun{8, 7, "main"}, + }); + + doAnalysisAndCompareResults("basic_05_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEFeatureTaintAnalysisTest, HandleBasicTest_06) { std::set GroundTruth; - GroundTruth.emplace("main", 19, "retval", std::set{"5"}); - GroundTruth.emplace("main", 19, "i", std::set{"15", "6", "13"}); - GroundTruth.emplace("main", 19, "j", std::set{"15", "6", "13"}); - GroundTruth.emplace("main", 19, "k", std::set{"6"}); - GroundTruth.emplace("main", 19, "p", - std::set{"1", "2", "9", "11"}); - doAnalysisAndCompareResults("basic_06_cpp.ll", {"main"}, GroundTruth, true); + auto Main19 = LineColFun{14, 3, "main"}; + + GroundTruth.emplace(Main19, "i", + TaintSetT{ + LineColFun{6, 7, "main"}, + LineColFun{13, 8, "main"}, + LineColFun{13, 6, "main"}, + }); + GroundTruth.emplace(Main19, "j", + TaintSetT{ + LineColFun{6, 7, "main"}, + LineColFun{13, 8, "main"}, + LineColFun{13, 6, "main"}, + }); + GroundTruth.emplace(Main19, "k", + TaintSetT{ + LineColFun{6, 7, "main"}, + }); + GroundTruth.emplace(Main19, "p", + TaintSetT{ + LineColFun{4, 7, "main"}, + LineColFun{5, 7, "main"}, + LineColFun{9, 7, "main"}, + LineColFun{11, 7, "main"}, + }); + + doAnalysisAndCompareResults("basic_06_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEFeatureTaintAnalysisTest, HandleBasicTest_07) { std::set GroundTruth; - GroundTruth.emplace("main", 15, "retval", std::set{"5"}); - GroundTruth.emplace("main", 15, "argc.addr", std::set{"6"}); - GroundTruth.emplace("main", 15, "argv.addr", std::set{"7"}); - GroundTruth.emplace("main", 15, "i", std::set{"12"}); - GroundTruth.emplace("main", 15, "j", - std::set{"8", "9", "10", "11"}); - doAnalysisAndCompareResults("basic_07_cpp.ll", {"main"}, GroundTruth, false); + auto Main15 = LineColFun{5, 3, "main"}; + + GroundTruth.emplace(Main15, "argc", + TaintSetT{ + LineColFun{1, 14, "main"}, + }); + GroundTruth.emplace(Main15, "argv", + TaintSetT{ + LineColFun{1, 27, "main"}, + }); + // strong update on i + GroundTruth.emplace(Main15, "i", + TaintSetT{ + LineColFun{4, 5, "main"}, + }); + GroundTruth.emplace(Main15, "j", + TaintSetT{ + LineColFun{2, 7, "main"}, + LineColFun{3, 11, "main"}, + LineColFun{3, 13, "main"}, + LineColFun{3, 7, "main"}, + }); + + doAnalysisAndCompareResults("basic_07_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEFeatureTaintAnalysisTest, HandleBasicTest_08) { std::set GroundTruth; - GroundTruth.emplace("main", 12, "retval", std::set{"2"}); - GroundTruth.emplace("main", 12, "i", std::set{"9"}); - doAnalysisAndCompareResults("basic_08_cpp.ll", {"main"}, GroundTruth, false); + auto Main12 = LineColFun{11, 3, "main"}; + + // strong update on i + GroundTruth.emplace(Main12, "i", + TaintSetT{ + LineColFun{10, 5, "main"}, + }); + + doAnalysisAndCompareResults("basic_08_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEFeatureTaintAnalysisTest, HandleBasicTest_09) { std::set GroundTruth; - GroundTruth.emplace("main", 10, "i", std::set{"4"}); - GroundTruth.emplace("main", 10, "j", std::set{"4", "6", "7"}); - GroundTruth.emplace("main", 10, "retval", std::set{"3"}); - doAnalysisAndCompareResults("basic_09_cpp.ll", {"main"}, GroundTruth, false); + auto Main10 = LineColFun{6, 3, "main"}; + + GroundTruth.emplace(Main10, "i", + TaintSetT{ + LineColFun{3, 7, "main"}, + }); + GroundTruth.emplace(Main10, "j", + TaintSetT{ + LineColFun{3, 7, "main"}, + LineColFun{5, 7, "main"}, + LineColFun{5, 5, "main"}, + }); + + doAnalysisAndCompareResults("basic_09_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEFeatureTaintAnalysisTest, HandleBasicTest_10) { std::set GroundTruth; - GroundTruth.emplace("main", 6, "i", std::set{"3"}); - GroundTruth.emplace("main", 6, "retval", std::set{"2"}); - doAnalysisAndCompareResults("basic_10_cpp.ll", {"main"}, GroundTruth, false); + auto Main6 = LineColFun{4, 3, "main"}; + GroundTruth.emplace(Main6, "i", + TaintSetT{ + LineColFun{3, 7, "main"}, + }); + + doAnalysisAndCompareResults("basic_10_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEFeatureTaintAnalysisTest, HandleBasicTest_11) { std::set GroundTruth; - GroundTruth.emplace("main", 20, "FeatureSelector", - std::set{"5", "7", "8"}); - GroundTruth.emplace("main", 20, "retval", std::set{"11", "16"}); - doAnalysisAndCompareResults("basic_11_cpp.ll", {"main"}, GroundTruth, false); + auto Main20 = RetStmt{"main"}; + + GroundTruth.emplace(Main20, "FeatureSelector", + TaintSetT{ + LineColFun{3, 14, "main"}, + LineColFun{4, 25, "main"}, + LineColFun{4, 7, "main"}, + }); + + GroundTruth.emplace(Main20, RetVal{"main"}, + TaintSetT{ + LineColFun{7, 5, "main"}, + LineColFun{15, 3, "main"}, + LineColFun{16, 1, "main"}, + }); + + doAnalysisAndCompareResults("basic_11_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEFeatureTaintAnalysisTest, HandleCallTest_01) { std::set GroundTruth; - GroundTruth.emplace("main", 14, "retval", std::set{"8"}); - GroundTruth.emplace("main", 14, "i", std::set{"9"}); - GroundTruth.emplace("main", 14, "j", - std::set{"12", "9", "10", "11"}); - GroundTruth.emplace( - "main", 14, "k", - std::set{"15", "1", "2", "13", "14", "12", "9", "10", "11"}); - doAnalysisAndCompareResults("call_01_cpp.ll", {"main"}, GroundTruth, false); + auto Main14 = RetStmt{"main"}; + + GroundTruth.emplace(Main14, "i", + TaintSetT{ + LineColFun{4, 7, "main"}, + }); + GroundTruth.emplace(Main14, "j", + TaintSetT{ + LineColFun{4, 7, "main"}, + LineColFun{5, 11, "main"}, + LineColFun{5, 13, "main"}, + LineColFun{5, 7, "main"}, + }); + GroundTruth.emplace(Main14, "k", + TaintSetT{ + LineColFun{4, 7, "main"}, + LineColFun{5, 11, "main"}, + LineColFun{5, 13, "main"}, + LineColFun{5, 7, "main"}, + LineColFun{6, 7, "main"}, + LineColFun{6, 11, "main"}, + LineColFun{6, 14, "main"}, + LineColFun{1, 12, "_Z2idi"}, + LineColFun{1, 24, "_Z2idi"}, + }); + + doAnalysisAndCompareResults("call_01_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEFeatureTaintAnalysisTest, HandleCallTest_02) { std::set GroundTruth; - GroundTruth.emplace("main", 13, "retval", std::set{"12"}); - GroundTruth.emplace("main", 13, "i", std::set{"13"}); - GroundTruth.emplace("main", 13, "j", std::set{"14"}); - GroundTruth.emplace("main", 13, "k", - std::set{"4", "5", "15", "6", "3", "14", "2", - "13", "16", "17", "18"}); - doAnalysisAndCompareResults("call_02_cpp.ll", {"main"}, GroundTruth, false); + auto Main13 = RetStmt{"main"}; + + GroundTruth.emplace(Main13, "i", + TaintSetT{ + LineColFun{4, 7, "main"}, + }); + GroundTruth.emplace(Main13, "j", + TaintSetT{ + LineColFun{5, 7, "main"}, + }); + GroundTruth.emplace(Main13, "k", + TaintSetT{ + LineColFun{4, 7, "main"}, + LineColFun{5, 7, "main"}, + LineColFun{6, 15, "main"}, + LineColFun{6, 18, "main"}, + LineColFun{6, 11, "main"}, + LineColFun{6, 7, "main"}, + LineColFun{1, 13, "_Z3sumii"}, + LineColFun{1, 20, "_Z3sumii"}, + LineColFun{1, 32, "_Z3sumii"}, + LineColFun{1, 36, "_Z3sumii"}, + LineColFun{1, 34, "_Z3sumii"}, + }); + + doAnalysisAndCompareResults("call_02_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEFeatureTaintAnalysisTest, HandleCallTest_03) { std::set GroundTruth; - GroundTruth.emplace("main", 10, "retval", std::set{"20"}); - GroundTruth.emplace("main", 10, "i", std::set{"21"}); - GroundTruth.emplace("main", 10, "j", - std::set{"22", "23", "15", "6", "21", "2", - "13", "8", "9", "11", "12", "10", - "24"}); - doAnalysisAndCompareResults("call_03_cpp.ll", {"main"}, GroundTruth, false); + auto Main10 = RetStmt{"main"}; + + GroundTruth.emplace(Main10, "i", + TaintSetT{ + LineColFun{9, 7, "main"}, + }); + GroundTruth.emplace(Main10, "j", + TaintSetT{ + LineColFun{9, 7, "main"}, + LineColFun{10, 21, "main"}, + LineColFun{6, 1, "_Z9factorialj"}, + LineColFun{3, 5, "_Z9factorialj"}, + LineColFun{9, 7, "main"}, + LineColFun{1, 29, "_Z9factorialj"}, + LineColFun{5, 3, "_Z9factorialj"}, + LineColFun{5, 10, "_Z9factorialj"}, + LineColFun{5, 14, "_Z9factorialj"}, + LineColFun{5, 24, "_Z9factorialj"}, + LineColFun{5, 12, "_Z9factorialj"}, + LineColFun{5, 26, "_Z9factorialj"}, + LineColFun{10, 11, "main"}, + LineColFun{10, 7, "main"}, + }); + + doAnalysisAndCompareResults("call_03_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEFeatureTaintAnalysisTest, HandleCallTest_04) { std::set GroundTruth; - GroundTruth.emplace("main", 20, "retval", std::set{"33"}); - GroundTruth.emplace("main", 20, "i", std::set{"34"}); - GroundTruth.emplace("main", 20, "j", - std::set{"15", "6", "2", "13", "8", "9", - "11", "12", "10", "35", "36", "34", - "37"}); - GroundTruth.emplace("main", 20, "k", - std::set{"41", "19", "15", "6", "44", "2", - "13", "8", "45", "18", "9", "11", - "12", "10", "46", "24", "25", "35", - "36", "27", "23", "26", "38", "34", - "37", "42", "43", "39", "40"}); - doAnalysisAndCompareResults("call_04_cpp.ll", {"main"}, GroundTruth, false); + auto Main10 = RetStmt{"main"}; + + GroundTruth.emplace(Main10, "i", + TaintSetT{ + LineColFun{13, 7, "main"}, + }); + GroundTruth.emplace(Main10, "j", + TaintSetT{ + LineColFun{6, 1, "_Z9factorialj"}, + LineColFun{3, 5, "_Z9factorialj"}, + LineColFun{1, 29, "_Z9factorialj"}, + LineColFun{5, 3, "_Z9factorialj"}, + LineColFun{5, 10, "_Z9factorialj"}, + LineColFun{5, 14, "_Z9factorialj"}, + LineColFun{5, 24, "_Z9factorialj"}, + LineColFun{5, 12, "_Z9factorialj"}, + LineColFun{5, 26, "_Z9factorialj"}, + LineColFun{14, 21, "main"}, + LineColFun{13, 7, "main"}, + LineColFun{14, 7, "main"}, + LineColFun{14, 11, "main"}, + }); + GroundTruth.emplace(Main10, "k", + TaintSetT{ + LineColFun{16, 12, "main"}, + LineColFun{8, 24, "_Z2idi"}, + LineColFun{6, 1, "_Z9factorialj"}, + LineColFun{3, 5, "_Z9factorialj"}, + LineColFun{16, 5, "main"}, + LineColFun{1, 29, "_Z9factorialj"}, + LineColFun{5, 3, "_Z9factorialj"}, + LineColFun{5, 10, "_Z9factorialj"}, + LineColFun{5, 14, "_Z9factorialj"}, + LineColFun{16, 5, "main"}, + LineColFun{8, 12, "_Z2idi"}, + LineColFun{5, 24, "_Z9factorialj"}, + LineColFun{5, 12, "_Z9factorialj"}, + LineColFun{5, 26, "_Z9factorialj"}, + LineColFun{16, 12, "main"}, + LineColFun{10, 20, "_Z3sumii"}, + LineColFun{10, 32, "_Z3sumii"}, + LineColFun{14, 11, "main"}, + LineColFun{14, 21, "main"}, + LineColFun{10, 34, "_Z3sumii"}, + LineColFun{10, 36, "_Z3sumii"}, + LineColFun{10, 13, "_Z3sumii"}, + LineColFun{15, 11, "main"}, + LineColFun{15, 14, "main"}, + LineColFun{13, 7, "main"}, + LineColFun{14, 7, "main"}, + LineColFun{16, 8, "main"}, + LineColFun{16, 15, "main"}, + LineColFun{15, 7, "main"}, + }); + + doAnalysisAndCompareResults("call_04_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEFeatureTaintAnalysisTest, HandleCallTest_05) { std::set GroundTruth; - GroundTruth.emplace("main", 10, "retval", std::set{"8"}); - GroundTruth.emplace("main", 10, "i", std::set{"3", "11", "9"}); - GroundTruth.emplace("main", 10, "j", std::set{"3", "10", "12"}); - doAnalysisAndCompareResults("call_05_cpp.ll", {"main"}, GroundTruth, false); + auto Main10 = RetStmt{"main"}; + + GroundTruth.emplace(Main10, "i", + TaintSetT{ + LineColFun{2, 38, "_Z18setValueToFortyTwoPi"}, + LineColFun{7, 3, "main"}, + LineColFun{5, 7, "main"}, + }); + GroundTruth.emplace(Main10, "j", + TaintSetT{ + LineColFun{2, 38, "_Z18setValueToFortyTwoPi"}, + LineColFun{6, 7, "main"}, + LineColFun{8, 3, "main"}, + }); + + doAnalysisAndCompareResults("call_05_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEFeatureTaintAnalysisTest, HandleCallTest_06) { // NOTE: Here we are suffering from IntraProceduralAliasesOnly std::set GroundTruth; - GroundTruth.emplace("main", 24, "retval", std::set{"11"}); - GroundTruth.emplace( - "main", 24, "i", - std::set{"3", "1", "2", "16", "17", "18", "12"}); - GroundTruth.emplace( - "main", 24, "j", - std::set{"19", "20", "21", "3", "1", "2", "13"}); - GroundTruth.emplace( - "main", 24, "k", - std::set{"22", "23", "3", "14", "1", "2", "24"}); - GroundTruth.emplace( - "main", 24, "l", - std::set{"15", "3", "1", "2", "25", "26", "27"}); - doAnalysisAndCompareResults("call_06_cpp.ll", {"main"}, GroundTruth, false); + auto Main24 = RetStmt{"main"}; + + GroundTruth.emplace(Main24, "i", + TaintSetT{ + LineColFun{2, 31, "_Z9incrementi"}, + LineColFun{2, 19, "_Z9incrementi"}, + LineColFun{2, 31, "_Z9incrementi"}, + LineColFun{9, 17, "main"}, + LineColFun{9, 5, "main"}, + LineColFun{9, 7, "main"}, + LineColFun{5, 7, "main"}, + }); + GroundTruth.emplace(Main24, "j", + TaintSetT{ + LineColFun{10, 7, "main"}, + LineColFun{10, 17, "main"}, + LineColFun{10, 5, "main"}, + LineColFun{2, 31, "_Z9incrementi"}, + LineColFun{2, 19, "_Z9incrementi"}, + LineColFun{2, 31, "_Z9incrementi"}, + LineColFun{6, 7, "main"}, + }); + GroundTruth.emplace(Main24, "k", + TaintSetT{ + LineColFun{11, 17, "main"}, + LineColFun{11, 7, "main"}, + LineColFun{2, 31, "_Z9incrementi"}, + LineColFun{7, 7, "main"}, + LineColFun{2, 19, "_Z9incrementi"}, + LineColFun{2, 31, "_Z9incrementi"}, + LineColFun{11, 5, "main"}, + }); + GroundTruth.emplace(Main24, "l", + TaintSetT{ + LineColFun{8, 7, "main"}, + LineColFun{2, 31, "_Z9incrementi"}, + LineColFun{2, 19, "_Z9incrementi"}, + LineColFun{2, 31, "_Z9incrementi"}, + LineColFun{12, 7, "main"}, + LineColFun{12, 17, "main"}, + LineColFun{12, 5, "main"}, + }); + + doAnalysisAndCompareResults("call_06_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEFeatureTaintAnalysisTest, HandleCallTest_07) { std::set GroundTruth; - GroundTruth.emplace("main", 6, "retval", std::set{"7"}); - GroundTruth.emplace("main", 6, "VarIR", std::set{"6", "3", "8"}); - doAnalysisAndCompareResults("call_07_cpp.ll", {"main"}, GroundTruth, false); + auto Main6 = RetStmt{"main"}; + + GroundTruth.emplace(Main6, "VarIR", + TaintSetT{ + LineColFun{7, 7, "main"}, + LineColFun{3, 6, "_Z13inputRefParamRi"}, + LineColFun{8, 3, "main"}, + }); + doAnalysisAndCompareResults("call_07_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEFeatureTaintAnalysisTest, HandleGlobalTest_01) { std::set GroundTruth; - GroundTruth.emplace("main", 9, "retval", std::set{"3"}); - GroundTruth.emplace("main", 9, "i", std::set{"7"}); - GroundTruth.emplace("main", 9, "j", std::set{"0", "5", "6"}); - doAnalysisAndCompareResults("global_01_cpp.ll", {"main"}, GroundTruth, false); + auto Main9 = RetStmt{"main"}; + + GroundTruth.emplace(Main9, "i", + TaintSetT{ + LineColFun{6, 5, "main"}, + }); + GroundTruth.emplace(Main9, "j", + TaintSetT{ + GlobalVar{"i"}, + LineColFun{5, 7, "main"}, + LineColFun{5, 5, "main"}, + }); + + doAnalysisAndCompareResults("global_01_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEFeatureTaintAnalysisTest, HandleGlobalTest_02) { std::set GroundTruth; - GroundTruth.emplace("_Z5initBv", 2, "a", std::set{"0"}); - GroundTruth.emplace("_Z5initBv", 2, "b", std::set{"2"}); - GroundTruth.emplace("main", 12, "a", std::set{"0"}); - GroundTruth.emplace("main", 12, "b", std::set{"2"}); - GroundTruth.emplace("main", 12, "retval", std::set{"6"}); - GroundTruth.emplace("main", 12, "c", std::set{"1", "8", "7"}); - doAnalysisAndCompareResults("global_02_cpp.ll", {"main"}, GroundTruth, false); + + auto Main12 = RetStmt{"main"}; + auto Init2 = RetStmt{"_Z5initBv"}; + + GroundTruth.emplace(Init2, "a", + TaintSetT{ + GlobalVar{"a"}, + }); + GroundTruth.emplace(Init2, "b", + TaintSetT{ + LineColFun{4, 18, "_Z5initBv"}, + }); + + GroundTruth.emplace(Main12, "a", + TaintSetT{ + GlobalVar{"a"}, + }); + GroundTruth.emplace(Main12, "b", + TaintSetT{ + LineColFun{4, 18, "_Z5initBv"}, + }); + GroundTruth.emplace(Main12, "c", + TaintSetT{ + GlobalVar{"b"}, + LineColFun{7, 7, "main"}, + LineColFun{7, 11, "main"}, + }); + + doAnalysisAndCompareResults("global_02_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEFeatureTaintAnalysisTest, HandleGlobalTest_03) { std::set GroundTruth; - GroundTruth.emplace("main", 1, "GlobalFeature", std::set{"0"}); - GroundTruth.emplace("main", 2, "GlobalFeature", std::set{"0"}); - GroundTruth.emplace("main", 17, "GlobalFeature", std::set{"0"}); - doAnalysisAndCompareResults("global_03_cpp.ll", {"main"}, GroundTruth, false); + GroundTruth.emplace(LineColFun{6, 11, "main"}, "GlobalFeature", + TaintSetT{ + GlobalVar{"GlobalFeature"}, + }); + GroundTruth.emplace(LineColFun{6, 25, "main"}, "GlobalFeature", + TaintSetT{ + GlobalVar{"GlobalFeature"}, + }); + GroundTruth.emplace(RetStmt{"main"}, "GlobalFeature", + TaintSetT{ + GlobalVar{"GlobalFeature"}, + }); + + doAnalysisAndCompareResults("global_03_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEFeatureTaintAnalysisTest, HandleGlobalTest_04) { std::set GroundTruth; - GroundTruth.emplace("main", 1, "GlobalFeature", std::set{"0"}); - GroundTruth.emplace("main", 2, "GlobalFeature", std::set{"0"}); - GroundTruth.emplace("main", 17, "GlobalFeature", std::set{"0"}); - GroundTruth.emplace("_Z7doStuffi", 1, "GlobalFeature", - std::set{"0"}); - GroundTruth.emplace("_Z7doStuffi", 2, "GlobalFeature", - std::set{"0"}); - doAnalysisAndCompareResults("global_04_cpp.ll", {"main", "_Z7doStuffi"}, + GroundTruth.emplace(LineColFun{8, 11, "main"}, "GlobalFeature", + TaintSetT{ + GlobalVar{"GlobalFeature"}, + }); + GroundTruth.emplace(LineColFun{8, 25, "main"}, "GlobalFeature", + TaintSetT{ + GlobalVar{"GlobalFeature"}, + }); + GroundTruth.emplace(RetStmt{"main"}, "GlobalFeature", + TaintSetT{ + GlobalVar{"GlobalFeature"}, + }); + GroundTruth.emplace(LineColFun{3, 31, "_Z7doStuffi"}, "GlobalFeature", + TaintSetT{ + GlobalVar{"GlobalFeature"}, + }); + GroundTruth.emplace(LineColFun{3, 22, "_Z7doStuffi"}, "GlobalFeature", + TaintSetT{ + GlobalVar{"GlobalFeature"}, + }); + + doAnalysisAndCompareResults("global_04_cpp_dbg.ll", {"main", "_Z7doStuffi"}, GroundTruth, false); } -TEST_F(IDEFeatureTaintAnalysisTest, HandleGlobalTest_05) { - std::set GroundTruth; - - // NOTE: Facts at init() should be empty, except for its own ID; - // g should be strongly updated - - GroundTruth.emplace("main", 1, "g", std::set{"0"}); - GroundTruth.emplace("main", 2, "g", std::set{"2"}); - GroundTruth.emplace("main", 4, "call", - std::set{"2", "4", "7", "8"}); - GroundTruth.emplace("main", 4, "g", std::set{"2"}); - - doAnalysisAndCompareResults("global_05_cpp.ll", {"main"}, GroundTruth, true); -} TEST_F(IDEFeatureTaintAnalysisTest, KillTest_01) { std::set GroundTruth; - GroundTruth.emplace("main", 12, "retval", std::set{"4"}); - GroundTruth.emplace("main", 12, "i", std::set{"5"}); - GroundTruth.emplace("main", 12, "j", std::set{"10"}); - GroundTruth.emplace("main", 12, "k", std::set{"9", "8", "5"}); - doAnalysisAndCompareResults("KillTest_01_cpp.ll", {"main"}, GroundTruth, + auto Main12 = RetStmt{"main"}; + + GroundTruth.emplace(Main12, "i", + TaintSetT{ + LineColFun{2, 7, "main"}, + }); + GroundTruth.emplace(Main12, "j", + TaintSetT{ + LineColFun{5, 5, "main"}, + }); + GroundTruth.emplace(Main12, "k", + TaintSetT{ + LineColFun{4, 7, "main"}, + LineColFun{4, 11, "main"}, + LineColFun{2, 7, "main"}, + }); + + doAnalysisAndCompareResults("KillTest_01_cpp_dbg.ll", {"main"}, GroundTruth, false); } TEST_F(IDEFeatureTaintAnalysisTest, KillTest_02) { std::set GroundTruth; - GroundTruth.emplace("main", 12, "retval", std::set{"6"}); - GroundTruth.emplace("main", 12, "A", std::set{"0"}); - GroundTruth.emplace("main", 12, "B", std::set{"2"}); - GroundTruth.emplace("main", 12, "C", std::set{"1", "7", "8"}); - doAnalysisAndCompareResults("KillTest_02_cpp.ll", {"main"}, GroundTruth, + auto Main12 = RetStmt{"main"}; + + GroundTruth.emplace(Main12, "A", + TaintSetT{ + GlobalVar{"A"}, + }); + GroundTruth.emplace(Main12, "B", + TaintSetT{ + LineColFun{4, 18, "_Z5initBv"}, + }); + GroundTruth.emplace(Main12, "C", + TaintSetT{ + GlobalVar{"B"}, + LineColFun{7, 11, "main"}, + LineColFun{7, 7, "main"}, + }); + + doAnalysisAndCompareResults("KillTest_02_cpp_dbg.ll", {"main"}, GroundTruth, false); } TEST_F(IDEFeatureTaintAnalysisTest, HandleReturnTest_01) { std::set GroundTruth; - GroundTruth.emplace("main", 6, "retval", std::set{"3"}); - GroundTruth.emplace("main", 6, "localVar", std::set{"4"}); - GroundTruth.emplace("main", 6, "call", std::set{"0", "5"}); - GroundTruth.emplace("main", 8, "localVar", - std::set{"0", "5", "6"}); - GroundTruth.emplace("main", 8, "call", std::set{"0", "5"}); - doAnalysisAndCompareResults("return_01_cpp.ll", {"main"}, GroundTruth, false); + auto Main6 = LineColFun{7, 12, "main"}; + auto Main8 = RetStmt{"main"}; + + GroundTruth.emplace(Main6, "localVar", + TaintSetT{ + LineColFun{6, 12, "main"}, + }); + GroundTruth.emplace(Main8, "localVar", + TaintSetT{ + LineColFun{2, 30, "_Z20returnIntegerLiteralv"}, + LineColFun{7, 14, "main"}, + LineColFun{7, 12, "main"}, + }); + + doAnalysisAndCompareResults("return_01_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEFeatureTaintAnalysisTest, HandleHeapTest_01) { std::set GroundTruth; - GroundTruth.emplace("main", 17, "retval", std::set{"3"}); - GroundTruth.emplace("main", 17, "i", std::set{"5", "6"}); - GroundTruth.emplace("main", 17, "j", - std::set{"5", "6", "7", "8", "9"}); - doAnalysisAndCompareResults("heap_01_cpp.ll", {"main"}, GroundTruth, false); -} -PHASAR_SKIP_TEST(TEST_F(IDEFeatureTaintAnalysisTest, HandleRVOTest_01) { - GTEST_SKIP() << "This test heavily depends on the used stdlib version. TODO: " - "add a better one"; + auto Main17 = RetStmt{"main"}; + GroundTruth.emplace(Main17, "i", + TaintSetT{ + LineColFun{3, 12, "main"}, + LineColFun{3, 8, "main"}, + }); + GroundTruth.emplace(Main17, "j", + TaintSetT{ + LineColFun{3, 12, "main"}, + LineColFun{3, 8, "main"}, + LineColFun{4, 12, "main"}, + LineColFun{4, 11, "main"}, + LineColFun{4, 7, "main"}, + }); + + doAnalysisAndCompareResults("heap_01_cpp_dbg.ll", {"main"}, GroundTruth, + false); +} - std::set GroundTruth; - GroundTruth.emplace("main", 16, "retval", std::set{"75", "76"}); - GroundTruth.emplace("main", 16, "str", - std::set{"70", "65", "72", "74", "77"}); - GroundTruth.emplace("main", 16, "ref.tmp", - std::set{"66", "9", "72", "73", "71"}); - doAnalysisAndCompareResults("rvo_01_cpp.ll", {"main"}, GroundTruth, false); -}) - -PHASAR_SKIP_TEST(TEST_F(IDEFeatureTaintAnalysisTest, HandleRVOTest_02) { - GTEST_SKIP() << "This test heavily depends on the used stdlib version. TODO: " - "add a better one"; +// PHASAR_SKIP_TEST(TEST_F(IDEFeatureTaintAnalysisTest, HandleRVOTest_02) { +// GTEST_SKIP() << "This test heavily depends on the used stdlib version. +// TODO: " +// "add a better one"; - std::set GroundTruth; - GroundTruth.emplace("main", 18, "retval", std::set{"75", "76"}); - GroundTruth.emplace("main", 18, "str", - std::set{"70", "65", "72", "74", "77"}); - GroundTruth.emplace("main", 18, "ref.tmp", - std::set{"66", "9", "72", "73", "71"}); - doAnalysisAndCompareResults("rvo_02_cpp.ll", {"main"}, GroundTruth, true); -}) +// std::set GroundTruth; +// GroundTruth.emplace("main", 18, "retval", std::set{"75", +// "76"}); GroundTruth.emplace("main", 18, "str", +// std::set{"70", "65", "72", "74", "77"}); +// GroundTruth.emplace("main", 18, "ref.tmp", +// std::set{"66", "9", "72", "73", "71"}); +// doAnalysisAndCompareResults("rvo_02_cpp.ll", {"main"}, GroundTruth, true); +// }) TEST_F(IDEFeatureTaintAnalysisTest, HandleRVOTest_03) { std::set GroundTruth; - - GroundTruth.emplace( - "main", 19, "Str", - std::set{"39", "43", "46", "49", "51", "54", "63"}); - GroundTruth.emplace("main", 19, "ref.tmp", - std::set{"13", "19", "2", "20", "23", "24", - "25", "27", "29", "32", "40", "45", - "46", "47"}); - GroundTruth.emplace("main", 19, "ref.tmp1", - std::set{"1", "13", "19", "20", "23", "24", - "25", "27", "29", "32", "48", "49", - "50"}); - doAnalysisAndCompareResults("rvo_03_cpp.ll", {"main"}, GroundTruth, true); + auto Main19 = RetStmt{"main"}; + + GroundTruth.emplace(Main19, "Str", + TaintSetT{ + LineColFun{49, 10, "main"}, + LineColFun{49, 10, "main"}, + LineColFun{51, 7, "main"}, + LineColFun{52, 7, "main"}, + LineColFun{53, 14, "main"}, + LineColFun{54, 1, "main"}, + LineColFun{41, 10, "_ZN6StringC2Ev"}, + }); + + doAnalysisAndCompareResults("rvo_03_cpp_dbg.ll", {"main"}, GroundTruth, true); } TEST_F(IDEFeatureTaintAnalysisTest, HandleRVOTest_04) { std::set GroundTruth; - GroundTruth.emplace("main", 10, "retval", std::set{"14"}); - GroundTruth.emplace( - "main", 10, "F", - std::set{"12", "15", "16", "17", "2", "3", "9"}); - GroundTruth.emplace("main", 10, "ref.tmp", - std::set{"16", "17", "2", "3", "9"}); - doAnalysisAndCompareResults("rvo_04_cpp.ll", {"main"}, GroundTruth, true); + auto Main10 = RetStmt{"main"}; + + GroundTruth.emplace(Main10, "F", + TaintSetT{ + LineColFun{17, 7, "main"}, + LineColFun{17, 7, "main"}, + LineColFun{18, 7, "main"}, + LineColFun{18, 5, "main"}, + LineColFun{14, 26, "_Z9createFoov"}, + LineColFun{14, 26, "_Z9createFoov"}, + LineColFun{7, 7, "_ZN3FooC2Ev"}, + }); + + doAnalysisAndCompareResults("rvo_04_cpp_dbg.ll", {"main"}, GroundTruth, true); } } // namespace diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp index d81885c43f..de8b4e8fde 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp @@ -10,28 +10,29 @@ #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/IDEGeneralizedLCA.h" #include "phasar/DataFlow/IfdsIde/Solver/IDESolver.h" -#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" +#include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCA/EdgeValue.h" #include "phasar/PhasarLLVM/HelperAnalyses.h" #include "phasar/PhasarLLVM/Passes/ValueAnnotationPass.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h" #include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" -#include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" -#include "phasar/Utils/Logger.h" -#include "llvm/Support/raw_ostream.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" +#include "llvm/Support/Casting.h" +#include "SrcCodeLocationEntry.h" #include "TestConfig.h" #include "gtest/gtest.h" -#include #include using namespace psr; using namespace psr::glca; +using namespace psr::unittest; -using groundTruth_t = - std::tuple; +using l_t = IDEGeneralizedLCA::l_t; +using groundTruth_t = std::tuple; /* ============== TEST FIXTURE ============== */ @@ -68,127 +69,171 @@ class IDEGeneralizedLCATest : public ::testing::Test { /// \brief compares the computed results with every given tuple (value, /// alloca, inst) void compareResults(const std::vector &Expected) { - for (const auto &[EVal, VrId, InstId] : Expected) { - const auto *Vr = HA->getProjectIRDB().getInstruction(VrId); - const auto *Inst = HA->getProjectIRDB().getInstruction(InstId); - ASSERT_NE(nullptr, Vr); - ASSERT_NE(nullptr, Inst); - auto Result = LCASolver->resultAt(Inst, Vr); - - EXPECT_EQ(EVal, Result) << "vr:" << VrId << " inst:" << InstId - << " Expected: " << EVal << " Got:" << Result; + for (const auto &[EVal, VarLoc, InstLoc] : Expected) { + const auto *Var = testingLocInIR(VarLoc, HA->getProjectIRDB()); + const auto *Inst = llvm::dyn_cast_if_present( + testingLocInIR(InstLoc, HA->getProjectIRDB())); + + ASSERT_TRUE(Var) << "Cannot map location " << VarLoc.str() << " to LLVM"; + ASSERT_TRUE(Inst) << "Cannot map location " << InstLoc.str() + << " to LLVM"; + + auto Result = LCASolver->resultAt(Inst, Var); + EXPECT_EQ(EVal, Result) + << "At VarLoc: " << VarLoc.str() << ", InstLoc: " << InstLoc.str() + << ";\n aka. Var: " << llvmIRToString(Var) + << "; Inst: " << llvmIRToString(Inst) << ":\n Expected: " << EVal + << " Got:" << LToString(Result); } } }; // class Fixture TEST_F(IDEGeneralizedLCATest, SimpleTest) { - initialize("SimpleTest_c.ll"); + initialize("SimpleTest_c_dbg.ll"); std::vector GroundTruth; - GroundTruth.push_back({{EdgeValue(10)}, 3, 20}); - GroundTruth.push_back({{EdgeValue(15)}, 4, 20}); + + GroundTruth.emplace_back(l_t{EdgeValue(10)}, LineColFun{4, 0, "main"}, + LineColFun{7, 3, "main"}); + GroundTruth.emplace_back(l_t{EdgeValue(15)}, LineColFun{5, 0, "main"}, + LineColFun{7, 3, "main"}); + compareResults(GroundTruth); } - TEST_F(IDEGeneralizedLCATest, BranchTest) { - initialize("BranchTest_c.ll"); + initialize("BranchTest_c_dbg.ll"); std::vector GroundTruth; - GroundTruth.push_back({{EdgeValue(25), EdgeValue(43)}, 3, 22}); - GroundTruth.push_back({{EdgeValue(24)}, 4, 22}); + + GroundTruth.push_back( + {{EdgeValue(25)}, LineColFun{7, 11, "main"}, LineColFun{8, 3, "main"}}); + GroundTruth.push_back( + {{EdgeValue(24)}, LineColFun{7, 9, "main"}, LineColFun{8, 3, "main"}}); + compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, FPtest) { - initialize("FPtest_c.ll"); - + initialize("FPtest_c_dbg.ll"); std::vector GroundTruth; - GroundTruth.push_back({{EdgeValue(4.5)}, 1, 16}); - GroundTruth.push_back({{EdgeValue(2.0)}, 2, 16}); + + GroundTruth.push_back( + {{EdgeValue(4.5)}, LineColFun{4, 9, "main"}, LineColFun{6, 3, "main"}}); + GroundTruth.push_back( + {{EdgeValue(2.0)}, LineColFun{5, 9, "main"}, LineColFun{6, 3, "main"}}); + compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, StringTest) { - initialize("StringTest_c.ll"); + initialize("StringTest_c_dbg.ll"); std::vector GroundTruth; - GroundTruth.push_back({{EdgeValue("Hello, World")}, 2, 8}); - GroundTruth.push_back({{EdgeValue("Hello, World")}, 3, 8}); + + GroundTruth.push_back({{EdgeValue("Hello, World")}, + LineColFun{4, 0, "main"}, + LineColFun{7, 3, "main"}}); + GroundTruth.push_back({{EdgeValue("Hello, World")}, + LineColFun{5, 0, "main"}, + LineColFun{7, 3, "main"}}); + compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, StringBranchTest) { - initialize("StringBranchTest_c.ll"); + initialize("StringBranchTest_c_dbg.ll"); std::vector GroundTruth; - GroundTruth.push_back( - {{EdgeValue("Hello, World"), EdgeValue("Hello Hello")}, 3, 15}); - GroundTruth.push_back({{EdgeValue("Hello Hello")}, 4, 15}); + + GroundTruth.push_back({{EdgeValue("Hello Hello"), EdgeValue("Hello, World")}, + LineColFun{5, 15, "main"}, + LineColFun{10, 3, "main"}}); + GroundTruth.push_back({{EdgeValue("Hello Hello")}, + LineColFun{6, 15, "main"}, + LineColFun{10, 3, "main"}}); + compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, StringTestCpp) { - initialize("StringTest_cpp.ll"); + initialize("StringTest_cpp_dbg.ll"); std::vector GroundTruth; - const auto *LastMainInstruction = - getLastInstructionOf(HA->getProjectIRDB().getFunction("main")); + GroundTruth.push_back({{EdgeValue("Hello, World")}, - 7, - static_cast( - std::stoi(getMetaDataID(LastMainInstruction)))}); + LineColFun{4, 15, "main"}, + LineColFun{6, 1, "main"}}); + compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, FloatDivisionTest) { - initialize("FloatDivision_c.ll"); + initialize("FloatDivision_c_dbg.ll"); std::vector GroundTruth; - GroundTruth.push_back({{EdgeValue(nullptr)}, 1, 24}); // i - GroundTruth.push_back({{EdgeValue(1.0)}, 2, 24}); // j - GroundTruth.push_back({{EdgeValue(-7.0)}, 3, 24}); // k + + GroundTruth.push_back( + {{EdgeValue(1.0)}, LineColFun{5, 9, "main"}, LineColFun{8, 3, "main"}}); + GroundTruth.push_back({{EdgeValue(nullptr)}, + LineColFun{6, 9, "main"}, + LineColFun{8, 3, "main"}}); + GroundTruth.push_back( + {{EdgeValue(-7.0)}, LineColFun{7, 9, "main"}, LineColFun{8, 3, "main"}}); + compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, SimpleFunctionTest) { - initialize("SimpleFunctionTest_c.ll"); + initialize("SimpleFunctionTest_c_dbg.ll"); std::vector GroundTruth; - GroundTruth.push_back({{EdgeValue(48)}, 10, 31}); // i - GroundTruth.push_back({{EdgeValue(nullptr)}, 11, 31}); // j + + GroundTruth.push_back( + {{EdgeValue(48)}, LineColFun{8, 7, "main"}, LineColFun{10, 3, "main"}}); + GroundTruth.push_back({{EdgeValue(nullptr)}, + LineColFun{9, 7, "main"}, + LineColFun{10, 3, "main"}}); + compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, GlobalVariableTest) { - initialize("GlobalVariableTest_c.ll"); + initialize("GlobalVariableTest_c_dbg.ll"); std::vector GroundTruth; - GroundTruth.push_back({{EdgeValue(50)}, 7, 13}); // i - GroundTruth.push_back({{EdgeValue(8)}, 10, 13}); // j + + GroundTruth.push_back( + {{EdgeValue(50)}, LineColFun{4, 13, "main"}, LineColFun{6, 3, "main"}}); + GroundTruth.push_back( + {{EdgeValue(8)}, LineColFun{5, 13, "main"}, LineColFun{6, 3, "main"}}); + compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, Imprecision) { - initialize("Imprecision_c.ll"); - // auto xInst = IRDB->getInstruction(0); // foo.x - // auto yInst = IRDB->getInstruction(1); // foo.y - // auto barInst = IRDB->getInstruction(7); + initialize("Imprecision_c_dbg.ll"); + std::vector GroundTruth; - // llvm::outs() << "foo.x = " << LCASolver->resultAt(barInst, xInst) << - // std::endl; llvm::outs() << "foo.y = " << LCASolver->resultAt(barInst, - // yInst) - // << std::endl; + GroundTruth.push_back({{EdgeValue(1), EdgeValue(2)}, + LineColFun{3, 14, "foo"}, + LineColFun{3, 26, "foo"}}); + GroundTruth.push_back({{EdgeValue(2), EdgeValue(3)}, + LineColFun{3, 21, "foo"}, + LineColFun{3, 26, "foo"}}); - std::vector GroundTruth; - GroundTruth.push_back({{EdgeValue(1), EdgeValue(2)}, 0, 7}); // i - GroundTruth.push_back({{EdgeValue(2), EdgeValue(3)}, 1, 7}); // j compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, ReturnConstTest) { - initialize("ReturnConstTest_c.ll"); + initialize("ReturnConstTest_c_dbg.ll"); std::vector GroundTruth; - GroundTruth.push_back({{EdgeValue(43)}, 7, 8}); // i + + GroundTruth.push_back( + {{EdgeValue(43)}, LineColFun{6, 12, "main"}, LineColFun{6, 3, "main"}}); + compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, NullTest) { - initialize("NullTest_c.ll"); + initialize("NullTest_c_dbg.ll"); std::vector GroundTruth; - GroundTruth.push_back({{EdgeValue("")}, 4, 5}); // foo(null) + + GroundTruth.push_back( + {{EdgeValue("")}, LineColFun{1, 31, "foo"}, LineColFun{1, 24, "foo"}}); + compareResults(GroundTruth); } diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp index 59a474013b..33fcdaa918 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp @@ -10,32 +10,41 @@ #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h" #include "phasar/DataFlow/IfdsIde/Solver/IDESolver.h" +#include "phasar/Domain/LatticeDomain.h" #include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" #include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/HelperAnalyses.h" #include "phasar/PhasarLLVM/HelperAnalysisConfig.h" -#include "phasar/PhasarLLVM/Passes/ValueAnnotationPass.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h" #include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" +#include "phasar/PhasarLLVM/Utils/LLVMIRToSrc.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "phasar/Utils/BitVectorSet.h" -#include "phasar/Utils/Logger.h" +#include "phasar/Utils/Printer.h" +#include "phasar/Utils/Utilities.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/raw_ostream.h" +#include "SrcCodeLocationEntry.h" #include "TestConfig.h" #include "gtest/gtest.h" -#include #include +#include #include #include #include using namespace psr; +using namespace psr::unittest; + +using TaintSetT = BitVectorSet; /* ============== TEST FIXTURE ============== */ class IDEInstInteractionAnalysisTest : public ::testing::Test { @@ -43,16 +52,15 @@ class IDEInstInteractionAnalysisTest : public ::testing::Test { static constexpr auto PathToLlFiles = PHASAR_BUILD_SUBFOLDER("inst_interaction/"); + using VarNameT = std::variant; // Function - Line Nr - Variable - Values using IIACompactResult_t = - std::tuple::l_t>; + std::tuple::l_t>; std::optional HA; LLVMProjectIRDB *IRDB{}; - void SetUp() override { ValueAnnotationPass::resetValueID(); } - void initializeIR(const std::string &LlvmFilePath, const std::vector &EntryPoints = {"main"}) { HA.emplace(PathToLlFiles + LlvmFilePath, EntryPoints, @@ -60,6 +68,55 @@ class IDEInstInteractionAnalysisTest : public ::testing::Test { IRDB = &HA->getProjectIRDB(); } + [[nodiscard]] const llvm::Instruction *getInst(TestingSrcLocation Loc) { + const auto *Ret = llvm::dyn_cast_if_present( + testingLocInIR(Loc, HA->getProjectIRDB())); + if (!Ret) { + throw std::runtime_error("Cannot convert loc " + Loc.str() + " to LLVM"); + } + return Ret; + } + + [[nodiscard]] bool matchesVar(const llvm::Value *Fact, + const VarNameT &VarName) { + return std::visit( + psr::Overloaded{ + [&](const std::string &Name) { + if (!llvm::isa(Fact) && + !llvm::isa(Fact)) { + return false; + } + auto FactName = psr::getVarNameFromIR(Fact); + return FactName == Name; + }, + [&](RetVal R) { + return llvm::any_of(Fact->users(), [R](const auto *V) { + const auto *Ret = llvm::dyn_cast(V); + return Ret && Ret->getFunction()->getName() == R.InFunction; + }); + }, + }, + VarName); + } + [[nodiscard]] std::string printVar(const VarNameT &VarName) { + return std::visit(psr::Overloaded{ + [](const std::string &Name) { return Name; }, + [](RetVal R) { return R.str(); }, + }, + VarName); + } + [[nodiscard]] LatticeDomain> + sorted(const IDEInstInteractionAnalysisT::l_t &Values) { + if (const auto *Set = Values.getValueOrNull()) { + std::set Ret(Set->begin(), Set->end()); + return Ret; + } + if (Values.isBottom()) { + return Bottom{}; + } + return Top{}; + } + void doAnalysisAndCompareResults(const std::string &LlvmFilePath, const std::vector &EntryPoints, @@ -70,31 +127,39 @@ class IDEInstInteractionAnalysisTest : public ::testing::Test { IRDB->emitPreprocessedIR(llvm::outs()); } - // IDEInstInteractionAnalysisT IIAProblem(IRDB, &ICFG, - // &PT, - // EntryPoints); assert(HA); auto IIAProblem = - createAnalysisProblem>( + createAnalysisProblem>( *HA, EntryPoints); - // use Phasar's instruction ids as testing labels + auto Generator = [](std::variant - Current) -> std::set { + Current) -> std::set { return std::visit( - [](const auto *InstOrGlob) -> std::set { - std::set Labels; - if (InstOrGlob->hasMetadata()) { - std::string Label = - llvm::cast( - InstOrGlob->getMetadata(PhasarConfig::MetaDataKind()) - ->getOperand(0)) - ->getString() - .str(); - Labels.insert(Label); - } - return Labels; - }, + psr::Overloaded{ + [](const llvm::GlobalVariable *Glob) + -> std::set { + std::set Labels; + Labels.insert(GlobalVar{Glob->getName()}); + return Labels; + }, + [](const llvm::Instruction *Inst) + -> std::set { + std::set Labels; + auto [Line, Col] = getLineAndColFromIR(Inst); + if (Col == 0 && llvm::isa(Inst)) { + std::tie(Line, Col) = getLineAndColFromIR(Inst->getOperand( + llvm::StoreInst::getPointerOperandIndex())); + } + if (Line != 0) { + Labels.insert(LineColFun{ + Line, + Col, + Inst->getFunction()->getName(), + }); + } + return Labels; + }}, Current); }; // register the above generator function @@ -105,49 +170,48 @@ class IDEInstInteractionAnalysisTest : public ::testing::Test { IIASolver.dumpResults(); } // do the comparison - for (const auto &[FunName, SrcLine, VarName, LatticeVal] : GroundTruth) { - const auto *Fun = IRDB->getFunctionDefinition(FunName); - const auto *IRLine = getNthInstruction(Fun, SrcLine); - auto ResultMap = IIASolver.resultsAt(IRLine); - assert(IRLine && "Could not retrieve IR line!"); + for (const auto &[InstLoc, VarName, ExpectedVal] : GroundTruth) { + // const auto *Fun = IRDB->getFunctionDefinition(FunName); + // const auto *IRLine = getNthInstruction(Fun, SrcLine); + const auto *IRLoc = testingLocInIR(InstLoc, *IRDB); + ASSERT_TRUE(IRLoc) << "Could not retrieve IR Loc: " << InstLoc.str(); + ASSERT_TRUE(llvm::isa(IRLoc)); + auto ResultMap = + IIASolver.resultsAt(llvm::cast(IRLoc)); bool FactFound = false; - for (auto &[Fact, Value] : ResultMap) { - std::string FactStr; - llvm::raw_string_ostream RSO(FactStr); - RSO << *Fact.getBase(); - llvm::StringRef FactRef(FactStr); - if (FactRef.ltrim().startswith("%" + VarName + " ") || - FactRef.ltrim().startswith("@" + VarName + " ")) { - PHASAR_LOG_LEVEL(DFADEBUG, "Checking variable: " << FactStr); - EXPECT_EQ(LatticeVal, Value); + for (auto &[Fact, ComputedVal] : ResultMap) { + if (matchesVar(Fact.getBase(), VarName)) { + EXPECT_EQ(sorted(ExpectedVal), sorted(ComputedVal)) + << "Unexpected taint-set at " << InstLoc << " for variable '" + << printVar(VarName) << "' (" << llvmIRToString(Fact.getBase()) + << ")"; FactFound = true; } } - if (!FactFound) { - PHASAR_LOG_LEVEL(DFADEBUG, "Variable '" << VarName << "' missing at '" - << llvmIRToString(IRLine) - << "'."); - } - EXPECT_TRUE(FactFound); + + EXPECT_TRUE(FactFound) + << "Variable '" << printVar(VarName) << "' missing at '" + << llvmIRToString(IRLoc) << "'."; } } - void TearDown() override {} + void TearDown() override { + BitVectorSet::clearPosition(); + } }; // Test Fixture TEST_F(IDEInstInteractionAnalysisTest, FieldSensArrayConstruction_01) { - initializeIR("array_01_cpp.ll"); - const auto *Main = IRDB->getFunction("main"); - const auto *Inst = getNthInstruction(Main, 2); + initializeIR("array_01_cpp_dbg.ll"); + const auto *Inst = getInst(LineColFun{2, 7, "main"}); llvm::outs() << "Instruction to create flow fact from: " << *Inst << '\n'; auto FlowFact = IDEIIAFlowFact::create(Inst); llvm::outs() << FlowFact << '\n'; - Inst = getNthInstruction(Main, 13); + Inst = getInst(LineColFun{5, 3, "main"}); llvm::outs() << "Instruction to create flow fact from: " << *Inst << '\n'; FlowFact = IDEIIAFlowFact::create(Inst); llvm::outs() << FlowFact << '\n'; - Inst = getNthInstruction(Main, 16); + Inst = getInst(LineColFun{6, 3, "main"}); llvm::outs() << "Instruction to create flow fact from: " << *Inst << '\n'; FlowFact = IDEIIAFlowFact::create(Inst); llvm::outs() << FlowFact << '\n'; @@ -155,21 +219,21 @@ TEST_F(IDEInstInteractionAnalysisTest, FieldSensArrayConstruction_01) { } TEST_F(IDEInstInteractionAnalysisTest, FieldSensArrayConstruction_02) { - initializeIR("array_02_cpp.ll"); - const auto *Main = IRDB->getFunction("main"); - const auto *Inst = getNthInstruction(Main, 2); + initializeIR("array_02_cpp_dbg.ll"); + const auto *Inst = getInst(LineColFun{2, 7, "main"}); llvm::outs() << "Instruction to create flow fact from: " << *Inst << '\n'; auto FlowFact = IDEIIAFlowFact::create(Inst); llvm::outs() << FlowFact << '\n'; - Inst = getNthInstruction(Main, 3); + Inst = getInst(LineColFun{4, 7, "main"}); llvm::outs() << "Instruction to create flow fact from: " << *Inst << '\n'; FlowFact = IDEIIAFlowFact::create(Inst); llvm::outs() << FlowFact << '\n'; - Inst = getNthInstruction(Main, 5); + Inst = getInst(LineColFun{3, 3, "main"}); llvm::outs() << "Instruction to create flow fact from: " << *Inst << '\n'; FlowFact = IDEIIAFlowFact::create(Inst); llvm::outs() << FlowFact << '\n'; - Inst = getNthInstruction(Main, 6); + Inst = getInst(OperandOf{llvm::StoreInst::getPointerOperandIndex(), + LineColFun{3, 16, "main"}}); llvm::outs() << "Instruction to create flow fact from: " << *Inst << '\n'; FlowFact = IDEIIAFlowFact::create(Inst); llvm::outs() << FlowFact << '\n'; @@ -177,21 +241,28 @@ TEST_F(IDEInstInteractionAnalysisTest, FieldSensArrayConstruction_02) { } TEST_F(IDEInstInteractionAnalysisTest, FieldSensArrayConstruction_03) { - initializeIR("array_03_cpp.ll"); - const auto *Main = IRDB->getFunction("main"); - const auto *Inst = getNthInstruction(Main, 2); + initializeIR("array_03_cpp_dbg.ll"); + const auto *Inst = getInst(LineColFun{2, 7, "main"}); llvm::outs() << "Instruction to create flow fact from: " << *Inst << '\n'; auto FlowFact = IDEIIAFlowFact::create(Inst); llvm::outs() << FlowFact << '\n'; - Inst = getNthInstruction(Main, 5); + + auto Store = LineColFun{3, 19, "main"}; + auto LastGep = OperandOf{llvm::StoreInst::getPointerOperandIndex(), Store}; + auto FirstGep = LineColFun{3, 3, "main"}; + + Inst = getInst(FirstGep); llvm::outs() << "Instruction to create flow fact from: " << *Inst << '\n'; FlowFact = IDEIIAFlowFact::create(Inst); llvm::outs() << FlowFact << '\n'; - Inst = getNthInstruction(Main, 6); + + const auto *LastGepInst = getInst(LastGep); + + Inst = llvm::cast(LastGepInst->getOperand(0)); llvm::outs() << "Instruction to create flow fact from: " << *Inst << '\n'; FlowFact = IDEIIAFlowFact::create(Inst); llvm::outs() << FlowFact << '\n'; - Inst = getNthInstruction(Main, 7); + Inst = LastGepInst; llvm::outs() << "Instruction to create flow fact from: " << *Inst << '\n'; FlowFact = IDEIIAFlowFact::create(Inst); llvm::outs() << FlowFact << '\n'; @@ -199,17 +270,16 @@ TEST_F(IDEInstInteractionAnalysisTest, FieldSensArrayConstruction_03) { } TEST_F(IDEInstInteractionAnalysisTest, FieldSensStructConstruction_01) { - initializeIR("struct_01_cpp.ll"); - const auto *Main = IRDB->getFunction("main"); - const auto *Inst = getNthInstruction(Main, 2); + initializeIR("struct_01_cpp_dbg.ll"); + const auto *Inst = getInst(LineColFun{8, 7, "main"}); llvm::outs() << "Instruction to create flow fact from: " << *Inst << '\n'; auto FlowFact = IDEIIAFlowFact::create(Inst); llvm::outs() << FlowFact << '\n'; - Inst = getNthInstruction(Main, 14); + Inst = getInst(LineColFun{12, 5, "main"}); llvm::outs() << "Instruction to create flow fact from: " << *Inst << '\n'; FlowFact = IDEIIAFlowFact::create(Inst); llvm::outs() << FlowFact << '\n'; - Inst = getNthInstruction(Main, 17); + Inst = getInst(LineColFun{13, 5, "main"}); llvm::outs() << "Instruction to create flow fact from: " << *Inst << '\n'; FlowFact = IDEIIAFlowFact::create(Inst); llvm::outs() << FlowFact << '\n'; @@ -217,21 +287,20 @@ TEST_F(IDEInstInteractionAnalysisTest, FieldSensStructConstruction_01) { } TEST_F(IDEInstInteractionAnalysisTest, FieldSensStructConstruction_02) { - initializeIR("struct_02_cpp.ll"); - const auto *Main = IRDB->getFunction("main"); - const auto *Inst = getNthInstruction(Main, 2); + initializeIR("struct_02_cpp_dbg.ll"); + const auto *Inst = getInst(LineColFun{12, 5, "main"}); llvm::outs() << "Instruction to create flow fact from: " << *Inst << '\n'; auto FlowFact = IDEIIAFlowFact::create(Inst); llvm::outs() << FlowFact << '\n'; - Inst = getNthInstruction(Main, 6); + Inst = getInst(LineColFun{13, 5, "main"}); llvm::outs() << "Instruction to create flow fact from: " << *Inst << '\n'; FlowFact = IDEIIAFlowFact::create(Inst); llvm::outs() << FlowFact << '\n'; - Inst = getNthInstruction(Main, 7); + Inst = getInst(LineColFun{13, 7, "main"}); llvm::outs() << "Instruction to create flow fact from: " << *Inst << '\n'; FlowFact = IDEIIAFlowFact::create(Inst); llvm::outs() << FlowFact << '\n'; - Inst = getNthInstruction(Main, 9); + Inst = getInst(LineColFun{14, 5, "main"}); llvm::outs() << "Instruction to create flow fact from: " << *Inst << '\n'; FlowFact = IDEIIAFlowFact::create(Inst); llvm::outs() << FlowFact << '\n'; @@ -239,87 +308,98 @@ TEST_F(IDEInstInteractionAnalysisTest, FieldSensStructConstruction_02) { } TEST_F(IDEInstInteractionAnalysisTest, ArrayEquality_01) { - initializeIR("array_01_cpp.ll"); + initializeIR("array_01_cpp_dbg.ll"); - const auto *Main = IRDB->getFunction("main"); - const auto *Inst = getNthInstruction(Main, 2); + const auto *Inst = getInst(LineColFun{2, 7, "main"}); auto FlowFact = IDEIIAFlowFact::create(Inst); ASSERT_EQ(FlowFact, FlowFact); - Inst = getNthInstruction(Main, 4); + Inst = getInst(LineColFun{4, 7, "main"}); FlowFact = IDEIIAFlowFact::create(Inst); - Inst = getNthInstruction(Main, 13); + Inst = getInst(LineColFun{5, 3, "main"}); auto OtherFlowFact = IDEIIAFlowFact::create(Inst); ASSERT_NE(FlowFact, OtherFlowFact); - Inst = getNthInstruction(Main, 13); - FlowFact = IDEIIAFlowFact::create(Inst); - Inst = getNthInstruction(Main, 18); + Inst = getInst(LineColFun{7, 11, "main"}); OtherFlowFact = IDEIIAFlowFact::create(Inst); ASSERT_EQ(FlowFact, OtherFlowFact); - Inst = getNthInstruction(Main, 16); + Inst = getInst(LineColFun{6, 3, "main"}); FlowFact = IDEIIAFlowFact::create(Inst); - Inst = getNthInstruction(Main, 21); + Inst = getInst(LineColFun{8, 11, "main"}); OtherFlowFact = IDEIIAFlowFact::create(Inst); ASSERT_EQ(FlowFact, OtherFlowFact); } TEST_F(IDEInstInteractionAnalysisTest, ArrayEquality_02) { - initializeIR("array_02_cpp.ll"); - const auto *Main = IRDB->getFunction("main"); - const auto *Inst = getNthInstruction(Main, 2); + initializeIR("array_02_cpp_dbg.ll"); + const auto *Inst = getInst(LineColFun{2, 7, "main"}); auto FlowFact = IDEIIAFlowFact::create(Inst); ASSERT_EQ(FlowFact, FlowFact); - Inst = getNthInstruction(Main, 5); + const auto *FirstGep = getInst(LineColFun{3, 3, "main"}); + Inst = FirstGep; FlowFact = IDEIIAFlowFact::create(Inst); - Inst = getNthInstruction(Main, 8); + Inst = getInst(LineColFun{4, 11, "main"}); auto OtherFlowFact = IDEIIAFlowFact::create(Inst); ASSERT_EQ(FlowFact, OtherFlowFact); - Inst = getNthInstruction(Main, 6); + const auto *SecondGep = getInst(OperandOf{ + llvm::StoreInst::getPointerOperandIndex(), LineColFun{3, 16, "main"}}); + Inst = SecondGep; FlowFact = IDEIIAFlowFact::create(Inst); - Inst = getNthInstruction(Main, 9); + Inst = llvm::cast( + getInst(LineColFunOp{4, 11, "main", llvm::Instruction::Load}) + ->getOperand(0)); OtherFlowFact = IDEIIAFlowFact::create(Inst); ASSERT_EQ(FlowFact, OtherFlowFact); - Inst = getNthInstruction(Main, 5); + Inst = FirstGep; FlowFact = IDEIIAFlowFact::create(Inst); - Inst = getNthInstruction(Main, 6); + Inst = SecondGep; OtherFlowFact = IDEIIAFlowFact::create(Inst); ASSERT_NE(FlowFact, OtherFlowFact); } TEST_F(IDEInstInteractionAnalysisTest, ArrayEquality_03) { - initializeIR("array_03_cpp.ll"); - const auto *Main = IRDB->getFunction("main"); - const auto *Inst = getNthInstruction(Main, 2); + initializeIR("array_03_cpp_dbg.ll"); + const auto *Inst = getInst(LineColFun{2, 7, "main"}); auto FlowFact = IDEIIAFlowFact::create(Inst); ASSERT_EQ(FlowFact, FlowFact); - Inst = getNthInstruction(Main, 5); + Inst = getInst(LineColFun{3, 3, "main"}); FlowFact = IDEIIAFlowFact::create(Inst); - Inst = getNthInstruction(Main, 9); + Inst = getInst(LineColFun{4, 11, "main"}); auto OtherFlowFact = IDEIIAFlowFact::create(Inst); ASSERT_EQ(FlowFact, OtherFlowFact); - Inst = getNthInstruction(Main, 6); + const auto *GepStore = + llvm::cast(getInst(LineColFun{3, 19, "main"})); + const auto *GepLoad = + getInst(LineColFunOp{4, 11, "main", llvm::Instruction::Load}); + + Inst = llvm::cast( + llvm::cast(GepStore->getPointerOperand()) + ->getPointerOperand()); FlowFact = IDEIIAFlowFact::create(Inst); - Inst = getNthInstruction(Main, 10); + Inst = llvm::cast( + llvm::cast(GepLoad->getOperand(0)) + ->getPointerOperand()); OtherFlowFact = IDEIIAFlowFact::create(Inst); ASSERT_EQ(FlowFact, OtherFlowFact); - Inst = getNthInstruction(Main, 7); + Inst = llvm::cast(GepStore->getPointerOperand()); FlowFact = IDEIIAFlowFact::create(Inst); - Inst = getNthInstruction(Main, 11); + Inst = llvm::cast(GepLoad->getOperand(0)); OtherFlowFact = IDEIIAFlowFact::create(Inst); ASSERT_EQ(FlowFact, OtherFlowFact); - Inst = getNthInstruction(Main, 6); + Inst = llvm::cast( + llvm::cast(GepStore->getPointerOperand()) + ->getPointerOperand()); FlowFact = IDEIIAFlowFact::create(Inst); - Inst = getNthInstruction(Main, 11); + Inst = llvm::cast(GepLoad->getOperand(0)); OtherFlowFact = IDEIIAFlowFact::create(Inst); // For K-limit of 2, this should be considered equal if (IDEIIAFlowFact::KLimit <= 2) { @@ -330,33 +410,32 @@ TEST_F(IDEInstInteractionAnalysisTest, ArrayEquality_03) { } TEST_F(IDEInstInteractionAnalysisTest, StructEquality_01) { - initializeIR("struct_01_cpp.ll"); - const auto *Main = IRDB->getFunction("main"); - const auto *Inst = getNthInstruction(Main, 2); + initializeIR("struct_01_cpp_dbg.ll"); + const auto *Inst = getInst(LineColFun{8, 7, "main"}); auto FlowFact = IDEIIAFlowFact::create(Inst); ASSERT_EQ(FlowFact, FlowFact); - Inst = getNthInstruction(Main, 14); + Inst = getInst(LineColFun{12, 5, "main"}); FlowFact = IDEIIAFlowFact::create(Inst); - Inst = getNthInstruction(Main, 22); + Inst = getInst(LineColFun{15, 13, "main"}); auto OtherFlowFact = IDEIIAFlowFact::create(Inst); ASSERT_EQ(FlowFact, OtherFlowFact); - Inst = getNthInstruction(Main, 17); + Inst = getInst(LineColFun{13, 5, "main"}); FlowFact = IDEIIAFlowFact::create(Inst); - Inst = getNthInstruction(Main, 25); + Inst = getInst(LineColFun{16, 13, "main"}); OtherFlowFact = IDEIIAFlowFact::create(Inst); ASSERT_EQ(FlowFact, OtherFlowFact); - Inst = getNthInstruction(Main, 20); + Inst = getInst(LineColFun{14, 5, "main"}); FlowFact = IDEIIAFlowFact::create(Inst); - Inst = getNthInstruction(Main, 28); + Inst = getInst(LineColFun{17, 13, "main"}); OtherFlowFact = IDEIIAFlowFact::create(Inst); ASSERT_EQ(FlowFact, OtherFlowFact); - Inst = getNthInstruction(Main, 17); + Inst = getInst(LineColFun{13, 5, "main"}); FlowFact = IDEIIAFlowFact::create(Inst); - Inst = getNthInstruction(Main, 20); + Inst = getInst(LineColFun{14, 5, "main"}); OtherFlowFact = IDEIIAFlowFact::create(Inst); llvm::outs() << "Compare:\n"; llvm::outs() << FlowFact << '\n'; @@ -366,40 +445,39 @@ TEST_F(IDEInstInteractionAnalysisTest, StructEquality_01) { } TEST_F(IDEInstInteractionAnalysisTest, StructEquality_02) { - initializeIR("struct_02_cpp.ll"); - const auto *Main = IRDB->getFunction("main"); - const auto *Inst = getNthInstruction(Main, 2); + initializeIR("struct_02_cpp_dbg.ll"); + const auto *Inst = getInst(LineColFun{12, 5, "main"}); auto FlowFact = IDEIIAFlowFact::create(Inst); ASSERT_EQ(FlowFact, FlowFact); - Inst = getNthInstruction(Main, 6); + Inst = getInst(LineColFun{13, 5, "main"}); FlowFact = IDEIIAFlowFact::create(Inst); - Inst = getNthInstruction(Main, 11); + Inst = getInst(LineColFun{15, 13, "main"}); auto OtherFlowFact = IDEIIAFlowFact::create(Inst); ASSERT_EQ(FlowFact, OtherFlowFact); - Inst = getNthInstruction(Main, 6); + Inst = getInst(LineColFun{13, 5, "main"}); FlowFact = IDEIIAFlowFact::create(Inst); - Inst = getNthInstruction(Main, 7); + Inst = getInst(LineColFun{13, 7, "main"}); OtherFlowFact = IDEIIAFlowFact::create(Inst); ASSERT_NE(FlowFact, OtherFlowFact); - Inst = getNthInstruction(Main, 7); + Inst = getInst(LineColFun{13, 7, "main"}); FlowFact = IDEIIAFlowFact::create(Inst); - Inst = getNthInstruction(Main, 12); + Inst = getInst(LineColFun{15, 15, "main"}); OtherFlowFact = IDEIIAFlowFact::create(Inst); ASSERT_EQ(FlowFact, OtherFlowFact); - Inst = getNthInstruction(Main, 9); + Inst = getInst(LineColFun{14, 5, "main"}); FlowFact = IDEIIAFlowFact::create(Inst); - Inst = getNthInstruction(Main, 15); + Inst = getInst(LineColFun{16, 13, "main"}); OtherFlowFact = IDEIIAFlowFact::create(Inst); ASSERT_EQ(FlowFact, OtherFlowFact); - Inst = getNthInstruction(Main, 6); + Inst = getInst(LineColFun{13, 5, "main"}); llvm::outs() << "Instruction to create flow fact from: " << *Inst << '\n'; FlowFact = IDEIIAFlowFact::create(Inst); - Inst = getNthInstruction(Main, 9); + Inst = getInst(LineColFun{14, 5, "main"}); llvm::outs() << "Instruction to create flow fact from 2: " << *Inst << '\n'; OtherFlowFact = IDEIIAFlowFact::create(Inst); ASSERT_NE(FlowFact, OtherFlowFact); @@ -426,454 +504,683 @@ TEST_F(IDEInstInteractionAnalysisTest, StructEquality_02) { TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_01) { std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 9, "i", {"4"})); - GroundTruth.emplace( - std::tuple>( - "main", 9, "j", {"4", "5", "6", "7"})); - GroundTruth.emplace( - std::tuple>( - "main", 9, "retval", {"3"})); - doAnalysisAndCompareResults("basic_01_cpp.ll", {"main"}, GroundTruth, false); + auto Main9 = LineColFun{4, 3, "main"}; + GroundTruth.emplace(Main9, "i", TaintSetT{LineColFun{2, 7, "main"}}); + GroundTruth.emplace(Main9, "j", + TaintSetT{ + LineColFun{2, 7, "main"}, + LineColFun{3, 11, "main"}, + LineColFun{3, 13, "main"}, + LineColFun{3, 7, "main"}, + }); + + doAnalysisAndCompareResults("basic_01_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_02) { std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 24, "retval", {"6"})); - GroundTruth.emplace( - std::tuple>( - "main", 24, "argc.addr", {"7"})); - GroundTruth.emplace( - std::tuple>( - "main", 24, "argv.addr", {"8"})); - GroundTruth.emplace( - std::tuple>( - "main", 24, "i", {"16", "18"})); - GroundTruth.emplace( - std::tuple>( - "main", 24, "j", {"9", "10", "11", "12"})); - GroundTruth.emplace( - std::tuple>( - "main", 24, "k", {"21", "16", "18", "20"})); - doAnalysisAndCompareResults("basic_02_cpp.ll", {"main"}, GroundTruth, false); + auto Main24 = LineColFun{10, 3, "main"}; + + GroundTruth.emplace(Main24, "argc", TaintSetT{LineColFun{1, 14, "main"}}); + GroundTruth.emplace(Main24, "argv", TaintSetT{LineColFun{1, 27, "main"}}); + GroundTruth.emplace(Main24, "i", + TaintSetT{ + LineColFun{5, 7, "main"}, + LineColFun{7, 7, "main"}, + }); + GroundTruth.emplace(Main24, "j", + TaintSetT{ + LineColFun{2, 7, "main"}, + LineColFun{3, 11, "main"}, + LineColFun{3, 13, "main"}, + LineColFun{3, 7, "main"}, + }); + GroundTruth.emplace(Main24, "k", + TaintSetT{ + LineColFun{5, 7, "main"}, + LineColFun{7, 7, "main"}, + LineColFun{9, 11, "main"}, + LineColFun{9, 7, "main"}, + }); + + doAnalysisAndCompareResults("basic_02_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_03) { std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 20, "retval", {"3"})); - GroundTruth.emplace( - std::tuple>( - "main", 20, "i", {"4", "10", "11", "12"})); - GroundTruth.emplace( - std::tuple>( - "main", 20, "x", {"5", "14", "15", "16"})); - doAnalysisAndCompareResults("basic_03_cpp.ll", {"main"}, GroundTruth, false); -} - -PHASAR_SKIP_TEST(TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_04) { - // If we use libcxx this won't work since internal implementation is different + + auto Main20 = LineColFun{6, 3, "main"}; + + GroundTruth.emplace(Main20, "i", + TaintSetT{ + LineColFun{2, 7, "main"}, + LineColFun{4, 5, "main"}, + }); + GroundTruth.emplace(Main20, "x", + TaintSetT{ + LineColFun{3, 12, "main"}, + LineColFun{3, 28, "main"}, + }); + + doAnalysisAndCompareResults("basic_03_cpp_dbg.ll", {"main"}, GroundTruth, + false); +} + +TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_04) { + LIBCPP_GTEST_SKIP; std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 23, "retval", {"7"})); - GroundTruth.emplace( - std::tuple>( - "main", 23, "argc.addr", {"8"})); - GroundTruth.emplace( - std::tuple>( - "main", 23, "argv.addr", {"9"})); - GroundTruth.emplace( - std::tuple>( - "main", 23, "i", {"10"})); - GroundTruth.emplace( - std::tuple>( - "main", 23, "j", {"10", "11", "12", "13"})); - GroundTruth.emplace( - std::tuple>( - "main", 23, "k", {"10", "11", "12", "13", "14", "18", "19"})); - doAnalysisAndCompareResults("basic_04_cpp.ll", {"main"}, GroundTruth, false); -}) + auto Main23 = LineColFun{11, 3, "main"}; + + GroundTruth.emplace(Main23, "argc", + TaintSetT{ + LineColFun{3, 14, "main"}, + }); + GroundTruth.emplace(Main23, "argv", + TaintSetT{ + LineColFun{3, 27, "main"}, + }); + GroundTruth.emplace(Main23, "i", + TaintSetT{ + LineColFun{4, 7, "main"}, + }); + GroundTruth.emplace(Main23, "j", + TaintSetT{ + LineColFun{4, 7, "main"}, + LineColFun{5, 11, "main"}, + LineColFun{5, 13, "main"}, + LineColFun{5, 7, "main"}, + }); + GroundTruth.emplace(Main23, "k", + TaintSetT{ + LineColFun{4, 7, "main"}, + LineColFun{5, 11, "main"}, + LineColFun{5, 13, "main"}, + LineColFun{5, 7, "main"}, + LineColFun{6, 7, "main"}, + LineColFun{8, 9, "main"}, + LineColFun{8, 7, "main"}, + }); + + doAnalysisAndCompareResults("basic_04_cpp_dbg.ll", {"main"}, GroundTruth, + false); +} TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_05) { std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 11, "i", {"5", "7"})); - GroundTruth.emplace( - std::tuple>( - "main", 11, "retval", {"2"})); - doAnalysisAndCompareResults("basic_05_cpp.ll", {"main"}, GroundTruth, false); + auto Main11 = LineColFun{10, 3, "main"}; + GroundTruth.emplace(Main11, "i", + TaintSetT{ + LineColFun{6, 7, "main"}, + LineColFun{8, 7, "main"}, + }); + + doAnalysisAndCompareResults("basic_05_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_06) { std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 19, "retval", {"5"})); - GroundTruth.emplace( - std::tuple>( - "main", 19, "i", {"15", "6", "13"})); - GroundTruth.emplace( - std::tuple>( - "main", 19, "j", {"15", "6", "13"})); - GroundTruth.emplace( - std::tuple>( - "main", 19, "k", {"6"})); - GroundTruth.emplace( - std::tuple>( - "main", 19, "p", {"1", "2", "9", "11"})); - doAnalysisAndCompareResults("basic_06_cpp.ll", {"main"}, GroundTruth, false); + auto Main19 = LineColFun{14, 3, "main"}; + + GroundTruth.emplace(Main19, "i", + TaintSetT{ + LineColFun{6, 7, "main"}, + LineColFun{13, 8, "main"}, + LineColFun{13, 6, "main"}, + }); + GroundTruth.emplace(Main19, "j", + TaintSetT{ + LineColFun{6, 7, "main"}, + LineColFun{13, 8, "main"}, + LineColFun{13, 6, "main"}, + }); + GroundTruth.emplace(Main19, "k", + TaintSetT{ + LineColFun{6, 7, "main"}, + }); + GroundTruth.emplace(Main19, "p", + TaintSetT{ + LineColFun{4, 7, "main"}, + LineColFun{5, 7, "main"}, + LineColFun{9, 7, "main"}, + LineColFun{11, 7, "main"}, + }); + + doAnalysisAndCompareResults("basic_06_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_07) { std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 15, "retval", {"5"})); - GroundTruth.emplace( - std::tuple>( - "main", 15, "argc.addr", {"6"})); - GroundTruth.emplace( - std::tuple>( - "main", 15, "argv.addr", {"7"})); - GroundTruth.emplace( - std::tuple>( - "main", 15, "i", {"12"})); - GroundTruth.emplace( - std::tuple>( - "main", 15, "j", {"8", "9", "10", "11"})); - doAnalysisAndCompareResults("basic_07_cpp.ll", {"main"}, GroundTruth, false); + auto Main15 = LineColFun{5, 3, "main"}; + + GroundTruth.emplace(Main15, "argc", + TaintSetT{ + LineColFun{1, 14, "main"}, + }); + GroundTruth.emplace(Main15, "argv", + TaintSetT{ + LineColFun{1, 27, "main"}, + }); + // strong update on i + GroundTruth.emplace(Main15, "i", + TaintSetT{ + LineColFun{4, 5, "main"}, + }); + GroundTruth.emplace(Main15, "j", + TaintSetT{ + LineColFun{2, 7, "main"}, + LineColFun{3, 11, "main"}, + LineColFun{3, 13, "main"}, + LineColFun{3, 7, "main"}, + }); + + doAnalysisAndCompareResults("basic_07_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_08) { std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 12, "retval", {"2"})); - GroundTruth.emplace( - std::tuple>( - "main", 12, "i", {"9"})); - doAnalysisAndCompareResults("basic_08_cpp.ll", {"main"}, GroundTruth, false); + auto Main12 = LineColFun{11, 3, "main"}; + + // strong update on i + GroundTruth.emplace(Main12, "i", + TaintSetT{ + LineColFun{10, 5, "main"}, + }); + + doAnalysisAndCompareResults("basic_08_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_09) { std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 10, "i", {"4"})); - GroundTruth.emplace( - std::tuple>( - "main", 10, "j", {"4", "6", "7"})); - GroundTruth.emplace( - std::tuple>( - "main", 10, "retval", {"3"})); - doAnalysisAndCompareResults("basic_09_cpp.ll", {"main"}, GroundTruth, false); + auto Main10 = LineColFun{6, 3, "main"}; + + GroundTruth.emplace(Main10, "i", + TaintSetT{ + LineColFun{3, 7, "main"}, + }); + GroundTruth.emplace(Main10, "j", + TaintSetT{ + LineColFun{3, 7, "main"}, + LineColFun{5, 7, "main"}, + LineColFun{5, 5, "main"}, + }); + + doAnalysisAndCompareResults("basic_09_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_10) { std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 6, "i", {"3"})); - GroundTruth.emplace( - std::tuple>( - "main", 6, "retval", {"2"})); - doAnalysisAndCompareResults("basic_10_cpp.ll", {"main"}, GroundTruth, false); + auto Main6 = LineColFun{4, 3, "main"}; + GroundTruth.emplace(Main6, "i", + TaintSetT{ + LineColFun{3, 7, "main"}, + }); + + doAnalysisAndCompareResults("basic_10_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_11) { std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 20, "FeatureSelector", {"5", "7", "8"})); - GroundTruth.emplace( - std::tuple>( - "main", 20, "retval", {"11", "16"})); - doAnalysisAndCompareResults("basic_11_cpp.ll", {"main"}, GroundTruth, false); + auto Main20 = RetStmt{"main"}; + + GroundTruth.emplace(Main20, "FeatureSelector", + TaintSetT{ + LineColFun{3, 14, "main"}, + LineColFun{4, 25, "main"}, + LineColFun{4, 7, "main"}, + }); + + GroundTruth.emplace(Main20, RetVal{"main"}, + TaintSetT{ + LineColFun{7, 5, "main"}, + LineColFun{15, 3, "main"}, + LineColFun{16, 1, "main"}, + }); + + doAnalysisAndCompareResults("basic_11_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEInstInteractionAnalysisTest, HandleCallTest_01) { std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 14, "retval", {"8"})); - GroundTruth.emplace( - std::tuple>( - "main", 14, "i", {"9"})); - GroundTruth.emplace( - std::tuple>( - "main", 14, "j", {"12", "9", "10", "11"})); - GroundTruth.emplace( - std::tuple>( - "main", 14, "k", {"15", "1", "2", "13", "12", "9", "10", "11"})); - doAnalysisAndCompareResults("call_01_cpp.ll", {"main"}, GroundTruth, false); + auto Main14 = RetStmt{"main"}; + + GroundTruth.emplace(Main14, "i", + TaintSetT{ + LineColFun{4, 7, "main"}, + }); + GroundTruth.emplace(Main14, "j", + TaintSetT{ + LineColFun{4, 7, "main"}, + LineColFun{5, 11, "main"}, + LineColFun{5, 13, "main"}, + LineColFun{5, 7, "main"}, + }); + GroundTruth.emplace(Main14, "k", + TaintSetT{ + LineColFun{4, 7, "main"}, + LineColFun{5, 11, "main"}, + LineColFun{5, 13, "main"}, + LineColFun{5, 7, "main"}, + LineColFun{6, 7, "main"}, + LineColFun{6, 14, "main"}, + LineColFun{1, 12, "_Z2idi"}, + LineColFun{1, 24, "_Z2idi"}, + }); + + doAnalysisAndCompareResults("call_01_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEInstInteractionAnalysisTest, HandleCallTest_02) { std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 13, "retval", {"12"})); - GroundTruth.emplace( - std::tuple>( - "main", 13, "i", {"13"})); - GroundTruth.emplace( - std::tuple>( - "main", 13, "j", {"14"})); - GroundTruth.emplace( - std::tuple>( - "main", 13, "k", - {"4", "5", "15", "6", "3", "14", "2", "13", "16", "18"})); - doAnalysisAndCompareResults("call_02_cpp.ll", {"main"}, GroundTruth, false); + auto Main13 = RetStmt{"main"}; + + GroundTruth.emplace(Main13, "i", + TaintSetT{ + LineColFun{4, 7, "main"}, + }); + GroundTruth.emplace(Main13, "j", + TaintSetT{ + LineColFun{5, 7, "main"}, + }); + GroundTruth.emplace(Main13, "k", + TaintSetT{ + LineColFun{4, 7, "main"}, + LineColFun{5, 7, "main"}, + LineColFun{6, 15, "main"}, + LineColFun{6, 18, "main"}, + LineColFun{6, 7, "main"}, + LineColFun{1, 13, "_Z3sumii"}, + LineColFun{1, 20, "_Z3sumii"}, + LineColFun{1, 32, "_Z3sumii"}, + LineColFun{1, 36, "_Z3sumii"}, + LineColFun{1, 34, "_Z3sumii"}, + }); + + doAnalysisAndCompareResults("call_02_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEInstInteractionAnalysisTest, HandleCallTest_03) { std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 10, "retval", {"20"})); - GroundTruth.emplace( - std::tuple>( - "main", 10, "i", {"21"})); - GroundTruth.emplace( - std::tuple>( - "main", 10, "j", - {"22", "15", "6", "21", "2", "13", "8", "9", "12", "10", "24"})); - doAnalysisAndCompareResults("call_03_cpp.ll", {"main"}, GroundTruth, false); + auto Main10 = RetStmt{"main"}; + + GroundTruth.emplace(Main10, "i", + TaintSetT{ + LineColFun{9, 7, "main"}, + }); + GroundTruth.emplace(Main10, "j", + TaintSetT{ + LineColFun{9, 7, "main"}, + LineColFun{10, 21, "main"}, + LineColFun{6, 1, "_Z9factorialj"}, + LineColFun{3, 5, "_Z9factorialj"}, + LineColFun{9, 7, "main"}, + LineColFun{1, 29, "_Z9factorialj"}, + LineColFun{5, 3, "_Z9factorialj"}, + LineColFun{5, 10, "_Z9factorialj"}, + LineColFun{5, 24, "_Z9factorialj"}, + LineColFun{5, 12, "_Z9factorialj"}, + LineColFun{5, 26, "_Z9factorialj"}, + LineColFun{10, 7, "main"}, + }); + + doAnalysisAndCompareResults("call_03_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEInstInteractionAnalysisTest, HandleCallTest_04) { std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 20, "retval", {"33"})); - GroundTruth.emplace( - std::tuple>( - "main", 20, "i", {"34"})); - GroundTruth.emplace( - std::tuple>( - "main", 20, "j", - {"15", "6", "2", "13", "8", "9", "12", "10", "35", "34", "37"})); - GroundTruth.emplace( - std::tuple>( - "main", 20, "k", - {"41", "19", "15", "6", "44", "2", "13", "8", "45", - "18", "9", "12", "10", "46", "24", "25", "35", "27", - "23", "26", "38", "34", "37", "42", "40"})); - doAnalysisAndCompareResults("call_04_cpp.ll", {"main"}, GroundTruth, false); + auto Main10 = RetStmt{"main"}; + + GroundTruth.emplace(Main10, "i", + TaintSetT{ + LineColFun{13, 7, "main"}, + }); + GroundTruth.emplace(Main10, "j", + TaintSetT{ + LineColFun{6, 1, "_Z9factorialj"}, + LineColFun{3, 5, "_Z9factorialj"}, + LineColFun{1, 29, "_Z9factorialj"}, + LineColFun{5, 3, "_Z9factorialj"}, + LineColFun{5, 10, "_Z9factorialj"}, + LineColFun{5, 24, "_Z9factorialj"}, + LineColFun{5, 12, "_Z9factorialj"}, + LineColFun{5, 26, "_Z9factorialj"}, + LineColFun{14, 21, "main"}, + LineColFun{13, 7, "main"}, + LineColFun{14, 7, "main"}, + }); + GroundTruth.emplace(Main10, "k", + TaintSetT{ + LineColFun{16, 12, "main"}, + LineColFun{8, 24, "_Z2idi"}, + LineColFun{6, 1, "_Z9factorialj"}, + LineColFun{3, 5, "_Z9factorialj"}, + LineColFun{16, 5, "main"}, + LineColFun{1, 29, "_Z9factorialj"}, + LineColFun{5, 3, "_Z9factorialj"}, + LineColFun{5, 10, "_Z9factorialj"}, + LineColFun{16, 5, "main"}, + LineColFun{8, 12, "_Z2idi"}, + LineColFun{5, 24, "_Z9factorialj"}, + LineColFun{5, 12, "_Z9factorialj"}, + LineColFun{5, 26, "_Z9factorialj"}, + LineColFun{16, 5, "main"}, + LineColFun{10, 20, "_Z3sumii"}, + LineColFun{10, 32, "_Z3sumii"}, + LineColFun{14, 21, "main"}, + LineColFun{10, 34, "_Z3sumii"}, + LineColFun{10, 36, "_Z3sumii"}, + LineColFun{10, 13, "_Z3sumii"}, + LineColFun{15, 14, "main"}, + LineColFun{13, 7, "main"}, + LineColFun{14, 7, "main"}, + LineColFun{16, 15, "main"}, + LineColFun{15, 7, "main"}, + }); + + doAnalysisAndCompareResults("call_04_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEInstInteractionAnalysisTest, HandleCallTest_05) { std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 10, "retval", {"8"})); - GroundTruth.emplace( - std::tuple>( - "main", 10, "i", {"3", "11", "9"})); - GroundTruth.emplace( - std::tuple>( - "main", 10, "j", {"3", "10", "12"})); - doAnalysisAndCompareResults("call_05_cpp.ll", {"main"}, GroundTruth, false); + auto Main10 = RetStmt{"main"}; + + GroundTruth.emplace(Main10, "i", + TaintSetT{ + LineColFun{2, 38, "_Z18setValueToFortyTwoPi"}, + LineColFun{7, 3, "main"}, + LineColFun{5, 7, "main"}, + }); + GroundTruth.emplace(Main10, "j", + TaintSetT{ + LineColFun{2, 38, "_Z18setValueToFortyTwoPi"}, + LineColFun{6, 7, "main"}, + LineColFun{8, 3, "main"}, + }); + + doAnalysisAndCompareResults("call_05_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEInstInteractionAnalysisTest, HandleCallTest_06) { // NOTE: Here we are suffering from IntraProceduralAliasesOnly std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 24, "retval", {"11"})); - GroundTruth.emplace( - std::tuple>( - "main", 24, "i", {"3", "1", "2", "16", "18", "12"})); - GroundTruth.emplace( - std::tuple>( - "main", 24, "j", {"19", "21", "3", "1", "2", "13"})); - GroundTruth.emplace( - std::tuple>( - "main", 24, "k", {"22", "3", "14", "1", "2", "24"})); - GroundTruth.emplace( - std::tuple>( - "main", 24, "l", {"15", "3", "1", "2", "25", "27"})); - doAnalysisAndCompareResults("call_06_cpp.ll", {"main"}, GroundTruth, false); + auto Main24 = RetStmt{"main"}; + + GroundTruth.emplace(Main24, "i", + TaintSetT{ + LineColFun{2, 31, "_Z9incrementi"}, + LineColFun{2, 19, "_Z9incrementi"}, + LineColFun{2, 31, "_Z9incrementi"}, + LineColFun{9, 17, "main"}, + LineColFun{9, 5, "main"}, + LineColFun{5, 7, "main"}, + }); + GroundTruth.emplace(Main24, "j", + TaintSetT{ + LineColFun{10, 17, "main"}, + LineColFun{10, 5, "main"}, + LineColFun{2, 31, "_Z9incrementi"}, + LineColFun{2, 19, "_Z9incrementi"}, + LineColFun{2, 31, "_Z9incrementi"}, + LineColFun{6, 7, "main"}, + }); + GroundTruth.emplace(Main24, "k", + TaintSetT{ + LineColFun{11, 17, "main"}, + LineColFun{2, 31, "_Z9incrementi"}, + LineColFun{7, 7, "main"}, + LineColFun{2, 19, "_Z9incrementi"}, + LineColFun{2, 31, "_Z9incrementi"}, + LineColFun{11, 5, "main"}, + }); + GroundTruth.emplace(Main24, "l", + TaintSetT{ + LineColFun{8, 7, "main"}, + LineColFun{2, 31, "_Z9incrementi"}, + LineColFun{2, 19, "_Z9incrementi"}, + LineColFun{2, 31, "_Z9incrementi"}, + LineColFun{12, 17, "main"}, + LineColFun{12, 5, "main"}, + }); + + doAnalysisAndCompareResults("call_06_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEInstInteractionAnalysisTest, HandleCallTest_07) { std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 6, "retval", {"7"})); - GroundTruth.emplace( - std::tuple>( - "main", 6, "VarIR", {"6", "3", "8"})); - doAnalysisAndCompareResults("call_07_cpp.ll", {"main"}, GroundTruth, false); + auto Main6 = RetStmt{"main"}; + + GroundTruth.emplace(Main6, "VarIR", + TaintSetT{ + LineColFun{7, 7, "main"}, + LineColFun{3, 6, "_Z13inputRefParamRi"}, + LineColFun{8, 3, "main"}, + }); + doAnalysisAndCompareResults("call_07_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEInstInteractionAnalysisTest, HandleGlobalTest_01) { std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 9, "retval", {"3"})); - GroundTruth.emplace( - std::tuple>( - "main", 9, "i", {"7"})); - GroundTruth.emplace( - std::tuple>( - "main", 9, "j", {"0", "5", "6"})); - doAnalysisAndCompareResults("global_01_cpp.ll", {"main"}, GroundTruth, false); + auto Main9 = RetStmt{"main"}; + + GroundTruth.emplace(Main9, "i", + TaintSetT{ + LineColFun{6, 5, "main"}, + }); + GroundTruth.emplace(Main9, "j", + TaintSetT{ + GlobalVar{"i"}, + LineColFun{5, 7, "main"}, + LineColFun{5, 5, "main"}, + }); + + doAnalysisAndCompareResults("global_01_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEInstInteractionAnalysisTest, HandleGlobalTest_02) { std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "_Z5initBv", 2, "a", {"0"})); - GroundTruth.emplace( - std::tuple>( - "_Z5initBv", 2, "b", {"2"})); - GroundTruth.emplace( - std::tuple>( - "main", 12, "a", {"0"})); - GroundTruth.emplace( - std::tuple>( - "main", 12, "b", {"2"})); - GroundTruth.emplace( - std::tuple>( - "main", 12, "retval", {"6"})); - GroundTruth.emplace( - std::tuple>( - "main", 12, "c", {"1", "8", "7"})); - doAnalysisAndCompareResults("global_02_cpp.ll", {"main"}, GroundTruth, false); + + auto Main12 = RetStmt{"main"}; + auto Init2 = RetStmt{"_Z5initBv"}; + + GroundTruth.emplace(Init2, "a", + TaintSetT{ + GlobalVar{"a"}, + }); + GroundTruth.emplace(Init2, "b", + TaintSetT{ + LineColFun{4, 18, "_Z5initBv"}, + }); + + GroundTruth.emplace(Main12, "a", + TaintSetT{ + GlobalVar{"a"}, + }); + GroundTruth.emplace(Main12, "b", + TaintSetT{ + LineColFun{4, 18, "_Z5initBv"}, + }); + GroundTruth.emplace(Main12, "c", + TaintSetT{ + GlobalVar{"b"}, + LineColFun{7, 7, "main"}, + LineColFun{7, 11, "main"}, + }); + + doAnalysisAndCompareResults("global_02_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEInstInteractionAnalysisTest, HandleGlobalTest_03) { std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 1, "GlobalFeature", {"0"})); - GroundTruth.emplace( - std::tuple>( - "main", 2, "GlobalFeature", {"0"})); - GroundTruth.emplace( - std::tuple>( - "main", 17, "GlobalFeature", {"0"})); - doAnalysisAndCompareResults("global_03_cpp.ll", {"main"}, GroundTruth, false); + GroundTruth.emplace(LineColFun{6, 11, "main"}, "GlobalFeature", + TaintSetT{ + GlobalVar{"GlobalFeature"}, + }); + GroundTruth.emplace(LineColFun{6, 25, "main"}, "GlobalFeature", + TaintSetT{ + GlobalVar{"GlobalFeature"}, + }); + GroundTruth.emplace(RetStmt{"main"}, "GlobalFeature", + TaintSetT{ + GlobalVar{"GlobalFeature"}, + }); + + doAnalysisAndCompareResults("global_03_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEInstInteractionAnalysisTest, HandleGlobalTest_04) { std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 1, "GlobalFeature", {"0"})); - GroundTruth.emplace( - std::tuple>( - "main", 2, "GlobalFeature", {"0"})); - GroundTruth.emplace( - std::tuple>( - "main", 17, "GlobalFeature", {"0"})); - GroundTruth.emplace( - std::tuple>( - "_Z7doStuffi", 1, "GlobalFeature", {"0"})); - GroundTruth.emplace( - std::tuple>( - "_Z7doStuffi", 2, "GlobalFeature", {"0"})); - doAnalysisAndCompareResults("global_04_cpp.ll", {"main", "_Z7doStuffi"}, + GroundTruth.emplace(LineColFun{8, 11, "main"}, "GlobalFeature", + TaintSetT{ + GlobalVar{"GlobalFeature"}, + }); + GroundTruth.emplace(LineColFun{8, 25, "main"}, "GlobalFeature", + TaintSetT{ + GlobalVar{"GlobalFeature"}, + }); + GroundTruth.emplace(RetStmt{"main"}, "GlobalFeature", + TaintSetT{ + GlobalVar{"GlobalFeature"}, + }); + GroundTruth.emplace(LineColFun{3, 31, "_Z7doStuffi"}, "GlobalFeature", + TaintSetT{ + GlobalVar{"GlobalFeature"}, + }); + GroundTruth.emplace(LineColFun{3, 22, "_Z7doStuffi"}, "GlobalFeature", + TaintSetT{ + GlobalVar{"GlobalFeature"}, + }); + + doAnalysisAndCompareResults("global_04_cpp_dbg.ll", {"main", "_Z7doStuffi"}, GroundTruth, false); } TEST_F(IDEInstInteractionAnalysisTest, KillTest_01) { std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 12, "retval", {"4"})); - GroundTruth.emplace( - std::tuple>( - "main", 12, "i", {"5"})); - GroundTruth.emplace( - std::tuple>( - "main", 12, "j", {"10"})); - GroundTruth.emplace( - std::tuple>( - "main", 12, "k", {"9", "8", "5"})); - doAnalysisAndCompareResults("KillTest_01_cpp.ll", {"main"}, GroundTruth, + auto Main12 = RetStmt{"main"}; + + GroundTruth.emplace(Main12, "i", + TaintSetT{ + LineColFun{2, 7, "main"}, + }); + GroundTruth.emplace(Main12, "j", + TaintSetT{ + LineColFun{5, 5, "main"}, + }); + GroundTruth.emplace(Main12, "k", + TaintSetT{ + LineColFun{4, 7, "main"}, + LineColFun{4, 11, "main"}, + LineColFun{2, 7, "main"}, + }); + + doAnalysisAndCompareResults("KillTest_01_cpp_dbg.ll", {"main"}, GroundTruth, false); } TEST_F(IDEInstInteractionAnalysisTest, KillTest_02) { std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 12, "retval", {"6"})); - GroundTruth.emplace( - std::tuple>( - "main", 12, "A", {"0"})); - GroundTruth.emplace( - std::tuple>( - "main", 12, "B", {"2"})); - GroundTruth.emplace( - std::tuple>( - "main", 12, "C", {"1", "7", "8"})); - doAnalysisAndCompareResults("KillTest_02_cpp.ll", {"main"}, GroundTruth, + auto Main12 = RetStmt{"main"}; + + GroundTruth.emplace(Main12, "A", + TaintSetT{ + GlobalVar{"A"}, + }); + GroundTruth.emplace(Main12, "B", + TaintSetT{ + LineColFun{4, 18, "_Z5initBv"}, + }); + GroundTruth.emplace(Main12, "C", + TaintSetT{ + GlobalVar{"B"}, + LineColFun{7, 11, "main"}, + LineColFun{7, 7, "main"}, + }); + + doAnalysisAndCompareResults("KillTest_02_cpp_dbg.ll", {"main"}, GroundTruth, false); } TEST_F(IDEInstInteractionAnalysisTest, HandleReturnTest_01) { std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 6, "retval", {"3"})); - GroundTruth.emplace( - std::tuple>( - "main", 6, "localVar", {"4"})); - GroundTruth.emplace( - std::tuple>( - "main", 6, "call", {"0"})); - GroundTruth.emplace( - std::tuple>( - "main", 8, "localVar", {"0", "6"})); - GroundTruth.emplace( - std::tuple>( - "main", 8, "call", {"0"})); - doAnalysisAndCompareResults("return_01_cpp.ll", {"main"}, GroundTruth, false); + auto Main6 = LineColFun{7, 12, "main"}; + auto Main8 = RetStmt{"main"}; + + GroundTruth.emplace(Main6, "localVar", + TaintSetT{ + LineColFun{6, 12, "main"}, + }); + GroundTruth.emplace(Main8, "localVar", + TaintSetT{ + LineColFun{2, 30, "_Z20returnIntegerLiteralv"}, + LineColFun{7, 12, "main"}, + }); + + doAnalysisAndCompareResults("return_01_cpp_dbg.ll", {"main"}, GroundTruth, + false); } TEST_F(IDEInstInteractionAnalysisTest, HandleHeapTest_01) { std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 17, "retval", {"3"})); - GroundTruth.emplace( - std::tuple>( - "main", 17, "i", {"5", "6"})); - GroundTruth.emplace( - std::tuple>( - "main", 17, "j", {"5", "6", "7", "8", "9"})); - doAnalysisAndCompareResults("heap_01_cpp.ll", {"main"}, GroundTruth, false); -} - -PHASAR_SKIP_TEST(TEST_F(IDEInstInteractionAnalysisTest, HandleRVOTest_01) { - GTEST_SKIP() << "This test heavily depends on the used stdlib version. TODO: " - "add a better one"; - std::set GroundTruth; - GroundTruth.emplace( - std::tuple>( - "main", 16, "retval", {"75", "76"})); - GroundTruth.emplace( - std::tuple>( - "main", 16, "str", {"70", "65", "72", "74", "77"})); - GroundTruth.emplace( - std::tuple>( - "main", 16, "ref.tmp", {"66", "9", "72", "73", "71"})); - doAnalysisAndCompareResults("rvo_01_cpp.ll", {"main"}, GroundTruth, false); -}) + auto Main17 = RetStmt{"main"}; + GroundTruth.emplace(Main17, "i", + TaintSetT{ + LineColFun{3, 12, "main"}, + LineColFun{3, 8, "main"}, + }); + GroundTruth.emplace(Main17, "j", + TaintSetT{ + LineColFun{3, 12, "main"}, + LineColFun{3, 8, "main"}, + LineColFun{4, 12, "main"}, + LineColFun{4, 11, "main"}, + LineColFun{4, 7, "main"}, + }); + + doAnalysisAndCompareResults("heap_01_cpp_dbg.ll", {"main"}, GroundTruth, + false); +} + +// PHASAR_SKIP_TEST(TEST_F(IDEInstInteractionAnalysisTest, HandleRVOTest_01) { +// GTEST_SKIP() << "This test heavily depends on the used stdlib version. +// TODO: " +// "add a better one"; + +// std::set GroundTruth; +// GroundTruth.emplace( +// std::tuple>( +// "main", 16, "retval", {"75", "76"})); +// GroundTruth.emplace( +// std::tuple>( +// "main", 16, "str", {"70", "65", "72", "74", "77"})); +// GroundTruth.emplace( +// std::tuple>( +// "main", 16, "ref.tmp", {"66", "9", "72", "73", "71"})); +// doAnalysisAndCompareResults("rvo_01_cpp.ll", {"main"}, GroundTruth, false); +// }) // TEST_F(IDEInstInteractionAnalysisTest, HandleStruct_01) { // std::set GroundTruth; diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysisSwiftTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysisSwiftTest.cpp index 5b2bd36241..35f070a2ab 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysisSwiftTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysisSwiftTest.cpp @@ -3,7 +3,6 @@ #include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.h" #include "phasar/PhasarLLVM/HelperAnalyses.h" -#include "phasar/PhasarLLVM/Passes/ValueAnnotationPass.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h" #include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" @@ -12,10 +11,10 @@ #include "TestConfig.h" #include "gtest/gtest.h" -#include #include using namespace psr; +using namespace psr::unittest; /* ============== TEST FIXTURE ============== */ class IDELinearConstantAnalysisSwiftTest : public ::testing::Test { diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysisTest.cpp index 7a7a20b80c..a84d1d55eb 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysisTest.cpp @@ -4,7 +4,6 @@ #include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" #include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/HelperAnalyses.h" -#include "phasar/PhasarLLVM/Passes/ValueAnnotationPass.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h" #include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" @@ -13,10 +12,10 @@ #include "TestConfig.h" #include "gtest/gtest.h" -#include #include using namespace psr; +using namespace psr::unittest; /* ============== TEST FIXTURE ============== */ class IDELinearConstantAnalysisTest : public ::testing::Test { @@ -29,8 +28,6 @@ class IDELinearConstantAnalysisTest : public ::testing::Test { using LCACompactResult_t = std::tuple; - void SetUp() override { ValueAnnotationPass::resetValueID(); } - IDELinearConstantAnalysis::lca_results_t doAnalysis(llvm::StringRef LlvmFilePath, bool PrintDump = false) { HelperAnalyses HA(PathToLlFiles + LlvmFilePath, EntryPoints); diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis_DotTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis_DotTest.cpp index 8f14daced7..d755dce01c 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis_DotTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis_DotTest.cpp @@ -1,20 +1,16 @@ #include "phasar/DataFlow/IfdsIde/Solver/IDESolver.h" #include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" -#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDELinearConstantAnalysis.h" #include "phasar/PhasarLLVM/HelperAnalyses.h" -#include "phasar/PhasarLLVM/Passes/ValueAnnotationPass.h" -#include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h" #include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" -#include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" #include "TestConfig.h" #include "gtest/gtest.h" -#include #include using namespace psr; +using namespace psr::unittest; /* ============== TEST FIXTURE ============== */ class IDELinearConstantAnalysisTest : public ::testing::Test { @@ -28,8 +24,6 @@ class IDELinearConstantAnalysisTest : public ::testing::Test { using LCACompactResult_t = std::tuple; - void SetUp() override { ValueAnnotationPass::resetValueID(); } - IDELinearConstantAnalysis::lca_results_t doAnalysis(llvm::StringRef LlvmFilePath, bool PrintDump = false, bool EmitESG = false) { diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp index 0b2d4fa52e..79f09ab423 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp @@ -13,20 +13,24 @@ #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h" #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/CSTDFILEIOTypeStateDescription.h" #include "phasar/PhasarLLVM/HelperAnalyses.h" -#include "phasar/PhasarLLVM/Passes/ValueAnnotationPass.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h" #include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" +#include "phasar/Utils/DebugOutput.h" +#include "llvm/IR/Instruction.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" + +#include "SrcCodeLocationEntry.h" #include "TestConfig.h" #include "gtest/gtest.h" -#include #include -using namespace std; using namespace psr; +using namespace psr::unittest; /* ============== TEST FIXTURE ============== */ class IDETSAnalysisFileIOTest : public ::testing::Test { @@ -58,9 +62,28 @@ class IDETSAnalysisFileIOTest : public ::testing::Test { *HA, &CSTDFILEIODesc, EntryPoints); } - void SetUp() override { ValueAnnotationPass::resetValueID(); } - - void TearDown() override {} + using GroundTruthMapTy = + std::map>; + + [[nodiscard]] static inline auto convertTestingLocationMapMapInIR( + const GroundTruthMapTy &Locs, + const ProjectIRDBBase &IRDB) { + std::map> Ret; + llvm::transform( + Locs, std::inserter(Ret, Ret.end()), [&](const auto &LocAndSet) { + const auto &[InstLoc, InnerMap] = LocAndSet; + const auto *LocVal = llvm::dyn_cast_if_present( + testingLocInIR(InstLoc, IRDB)); + std::map ConvMap; + for (const auto &[FactLoc, Val] : InnerMap) { + if (const auto *Fact = testingLocInIR(FactLoc, IRDB)) { + ConvMap.try_emplace(Fact, Val); + } + } + return std::make_pair(LocVal, std::move(ConvMap)); + }); + return Ret; + } /** * We map instruction id to value for the ground truth. ID has to be @@ -69,483 +92,489 @@ class IDETSAnalysisFileIOTest : public ::testing::Test { * @param solver provides the results */ void compareResults( - const std::map> &GroundTruth, + const GroundTruthMapTy &GroundTruth, IDESolver_P> &Solver) { - for (const auto &InstToGroundTruth : GroundTruth) { - const auto *Inst = - HA->getProjectIRDB().getInstruction(InstToGroundTruth.first); - // std::cout << "Handle results at " << InstToGroundTruth.first << - // std::endl; - auto GT = InstToGroundTruth.second; - std::map Results; - for (auto Result : Solver.resultsAt(Inst, true)) { - if (GT.find(getMetaDataID(Result.first)) != GT.end()) { - Results.insert(std::pair( - getMetaDataID(Result.first), int(Result.second))); + auto GroundTruthEntries = + convertTestingLocationMapMapInIR(GroundTruth, HA->getProjectIRDB()); + + for (const auto &[CurrInst, GT] : GroundTruthEntries) { + std::map Results; + + for (const auto &[ResFact, ResState] : Solver.resultsAt(CurrInst, true)) { + if (GT.count(ResFact)) { + Results.try_emplace(ResFact, int(ResState)); } } - EXPECT_EQ(Results, GT) << "At " << llvmIRToShortString(Inst); + + EXPECT_EQ(Results, GT) + << "At " << llvmIRToShortString(CurrInst) << ": Expected " + << PrettyPrinter{GT} << "; got: " << PrettyPrinter{Results}; } } }; // Test Fixture TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_01) { - initialize({PathToLlFiles + "typestate_01_c.ll"}); + initialize({PathToLlFiles + "typestate_01_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); Llvmtssolver.solve(); - const std::map> Gt = { - {5, {{"3", IOSTATE::UNINIT}}}, - {9, {{"3", IOSTATE::CLOSED}}}, - {7, {{"3", IOSTATE::OPENED}}}}; - compareResults(Gt, Llvmtssolver); + + GroundTruthMapTy GroundTruth; + const auto File = LineColFun{4, 9, "main"}; + const auto Entry = LineColFun{5, 7, "main"}; + const auto EntryTwo = LineColFun{6, 3, "main"}; + const auto EntryThree = LineColFun{7, 3, "main"}; + GroundTruth.insert({Entry, {{File, IOSTATE::UNINIT}}}); + GroundTruth.insert({EntryTwo, {{File, IOSTATE::OPENED}}}); + GroundTruth.insert({EntryThree, {{File, IOSTATE::CLOSED}}}); + compareResults(GroundTruth, Llvmtssolver); } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_02) { - initialize({PathToLlFiles + "typestate_02_c.ll"}); + initialize({PathToLlFiles + "typestate_02_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); - const std::map> Gt = { - {7, {{"3", IOSTATE::OPENED}, {"5", IOSTATE::OPENED}}}}; - compareResults(Gt, Llvmtssolver); + + GroundTruthMapTy GroundTruth; + const auto File = LineColFun{4, 9, "main"}; + const auto Entry = LineColFun{6, 3, "main"}; + GroundTruth.insert({Entry, {{File, IOSTATE::OPENED}}}); + compareResults(GroundTruth, Llvmtssolver); } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_03) { - initialize({PathToLlFiles + "typestate_03_c.ll"}); + initialize({PathToLlFiles + "typestate_03_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); - // llvmtssolver.printReport(); - const std::map> Gt = { - // Entry in foo() - {2, {{"foo.0", IOSTATE::OPENED}}}, - // Exit in foo() - {6, - { - {"foo.0", IOSTATE::CLOSED}, - {"2", IOSTATE::CLOSED}, - {"4", IOSTATE::CLOSED}, - //{"8", IOSTATE::CLOSED} // 6 is before 8; so no info avaliable - // before ret FF - }}, - // Exit in main() - {14, - {{"2", IOSTATE::CLOSED}, - {"8", IOSTATE::CLOSED}, - {"12", IOSTATE::CLOSED}}}}; - compareResults(Gt, Llvmtssolver); + + GroundTruthMapTy GroundTruth; + // %f = alloca ptr, align 8 + const auto MainFile = LineColFun{6, 9, "main"}; + // %f.addr = alloca ptr, align 8 + // const auto FooFile = LineColFun{3, 16, "foo"}; + // const auto FooFClose = + // LineColFun{3, 21, "foo"}; + // %0 = load ptr, ptr %f + const auto PassFToFClose = LineColFun{3, 28, "foo"}; + // ret void + const auto FooRet = LineColFun{3, 32, "foo"}; + // %0 = load ptr, ptr %f, align 8 + const auto PassFToFoo = LineColFun{9, 7, "main"}; + // ret i32 0 + const auto Return = LineColFun{11, 3, "main"}; + // Entry in foo() + // GroundTruth.insert({FooFClose, {{FooFile, IOSTATE::OPENED}}}); + // Exit in foo() + GroundTruth.insert({FooRet, + {// {FooFile, IOSTATE::CLOSED}, + {PassFToFClose, IOSTATE::CLOSED}}}); + // Exit in main() + GroundTruth.insert({Return, + {// {FooFClose, IOSTATE::CLOSED}, + {MainFile, IOSTATE::CLOSED}, + {PassFToFoo, IOSTATE::CLOSED}}}); + compareResults(GroundTruth, Llvmtssolver); } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_04) { - initialize({PathToLlFiles + "typestate_04_c.ll"}); + initialize({PathToLlFiles + "typestate_04_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); - const std::map> Gt = { - // At exit in foo() - {6, - { - {"2", IOSTATE::OPENED}, - //{"8", IOSTATE::OPENED} // 6 is before 8, so no info available - // before retFF - }}, - // Before closing in main() - {12, {{"2", IOSTATE::UNINIT}, {"8", IOSTATE::UNINIT}}}, - // At exit in main() - {14, {{"2", IOSTATE::ERROR}, {"8", IOSTATE::ERROR}}}}; - - compareResults(Gt, Llvmtssolver); + GroundTruthMapTy GroundTruth; + const auto FooArg = LineColFun{4, 16, "foo"}; + const auto FooRet = LineColFun{4, 49, "foo"}; + const auto File = LineColFun{7, 9, "main"}; + const auto FClose = LineColFun{9, 3, "main"}; + const auto Return = LineColFun{10, 3, "main"}; + GroundTruth.insert({FooRet, {{FooArg, IOSTATE::OPENED}}}); + GroundTruth.insert({FClose, {{File, IOSTATE::UNINIT}}}); + GroundTruth.insert({Return, {{File, IOSTATE::ERROR}}}); + compareResults(GroundTruth, Llvmtssolver); } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_05) { - initialize({PathToLlFiles + "typestate_05_c.ll"}); + initialize({PathToLlFiles + "typestate_05_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); - const std::map> Gt = { - // Before if statement - {10, {{"4", IOSTATE::OPENED}, {"6", IOSTATE::OPENED}}}, - // Inside if statement at last instruction - {13, - {{"4", IOSTATE::CLOSED}, - {"6", IOSTATE::CLOSED}, - {"11", IOSTATE::CLOSED}}}, - // After if statement - {14, {{"4", IOSTATE::BOT}, {"6", IOSTATE::BOT}}}}; - compareResults(Gt, Llvmtssolver); + + GroundTruthMapTy GroundTruth; + const auto File = LineColFun{6, 9, "main"}; + const auto CallFOpen = LineColFun{7, 7, "main"}; + const auto AfterFOpen = LineColFun{8, 7, "main"}; + const auto LoadFile = LineColFun{9, 12, "main"}; + const auto AfterFClose = LineColFun{10, 3, "main"}; + const auto Return = LineColFun{11, 3, "main"}; + GroundTruth.insert( + {AfterFOpen, {{File, IOSTATE::OPENED}, {CallFOpen, IOSTATE::OPENED}}}); + GroundTruth.insert({AfterFClose, + {{File, IOSTATE::CLOSED}, + {CallFOpen, IOSTATE::CLOSED}, + {LoadFile, IOSTATE::CLOSED}}}); + GroundTruth.insert( + {Return, {{File, IOSTATE::BOT}, {CallFOpen, IOSTATE::BOT}}}); + compareResults(GroundTruth, Llvmtssolver); } TEST_F(IDETSAnalysisFileIOTest, DISABLED_HandleTypeState_06) { // This test fails due to imprecise points-to information - initialize({PathToLlFiles + "typestate_06_c.ll"}); + initialize({PathToLlFiles + "typestate_06_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); - const std::map> Gt = { - // Before first fopen() - {8, {{"5", IOSTATE::UNINIT}, {"6", IOSTATE::UNINIT}}}, - // Before storing the result of the first fopen() - {9, - {{"5", IOSTATE::UNINIT}, - {"6", IOSTATE::UNINIT}, - // Return value of first fopen() - {"8", IOSTATE::OPENED}}}, - // Before second fopen() - {10, - {{"5", IOSTATE::OPENED}, - {"6", IOSTATE::UNINIT}, - {"8", IOSTATE::OPENED}}}, - // Before storing the result of the second fopen() - {11, - {{"5", IOSTATE::OPENED}, - {"6", IOSTATE::UNINIT}, - // Return value of second fopen() - {"10", IOSTATE::OPENED}}}, - // Before fclose() - {13, - {{"5", IOSTATE::OPENED}, - {"6", IOSTATE::OPENED}, - {"12", IOSTATE::OPENED}}}, - // After if statement - {14, {{"5", IOSTATE::CLOSED}, {"6", IOSTATE::OPENED}}}}; - compareResults(Gt, Llvmtssolver); + + GroundTruthMapTy GroundTruth; + + // %f = alloca ptr, align 8 + const auto FileF = LineColFun{5, 9, "main"}; + // %d = alloca ptr, align 8 + const auto FileD = LineColFun{6, 9, "main"}; + // %call = call noalias ptr @fopen(ptr noundef @.str, ptr noundef @.str.1) + const auto FirstFOpenCall = LineColFun{7, 7, "main"}; + // store ptr %call, ptr %f, align 8 + const auto StoreFirstFOpenRetVal = LineColFun{7, 5, "main"}; + // %call1 = call noalias ptr @fopen(ptr noundef @.str.2, ptr noundef @.str.3) + const auto SecondFOpenCall = LineColFun{8, 7, "main"}; + // store ptr %call1, ptr %d, align 8 + const auto StoreSecondFOpenRetVal = LineColFun{8, 5, "main"}; + // %0 = load ptr, ptr %f, align 8 + const auto LoadFileF = LineColFun{10, 10, "main"}; + // %call2 = call i32 @fclose(ptr noundef %0) + const auto CallFClose = LineColFun{10, 3, "main"}; + // ret i32 0 + const auto Return = LineColFun{12, 3, "main"}; + + GroundTruth.insert({FirstFOpenCall, {{FileF, IOSTATE::UNINIT}}}); + GroundTruth.insert({FirstFOpenCall, {{FileD, IOSTATE::UNINIT}}}); + + GroundTruth.insert({StoreFirstFOpenRetVal, {{FileF, IOSTATE::UNINIT}}}); + GroundTruth.insert({StoreFirstFOpenRetVal, {{FileD, IOSTATE::UNINIT}}}); + GroundTruth.insert( + {StoreFirstFOpenRetVal, {{FirstFOpenCall, IOSTATE::OPENED}}}); + + GroundTruth.insert({SecondFOpenCall, {{FileF, IOSTATE::OPENED}}}); + GroundTruth.insert({SecondFOpenCall, {{FileD, IOSTATE::UNINIT}}}); + GroundTruth.insert({SecondFOpenCall, {{FirstFOpenCall, IOSTATE::OPENED}}}); + + GroundTruth.insert({StoreSecondFOpenRetVal, {{FileF, IOSTATE::OPENED}}}); + GroundTruth.insert({StoreSecondFOpenRetVal, {{FileD, IOSTATE::UNINIT}}}); + GroundTruth.insert( + {StoreSecondFOpenRetVal, {{SecondFOpenCall, IOSTATE::OPENED}}}); + + GroundTruth.insert({CallFClose, {{FileF, IOSTATE::OPENED}}}); + GroundTruth.insert({CallFClose, {{FileD, IOSTATE::UNINIT}}}); + GroundTruth.insert({CallFClose, {{LoadFileF, IOSTATE::OPENED}}}); + + GroundTruth.insert({Return, {{FileF, IOSTATE::OPENED}}}); + GroundTruth.insert({Return, {{FileD, IOSTATE::UNINIT}}}); + compareResults(GroundTruth, Llvmtssolver); } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_07) { - initialize({PathToLlFiles + "typestate_07_c.ll"}); + initialize({PathToLlFiles + "typestate_07_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); - const std::map> Gt = { - // In foo() - {6, - { - {"foo.0", IOSTATE::CLOSED}, {"2", IOSTATE::CLOSED}, - //{"8", IOSTATE::CLOSED}// 6 is before 8, so no info available - // before retFF - }}, - // At fclose() - {11, {{"8", IOSTATE::UNINIT}, {"10", IOSTATE::UNINIT}}}, - // After fclose() - {12, {{"8", IOSTATE::ERROR}, {"10", IOSTATE::ERROR}}}, - // After fopen() - {13, - {{"8", IOSTATE::ERROR}, - {"10", IOSTATE::ERROR}, - {"12", IOSTATE::OPENED}}}, - // After store - {14, - {{"8", IOSTATE::OPENED}, - {"10", IOSTATE::ERROR}, - {"12", IOSTATE::OPENED}}}, - // At exit in main() - {16, {{"2", IOSTATE::CLOSED}, {"8", IOSTATE::CLOSED}}}}; - compareResults(Gt, Llvmtssolver); + + GroundTruthMapTy GroundTruth; + // %f.addr = alloca ptr, align 8 + const auto FooFile = LineColFun{3, 16, "foo"}; + // ret void + const auto FooRet = LineColFun{3, 32, "foo"}; + // %f = alloca ptr, align 8 + const auto MainFile = LineColFun{6, 9, "main"}; + // %0 = load ptr, ptr %f, align 8 + const auto MainFileLoad = LineColFun{7, 10, "main"}; + // %call = call i32 @fclose(ptr noundef %0) + const auto CallFClose = LineColFun{7, 3, "main"}; + // %call1 = call noalias ptr @fopen(ptr noundef @.str, ptr noundef @.str.1) + const auto Call1FOpen = LineColFun{8, 7, "main"}; + // store ptr %call1, ptr %f, align 8 + const auto StoreOfCall1 = LineColFun{8, 5, "main"}; + // %1 = load ptr, ptr %f, align 8 + const auto LoadMainFile = LineColFun{10, 7, "main"}; + // ret i32 0 + const auto MainReturn = LineColFun{12, 3, "main"}; + + GroundTruth.insert({FooRet, {{FooFile, IOSTATE::CLOSED}}}); + GroundTruth.insert( + {CallFClose, + {{MainFile, IOSTATE::UNINIT}, {MainFileLoad, IOSTATE::UNINIT}}}); + GroundTruth.insert( + {Call1FOpen, + {{MainFile, IOSTATE::ERROR}, {MainFileLoad, IOSTATE::ERROR}}}); + GroundTruth.insert({StoreOfCall1, + {{MainFile, IOSTATE::ERROR}, + {MainFileLoad, IOSTATE::ERROR}, + {Call1FOpen, IOSTATE::OPENED}}}); + GroundTruth.insert({LoadMainFile, + {{MainFile, IOSTATE::OPENED}, + {MainFileLoad, IOSTATE::ERROR}, + {Call1FOpen, IOSTATE::OPENED}}}); + GroundTruth.insert( + {MainReturn, {{MainFile, IOSTATE::CLOSED}, {FooFile, IOSTATE::CLOSED}}}); } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_08) { - initialize({PathToLlFiles + "typestate_08_c.ll"}); + initialize({PathToLlFiles + "typestate_08_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); - const std::map> Gt = { - // At exit in foo() - {6, {{"2", IOSTATE::OPENED}}}, - // At exit in main() - {11, {{"2", IOSTATE::OPENED}, {"8", IOSTATE::UNINIT}}}}; - compareResults(Gt, Llvmtssolver); + + GroundTruthMapTy GroundTruth; + const auto FooFile = LineColFun{5, 9, "foo"}; + const auto FooRet = LineColFun{7, 3, "foo"}; + const auto MainFile = LineColFun{11, 9, "main"}; + const auto MainReturn = LineColFun{13, 3, "main"}; + GroundTruth.insert({FooRet, {{FooFile, IOSTATE::OPENED}}}); + GroundTruth.insert( + {MainReturn, {{FooFile, IOSTATE::OPENED}, {MainFile, IOSTATE::UNINIT}}}); + compareResults(GroundTruth, Llvmtssolver); } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_09) { - initialize({PathToLlFiles + "typestate_09_c.ll"}); + initialize({PathToLlFiles + "typestate_09_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); - const std::map> Gt = { - // At exit in foo() - {8, - { - {"4", IOSTATE::OPENED}, - //{"10", IOSTATE::OPENED}// 8 is before 10, so no info available - // before retFF - }}, - // At exit in main() - {18, {{"4", IOSTATE::CLOSED}, {"10", IOSTATE::CLOSED}}}}; - compareResults(Gt, Llvmtssolver); + + GroundTruthMapTy GroundTruth; + const auto FooFile = LineColFun{5, 9, "foo"}; + const auto FooRet = LineColFun{7, 3, "foo"}; + const auto MainFile = LineColFun{11, 9, "main"}; + const auto MainReturn = LineColFun{15, 3, "main"}; + GroundTruth.insert({FooRet, {{FooFile, IOSTATE::OPENED}}}); + GroundTruth.insert( + {MainReturn, {{FooFile, IOSTATE::CLOSED}, {MainFile, IOSTATE::CLOSED}}}); + compareResults(GroundTruth, Llvmtssolver); } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_10) { - initialize({PathToLlFiles + "typestate_10_c.ll"}); + initialize({PathToLlFiles + "typestate_10_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); - const std::map> Gt = { - // At exit in bar() - {4, {{"2", IOSTATE::UNINIT}}}, - // At exit in foo() - {11, - {//{"2", IOSTATE::OPENED}, - //{"13", IOSTATE::OPENED}, // 2 and 13 are in different functions, so - // results are not available before retFF - {"5", IOSTATE::OPENED}}}, - // At exit in main() - {19, - {{"2", IOSTATE::CLOSED}, - {"5", IOSTATE::CLOSED}, - {"13", IOSTATE::CLOSED}}}}; - compareResults(Gt, Llvmtssolver); + + GroundTruthMapTy GroundTruth; + const auto BarFile = LineColFun{5, 9, "bar"}; + const auto BarRet = LineColFun{6, 3, "bar"}; + const auto FooFile = LineColFun{10, 9, "foo"}; + const auto FooRet = LineColFun{12, 3, "foo"}; + const auto MainFile = LineColFun{16, 9, "main"}; + const auto MainReturn = LineColFun{20, 3, "main"}; + GroundTruth.insert({BarRet, {{BarFile, IOSTATE::UNINIT}}}); + GroundTruth.insert({FooRet, {{FooFile, IOSTATE::OPENED}}}); + GroundTruth.insert({MainReturn, + {{BarFile, IOSTATE::CLOSED}, + {FooFile, IOSTATE::CLOSED}, + {MainFile, IOSTATE::CLOSED}}}); + compareResults(GroundTruth, Llvmtssolver); } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_11) { - initialize({PathToLlFiles + "typestate_11_c.ll"}); + initialize({PathToLlFiles + "typestate_11_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); - const std::map> Gt = { - // At exit in bar(): closing uninitialized file-handle gives error-state - {6, - { - {"2", IOSTATE::ERROR}, - //{"7", IOSTATE::ERROR}, - //{"13", IOSTATE::ERROR} // 7 and 13 not yet reached - }}, - // At exit in foo() - {11, - { - //{"2", IOSTATE::OPENED}, // 2 is in different function - {"7", IOSTATE::OPENED}, - //{"13", IOSTATE::OPENED} // 13 is after 11 - }}, - // At exit in main(): due to aliasing the error-state from bar is - // propagated back to main - {19, - {{"2", IOSTATE::ERROR}, {"7", IOSTATE::ERROR}, {"13", IOSTATE::ERROR}}}}; - compareResults(Gt, Llvmtssolver); + + GroundTruthMapTy GroundTruth; + const auto BarFile = LineColFun{4, 16, "bar"}; + const auto BarRet = LineColFun{4, 32, "bar"}; + const auto FooFile = LineColFun{6, 16, "foo"}; + const auto FooRet = LineColFun{6, 49, "foo"}; + const auto MainFile = LineColFun{9, 9, "main"}; + const auto MainReturn = LineColFun{13, 3, "main"}; + GroundTruth.insert({BarRet, {{BarFile, IOSTATE::ERROR}}}); + GroundTruth.insert({FooRet, {{FooFile, IOSTATE::OPENED}}}); + GroundTruth.insert({MainReturn, + {{BarFile, IOSTATE::ERROR}, + {FooFile, IOSTATE::ERROR}, + {MainFile, IOSTATE::ERROR}}}); + compareResults(GroundTruth, Llvmtssolver); } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_12) { - initialize({PathToLlFiles + "typestate_12_c.ll"}); + initialize({PathToLlFiles + "typestate_12_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); - const std::map> Gt = { - // At exit in bar() - {6, - { - {"2", IOSTATE::OPENED}, - //{"10", IOSTATE::OPENED} // 6 has no information about 10, as it - // always completes before - }}, - // At exit in foo() - {8, {{"2", IOSTATE::OPENED}, {"10", IOSTATE::OPENED}}}, - // At exit in main() - {16, {{"2", IOSTATE::CLOSED}, {"10", IOSTATE::CLOSED}}}}; - compareResults(Gt, Llvmtssolver); + + GroundTruthMapTy GroundTruth; + const auto BarFile = LineColFun{5, 9, "bar"}; + const auto BarRet = LineColFun{7, 3, "bar"}; + const auto AfterFoo = LineColFun{15, 3, "main"}; + const auto MainFile = LineColFun{13, 9, "main"}; + const auto MainReturn = LineColFun{17, 3, "main"}; + GroundTruth.insert({BarRet, {{BarFile, IOSTATE::OPENED}}}); + GroundTruth.insert( + {AfterFoo, {{MainFile, IOSTATE::OPENED}, {BarFile, IOSTATE::OPENED}}}); + GroundTruth.insert( + {MainReturn, {{MainFile, IOSTATE::CLOSED}, {BarFile, IOSTATE::CLOSED}}}); + compareResults(GroundTruth, Llvmtssolver); } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_13) { - initialize({PathToLlFiles + "typestate_13_c.ll"}); + initialize({PathToLlFiles + "typestate_13_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); - const std::map> Gt = { - // Before first fclose() - {8, {{"3", IOSTATE::OPENED}}}, - // Before second fclose() - {10, {{"3", IOSTATE::CLOSED}}}, - // At exit in main() - {11, {{"3", IOSTATE::ERROR}}}}; - compareResults(Gt, Llvmtssolver); + + GroundTruthMapTy GroundTruth; + const auto File = LineColFun{4, 9, "main"}; + const auto BeforeFirstFClose = LineColFun{7, 3, "main"}; + const auto BeforeSecondFClose = LineColFun{8, 3, "main"}; + const auto Return = LineColFun{10, 3, "main"}; + GroundTruth.insert({BeforeFirstFClose, {{File, IOSTATE::OPENED}}}); + GroundTruth.insert({BeforeSecondFClose, {{File, IOSTATE::CLOSED}}}); + GroundTruth.insert({Return, {{File, IOSTATE::ERROR}}}); + compareResults(GroundTruth, Llvmtssolver); } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_14) { - initialize({PathToLlFiles + "typestate_14_c.ll"}); + initialize({PathToLlFiles + "typestate_14_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); - const std::map> Gt = { - // Before first fopen() - {7, {{"5", IOSTATE::UNINIT}}}, - // Before second fopen() - {9, {{"5", IOSTATE::OPENED}}}, - // After second store - {11, - {{"5", IOSTATE::OPENED}, - {"7", IOSTATE::OPENED}, - {"9", IOSTATE::OPENED}}}, - // At exit in main() - {11, - {{"5", IOSTATE::CLOSED}, - {"7", IOSTATE::CLOSED}, - {"9", IOSTATE::CLOSED}}}}; - compareResults(Gt, Llvmtssolver); + + GroundTruthMapTy GroundTruth; + const auto File = LineColFun{4, 9, "main"}; + const auto BeforeFirstFOpen = LineColFun{5, 5, "main"}; + const auto BeforeSecondFOpen = LineColFun{6, 5, "main"}; + const auto BeforeFClose = LineColFun{7, 3, "main"}; + const auto Return = LineColFun{9, 3, "main"}; + GroundTruth.insert({BeforeFirstFOpen, {{File, IOSTATE::UNINIT}}}); + GroundTruth.insert({BeforeSecondFOpen, {{File, IOSTATE::OPENED}}}); + GroundTruth.insert({BeforeFClose, + {{File, IOSTATE::OPENED}, + {LineColFun{5, 7, "main"}, IOSTATE::OPENED}, + {LineColFun{6, 7, "main"}, IOSTATE::OPENED}}}); + GroundTruth.insert({Return, + {{File, IOSTATE::CLOSED}, + {LineColFun{5, 7, "main"}, IOSTATE::CLOSED}, + {LineColFun{6, 7, "main"}, IOSTATE::CLOSED}}}); + compareResults(GroundTruth, Llvmtssolver); } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_15) { - initialize({PathToLlFiles + "typestate_15_c.ll"}); + initialize({PathToLlFiles + "typestate_15_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); - const std::map> Gt = { - // After store of ret val of first fopen() - {9, - { - {"5", IOSTATE::OPENED}, {"7", IOSTATE::OPENED}, - // for 9, 11, 13 state is top - // {"9", IOSTATE::OPENED}, - // {"11", IOSTATE::OPENED}, - // {"13", IOSTATE::OPENED} - }}, - // After first fclose() - {11, - { - {"5", IOSTATE::CLOSED}, - {"7", IOSTATE::CLOSED}, - {"9", IOSTATE::CLOSED}, - // for 11 and 13 state is top - // {"11", IOSTATE::CLOSED}, - // {"13", IOSTATE::CLOSED} - }}, - // After second fopen() but before storing ret val - {12, - { - {"5", IOSTATE::CLOSED}, - {"7", IOSTATE::CLOSED}, - {"9", IOSTATE::CLOSED}, - {"11", IOSTATE::OPENED}, - // for 13 state is top - //{"13", IOSTATE::CLOSED} - }}, - // After storing ret val of second fopen() - {13, - { - {"5", IOSTATE::OPENED}, - {"7", IOSTATE::CLOSED}, // 7 and 9 do not alias 11 - {"9", IOSTATE::CLOSED}, - {"11", IOSTATE::OPENED}, - // for 13 state is top - //{"13", IOSTATE::OPENED} - }}, - // At exit in main() - {15, - {{"5", IOSTATE::CLOSED}, - // Due to flow-insensitive alias information, the - // closed file-handle (which has ID 13) may alias - // the closed file handles 7 and 9. Hence closed - // + closed gives error for 7 and 9 => false positive - {"7", IOSTATE::ERROR}, - {"9", IOSTATE::ERROR}, - {"11", IOSTATE::CLOSED}, - {"13", IOSTATE::CLOSED}}}}; - compareResults(Gt, Llvmtssolver); + + GroundTruthMapTy GroundTruth; + // 5: %f = alloca ptr, align 8 + const auto File = LineColFun{4, 9, "main"}; + // %call = call noalias ptr @fopen + const auto FOpen = LineColFun{5, 7, "main"}; + // %0 = load ptr, ptr %f, align 8 + const auto LoadFile = LineColFun{6, 10, "main"}; + // %call2 = call noalias ptr @fopen + const auto SecondFOpen = LineColFun{7, 7, "main"}; + // store ptr %call2, ptr %f, align 8 + const auto StoreSecondFOpen = LineColFun{7, 5, "main"}; + // %1 = load ptr, ptr %f, align 8 + const auto SecondLoadFile = LineColFun{8, 10, "main"}; + // ret i32 0 + const auto Return = LineColFun{10, 3, "main"}; + + GroundTruth.insert( + {LoadFile, {{File, IOSTATE::OPENED}, {FOpen, IOSTATE::OPENED}}}); + GroundTruth.insert({SecondFOpen, + {{File, IOSTATE::CLOSED}, + {FOpen, IOSTATE::CLOSED}, + {LoadFile, IOSTATE::CLOSED}}}); + GroundTruth.insert({StoreSecondFOpen, + {{File, IOSTATE::CLOSED}, + {FOpen, IOSTATE::CLOSED}, + {LoadFile, IOSTATE::CLOSED}, + {SecondFOpen, IOSTATE::OPENED}}}); + GroundTruth.insert({SecondLoadFile, + {{File, IOSTATE::OPENED}, + {FOpen, IOSTATE::CLOSED}, + {LoadFile, IOSTATE::CLOSED}, + {SecondFOpen, IOSTATE::OPENED}}}); + GroundTruth.insert({Return, + {{File, IOSTATE::CLOSED}, + {FOpen, IOSTATE::ERROR}, + {LoadFile, IOSTATE::ERROR}, + {SecondFOpen, IOSTATE::CLOSED}, + {SecondLoadFile, IOSTATE::CLOSED}}}); + compareResults(GroundTruth, Llvmtssolver); } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_16) { /// TODO: After the EF fix everything is BOT; --> Make the TSA more precise! - initialize({PathToLlFiles + "typestate_16_c.ll"}); + initialize({PathToLlFiles + "typestate_16_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); - // Llvmtssolver.dumpResults(); - - // auto Pts = PT->getAliasSet(IRDB->getInstruction(2)); - // std::cout << "Alias(2) = {"; - // bool Frst = true; - // for (const auto *P : *Pts) { - // if (Frst) { - // Frst = false; - // } else { - // std::cout << ", "; - // } - // std::cout << llvmIRToShortString(P); - // } - // std::cout << "}" << std::endl; - - const std::map> Gt = { - // At exit in foo() - {16, - { - //{"2", IOSTATE::CLOSED}, - {"2", IOSTATE::BOT} // Overapproximation due to too flat lattice! - // {"18", IOSTATE::CLOSED} // pointsTo information is not sufficient - }}, - // At exit in main() - {24, - {{"2", IOSTATE::BOT}, - {"18", IOSTATE::BOT}}}}; // Overapproximation due to too flat lattice - // (would expect CLOSED for both)! - compareResults(Gt, Llvmtssolver); + + GroundTruthMapTy GroundTruth; + const auto FooFile = LineColFun{4, 16, "foo"}; + const auto FooExit = LineColFun{11, 1, "foo"}; + const auto MainFile = LineColFun{14, 9, "main"}; + const auto MainReturn = LineColFun{19, 3, "main"}; + // At exit in foo() + GroundTruth.insert({FooExit, {{FooFile, IOSTATE::BOT}}}); + // At exit in main() + GroundTruth.insert( + {MainReturn, {{FooFile, IOSTATE::BOT}, {MainFile, IOSTATE::BOT}}}); + compareResults(GroundTruth, Llvmtssolver); } -// TODO: Check this case again! TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_17) { - initialize({PathToLlFiles + "typestate_17_c.ll"}); + initialize({PathToLlFiles + "typestate_17_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); - const std::map> Gt = { - // Before loop - {15, - {{"2", IOSTATE::CLOSED}, - {"9", IOSTATE::CLOSED}, - {"13", IOSTATE::CLOSED}}}, - // Before fgetc() // fgetc(CLOSED)=ERROR join CLOSED = BOT - {17, - { - {"2", IOSTATE::BOT}, {"9", IOSTATE::BOT}, {"13", IOSTATE::BOT}, - // {"16", IOSTATE::BOT} // at 16 we now have ERROR (actually, this is - // correct as well as BOT) - }}, - // At exit in main() - {22, - { - {"2", IOSTATE::BOT}, {"9", IOSTATE::BOT}, {"13", IOSTATE::BOT}, - //{"16", IOSTATE::BOT} // at 16 we now have ERROR (actually, this is - // correct as well as BOT) - }}}; - compareResults(Gt, Llvmtssolver); + GroundTruthMapTy GroundTruth; + const auto FooFile = LineColFun{4, 16, "foo"}; + const auto File = LineColFun{8, 9, "main"}; + const auto FOpenFile = LineColFun{8, 9, "main"}; + const auto BeforeLoop = LineColFun{14, 3, "main"}; + const auto BeforeFGetC = LineColFun{14, 13, "main"}; + const auto MainReturn = LineColFun{17, 3, "main"}; + GroundTruth.insert({BeforeLoop, + {{FooFile, IOSTATE::CLOSED}, + {File, IOSTATE::CLOSED}, + {FOpenFile, IOSTATE::CLOSED}}}); + GroundTruth.insert({BeforeFGetC, + {{FooFile, IOSTATE::BOT}, + {File, IOSTATE::BOT}, + {FOpenFile, IOSTATE::BOT}}}); + GroundTruth.insert({MainReturn, + {{FooFile, IOSTATE::BOT}, + {File, IOSTATE::BOT}, + {FOpenFile, IOSTATE::BOT}}}); + compareResults(GroundTruth, Llvmtssolver); } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_18) { /// TODO: After the EF fix everything is BOT; --> Make the TSA more precise! - initialize({PathToLlFiles + "typestate_18_c.ll"}); + initialize({PathToLlFiles + "typestate_18_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); - const std::map> Gt = { - // At exit in foo() - {17, - { - //{"2", IOSTATE::CLOSED}, - {"2", IOSTATE::BOT}, // Overapproximation due to too flat lattice! - // {"19", IOSTATE::CLOSED} // pointsTo information not sufficient - }}, - // At exit in main() - {25, - {{"2", IOSTATE::BOT}, - {"19", IOSTATE::BOT}}}}; // Overapproximation due to too flat lattice - // (would expect CLOSED for both)! - compareResults(Gt, Llvmtssolver); + + GroundTruthMapTy GroundTruth; + const auto FooReturn = LineColFun{11, 1, "foo"}; + const auto FooFile = LineColFun{4, 16, "foo"}; + const auto MainFile = LineColFun{14, 9, "main"}; + const auto MainReturn = LineColFun{19, 3, "main"}; + GroundTruth.insert({FooReturn, {{FooFile, IOSTATE::BOT}}}); + GroundTruth.insert( + {MainReturn, {{MainFile, IOSTATE::BOT}, {FooFile, IOSTATE::BOT}}}); + compareResults(GroundTruth, Llvmtssolver); } -// TODO: Check this case again! TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_19) { - initialize({PathToLlFiles + "typestate_19_c.ll"}); + initialize({PathToLlFiles + "typestate_19_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); - const std::map> Gt = { - {11, {{"8", IOSTATE::UNINIT}}}, - {14, {{"8", IOSTATE::BOT}}}, - // At exit in main() - {25, {{"2", IOSTATE::CLOSED}, {"8", IOSTATE::CLOSED}}}}; - compareResults(Gt, Llvmtssolver); + + GroundTruthMapTy GroundTruth; + const auto FooFile = LineColFun{4, 16, "foo"}; + const auto MainFile = LineColFun{7, 9, "main"}; + const auto WhileCond = LineColFun{11, 3, "main"}; + const auto StoreCall = LineColFun{11, 13, "main"}; + const auto MainReturn = LineColFun{18, 3, "main"}; + + GroundTruth.insert({WhileCond, {{MainFile, IOSTATE::UNINIT}}}); + GroundTruth.insert({StoreCall, {{MainFile, IOSTATE::BOT}}}); + GroundTruth.insert( + {MainReturn, {{FooFile, IOSTATE::CLOSED}, {MainFile, IOSTATE::CLOSED}}}); + compareResults(GroundTruth, Llvmtssolver); } // main function for the test case diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLEVPKDFTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLEVPKDFTest.cpp index bc74fadfda..c801682777 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLEVPKDFTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLEVPKDFTest.cpp @@ -14,7 +14,6 @@ #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFCTXDescription.h" #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLEVPKDFDescription.h" #include "phasar/PhasarLLVM/HelperAnalyses.h" -#include "phasar/PhasarLLVM/Passes/ValueAnnotationPass.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h" #include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" @@ -25,8 +24,8 @@ #include -using namespace std; using namespace psr; +using namespace psr::unittest; /* ============== TEST FIXTURE ============== */ class IDETSAnalysisOpenSSLEVPKDFTest : public ::testing::Test { @@ -40,9 +39,11 @@ class IDETSAnalysisOpenSSLEVPKDFTest : public ::testing::Test { OpenSSLEVPKDFDescription OpenSSLEVPKDFDesc{}; std::optional> TSProblem; std::optional> TSKDFProblem; - unique_ptr>> + std::unique_ptr< + IDESolver>> Llvmtssolver; - unique_ptr>> + std::unique_ptr< + IDESolver>> KdfSolver; // enum OpenSSLEVPKDFCTXState { @@ -54,8 +55,6 @@ class IDETSAnalysisOpenSSLEVPKDFTest : public ::testing::Test { // ERROR = 4, // BOT = 0 // }; - IDETSAnalysisOpenSSLEVPKDFTest() = default; - ~IDETSAnalysisOpenSSLEVPKDFTest() override = default; void initialize(const llvm::Twine &IRFile) { HA.emplace(PathToLlFiles + IRFile, EntryPoints); @@ -64,7 +63,7 @@ class IDETSAnalysisOpenSSLEVPKDFTest : public ::testing::Test { createAnalysisProblem>( *HA, &OpenSSLEVPKDFDesc, EntryPoints); - KdfSolver = make_unique< + KdfSolver = std::make_unique< IDESolver>>( *TSKDFProblem, &HA->getICFG()); @@ -74,17 +73,13 @@ class IDETSAnalysisOpenSSLEVPKDFTest : public ::testing::Test { IDETypeStateAnalysis>( *HA, &*OpenSSLEVPKeyDerivationDesc, EntryPoints); - Llvmtssolver = make_unique< + Llvmtssolver = std::make_unique< IDESolver>>( *TSProblem, &HA->getICFG()); KdfSolver->solve(); Llvmtssolver->solve(); } - void SetUp() override { ValueAnnotationPass::resetValueID(); } - - void TearDown() override {} - /** * We map instruction id to value for the ground truth. ID has to be * a string since Argument ID's are not integer type (e.g. main.0 for diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLSecureHeapTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLSecureHeapTest.cpp index a4cc5eb869..92a05db2a3 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLSecureHeapTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLSecureHeapTest.cpp @@ -14,7 +14,6 @@ #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h" #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureHeapDescription.h" #include "phasar/PhasarLLVM/HelperAnalyses.h" -#include "phasar/PhasarLLVM/Passes/ValueAnnotationPass.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h" #include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" @@ -28,8 +27,8 @@ #include #include -using namespace std; using namespace psr; +using namespace psr::unittest; /* ============== TEST FIXTURE ============== */ class IDETSAnalysisOpenSSLSecureHeapTest : public ::testing::Test { @@ -43,10 +42,10 @@ class IDETSAnalysisOpenSSLSecureHeapTest : public ::testing::Test { std::optional Desc; std::optional> TSProblem; std::optional SecureHeapPropagationProblem; - unique_ptr< + std::unique_ptr< IDESolver>> Llvmtssolver; - unique_ptr> + std::unique_ptr> SecureHeapPropagationResults; enum OpenSSLSecureHeapState { TOP = 42, @@ -57,8 +56,6 @@ class IDETSAnalysisOpenSSLSecureHeapTest : public ::testing::Test { FREED = 4, ERROR = 5 }; - IDETSAnalysisOpenSSLSecureHeapTest() = default; - ~IDETSAnalysisOpenSSLSecureHeapTest() override = default; void initialize(const llvm::Twine &IRFile) { HA.emplace(IRFile, EntryPoints); @@ -66,14 +63,14 @@ class IDETSAnalysisOpenSSLSecureHeapTest : public ::testing::Test { SecureHeapPropagationProblem = createAnalysisProblem(*HA, EntryPoints); SecureHeapPropagationResults = - make_unique>( + std::make_unique>( *SecureHeapPropagationProblem, &HA->getICFG()); Desc.emplace(*SecureHeapPropagationResults); TSProblem = createAnalysisProblem< IDETypeStateAnalysis>(*HA, &*Desc, EntryPoints); - Llvmtssolver = make_unique< + Llvmtssolver = std::make_unique< IDESolver>>( *TSProblem, &HA->getICFG()); @@ -81,10 +78,6 @@ class IDETSAnalysisOpenSSLSecureHeapTest : public ::testing::Test { Llvmtssolver->solve(); } - void SetUp() override { ValueAnnotationPass::resetValueID(); } - - void TearDown() override {} - /** * We map instruction id to value for the ground truth. ID has to be * a string since Argument ID's are not integer type (e.g. main.0 for diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLSecureMemoryTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLSecureMemoryTest.cpp index 558c8007c4..c8e7bd9369 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLSecureMemoryTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisOpenSSLSecureMemoryTest.cpp @@ -13,7 +13,6 @@ #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h" #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureMemoryDescription.h" #include "phasar/PhasarLLVM/HelperAnalyses.h" -#include "phasar/PhasarLLVM/Passes/ValueAnnotationPass.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h" #include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" @@ -25,8 +24,8 @@ #include #include -using namespace std; using namespace psr; +using namespace psr::unittest; /* ============== TEST FIXTURE ============== */ class IDETSAnalysisOpenSSLSecureMemoryTest : public ::testing::Test { @@ -38,7 +37,8 @@ class IDETSAnalysisOpenSSLSecureMemoryTest : public ::testing::Test { std::optional HA; OpenSSLSecureMemoryDescription Desc{}; std::optional> TSProblem; - unique_ptr>> + std::unique_ptr< + IDESolver_P>> Llvmtssolver; enum OpenSSLSecureMemoryState { @@ -49,8 +49,6 @@ class IDETSAnalysisOpenSSLSecureMemoryTest : public ::testing::Test { ERROR = 3, ALLOCATED = 4 }; - IDETSAnalysisOpenSSLSecureMemoryTest() = default; - ~IDETSAnalysisOpenSSLSecureMemoryTest() override = default; void initialize(const llvm::Twine &&IRFile) { HA.emplace(IRFile, EntryPoints); @@ -58,17 +56,13 @@ class IDETSAnalysisOpenSSLSecureMemoryTest : public ::testing::Test { TSProblem = createAnalysisProblem< IDETypeStateAnalysis>(*HA, &Desc, EntryPoints); - Llvmtssolver = make_unique< + Llvmtssolver = std::make_unique< IDESolver_P>>( *TSProblem, &HA->getICFG()); Llvmtssolver->solve(); } - void SetUp() override { ValueAnnotationPass::resetValueID(); } - - void TearDown() override {} - /** * We map instruction id to value for the ground truth. ID has to be * a string since Argument ID's are not integer type (e.g. main.0 for diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp index b36430c3c6..04f564ac70 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp @@ -5,21 +5,23 @@ #include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" #include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/HelperAnalyses.h" -#include "phasar/PhasarLLVM/Passes/ValueAnnotationPass.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h" #include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" +#include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" +#include "llvm/Support/Casting.h" +#include "SrcCodeLocationEntry.h" #include "TestConfig.h" #include "gtest/gtest.h" -#include +#include -using namespace std; using namespace psr; +using namespace psr::unittest; /* ============== TEST FIXTURE ============== */ @@ -33,16 +35,11 @@ class IFDSConstAnalysisTest : public ::testing::Test { std::optional Constproblem; std::vector RetOrResInstructions; - IFDSConstAnalysisTest() = default; - ~IFDSConstAnalysisTest() override = default; - void initialize(const llvm::Twine &IRFile) { HA.emplace(IRFile, EntryPoints); Constproblem = createAnalysisProblem(*HA, EntryPoints); } - void SetUp() override { ValueAnnotationPass::resetValueID(); } - llvm::ArrayRef getRetOrResInstructions() { if (!RetOrResInstructions.empty()) { return RetOrResInstructions; @@ -59,26 +56,38 @@ class IFDSConstAnalysisTest : public ::testing::Test { return RetOrResInstructions; } - void compareResults(const std::set &GroundTruth, - IFDSSolver_P &Solver) { + void compareResultsImpl(const std::set &GroundTruth, + IFDSSolver_P &Solver) { std::set AllMutableAllocas; + for (const auto *RR : getRetOrResInstructions()) { std::set Facts = Solver.ifdsResultsAt(RR); for (const auto *Fact : Facts) { if (isAllocaInstOrHeapAllocaFunction(Fact) || (llvm::isa(Fact) && !Constproblem->isZeroValue(Fact))) { - + llvm::outs() << "Found *Fact: " << *Fact << "\n"; AllMutableAllocas.insert(Fact); } } } - std::set MutableIDs; - for (const auto *Memloc : AllMutableAllocas) { - std::cerr << "> Is Mutable: " << llvmIRToShortString(Memloc) << "\n"; - MutableIDs.insert(std::stoul(getMetaDataID(Memloc))); - } - EXPECT_EQ(GroundTruth, MutableIDs); + + EXPECT_EQ(GroundTruth, AllMutableAllocas); + } + + void compareResults(const std::set &GroundTruth, + IFDSSolver_P &Solver) { + auto GroundTruthEntries = + convertTestingLocationSetInIR(GroundTruth, HA->getProjectIRDB()); + + compareResultsImpl(GroundTruthEntries, Solver); + } + void compareResults(std::initializer_list GroundTruth, + IFDSSolver_P &Solver) { + auto GroundTruthEntries = + convertTestingLocationSetInIR(GroundTruth, HA->getProjectIRDB()); + + compareResultsImpl(GroundTruthEntries, Solver); } }; @@ -87,28 +96,35 @@ TEST_F(IFDSConstAnalysisTest, HandleBasicTest_01) { initialize({PathToLlFiles + "basic/basic_01_cpp_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({}, Llvmconstsolver); + std::set GroundTruth; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, HandleBasicTest_02) { initialize({PathToLlFiles + "basic/basic_02_cpp_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({1}, Llvmconstsolver); + auto Entry = LineColFun{3, 0, "main"}; + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, HandleBasicTest_03) { initialize({PathToLlFiles + "basic/basic_03_cpp_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({1}, Llvmconstsolver); + auto Entry = LineColFun{3, 0, "main"}; + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, HandleBasicTest_04) { initialize({PathToLlFiles + "basic/basic_04_cpp_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({1}, Llvmconstsolver); + auto Entry = LineColFun{3, 0, "main"}; + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } /* ============== CONTROL FLOW TESTS ============== */ @@ -116,35 +132,44 @@ TEST_F(IFDSConstAnalysisTest, HandleCFForTest_01) { initialize({PathToLlFiles + "control_flow/cf_for_01_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({0}, Llvmconstsolver); + auto Entry = LineColFun{3, 12, "main"}; + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, HandleCFForTest_02) { initialize({PathToLlFiles + "control_flow/cf_for_02_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({1}, Llvmconstsolver); + auto Entry = LineColFun{4, 12, "main"}; + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, HandleCFIfTest_01) { initialize({PathToLlFiles + "control_flow/cf_if_01_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({1}, Llvmconstsolver); + auto Entry = LineColFun{4, 12, "main"}; + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, HandleCFIfTest_02) { initialize({PathToLlFiles + "control_flow/cf_if_02_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({}, Llvmconstsolver); + std::set GroundTruth{}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, HandleCFWhileTest_01) { initialize({PathToLlFiles + "control_flow/cf_while_01_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({1}, Llvmconstsolver); + auto Entry = LineColFun{5, 12, "main"}; + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } /* ============== POINTER TESTS ============== */ @@ -152,14 +177,18 @@ TEST_F(IFDSConstAnalysisTest, HandlePointerTest_01) { initialize({PathToLlFiles + "pointer/pointer_01_cpp_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({1}, Llvmconstsolver); + auto Entry = LineColFun{3, 0, "main"}; + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, HandlePointerTest_02) { initialize({PathToLlFiles + "pointer/pointer_02_cpp_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({1}, Llvmconstsolver); + auto Entry = LineColFun{3, 0, "main"}; + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, DISABLED_HandlePointerTest_03) { @@ -168,14 +197,18 @@ TEST_F(IFDSConstAnalysisTest, DISABLED_HandlePointerTest_03) { initialize({PathToLlFiles + "pointer/pointer_03_cpp_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({2, 3}, Llvmconstsolver); + auto Entry = LineColFun{4, 0, "main"}; + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, HandlePointerTest_04) { initialize({PathToLlFiles + "pointer/pointer_04_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({3}, Llvmconstsolver); + auto Entry = LineColFun{5, 7, "main"}; + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } /* ============== GLOBAL TESTS ============== */ @@ -183,14 +216,19 @@ TEST_F(IFDSConstAnalysisTest, HandleGlobalTest_01) { initialize({PathToLlFiles + "global/global_01_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({0}, Llvmconstsolver); + auto Entry = GlobalVar{"g1"}; + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, HandleGlobalTest_02) { initialize({PathToLlFiles + "global/global_02_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({0, 1}, Llvmconstsolver); + auto Entry = GlobalVar{"g"}; + auto EntryTwo = LineColFun{4, 7, "main"}; + std::set GroundTruth{Entry, EntryTwo}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, HandleGlobalTest_03) { @@ -198,8 +236,11 @@ TEST_F(IFDSConstAnalysisTest, HandleGlobalTest_03) { IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - /// The @llvm.global_ctors global variable is never immutable - compareResults({0, /*1,*/ 2}, Llvmconstsolver); + auto Entry = LineColFun{6, 10, "__cxx_global_var_init"}; + auto EntryTwo = GlobalVar{"g"}; + + std::set GroundTruth{Entry, EntryTwo}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, DISABLED_HandleGlobalTest_04) { @@ -208,7 +249,9 @@ TEST_F(IFDSConstAnalysisTest, DISABLED_HandleGlobalTest_04) { initialize({PathToLlFiles + "global/global_04_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({0, 4}, Llvmconstsolver); + auto Entry = GlobalVar{"g1"}; + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } /* ============== CALL TESTS ============== */ @@ -216,21 +259,28 @@ TEST_F(IFDSConstAnalysisTest, HandleCallParamTest_01) { initialize({PathToLlFiles + "call/param/call_param_01_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({5}, Llvmconstsolver); + auto Entry = LineColFun{5, 0, "main"}; + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, HandleCallParamTest_02) { initialize({PathToLlFiles + "call/param/call_param_02_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({5}, Llvmconstsolver); + auto Entry = LineColFun{5, 0, "main"}; + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, HandleCallParamTest_03) { initialize({PathToLlFiles + "call/param/call_param_03_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({}, Llvmconstsolver); + // auto Entry = LineColFun{, , "main"}; + // std::set GroundTruth{Entry}; + std::set GroundTruth{}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, DISABLED_HandleCallParamTest_04) { @@ -248,7 +298,7 @@ TEST_F(IFDSConstAnalysisTest, DISABLED_HandleCallParamTest_05) { initialize({PathToLlFiles + "call/param/call_param_05_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({2}, Llvmconstsolver); + compareResults({}, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, HandleCallParamTest_06) { @@ -262,14 +312,18 @@ TEST_F(IFDSConstAnalysisTest, HandleCallParamTest_07) { initialize({PathToLlFiles + "call/param/call_param_07_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({6}, Llvmconstsolver); + auto Entry = LineColFun{6, 12, "main"}; + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, HandleCallParamTest_08) { initialize({PathToLlFiles + "call/param/call_param_08_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({4}, Llvmconstsolver); + auto Entry = LineColFun{9, 0, "main"}; + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, HandleCallReturnTest_01) { @@ -283,14 +337,18 @@ TEST_F(IFDSConstAnalysisTest, HandleCallReturnTest_02) { initialize({PathToLlFiles + "call/return/call_ret_02_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({0}, Llvmconstsolver); + auto Entry = LineColFun{3, 12, "_Z3foov"}; + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, HandleCallReturnTest_03) { initialize({PathToLlFiles + "call/return/call_ret_03_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({0}, Llvmconstsolver); + auto Entry = LineColFun{3, 12, "_Z3foov"}; + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } /* ============== ARRAY TESTS ============== */ @@ -328,7 +386,9 @@ TEST_F(IFDSConstAnalysisTest, HandleArrayTest_05) { initialize({PathToLlFiles + "array/array_05_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({1}, Llvmconstsolver); + auto Entry = LineColFun{3, 0, "main"}; + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, HandleArrayTest_06) { @@ -336,7 +396,9 @@ TEST_F(IFDSConstAnalysisTest, HandleArrayTest_06) { IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); HA->getAliasInfo().print(llvm::errs()); - compareResults({1}, Llvmconstsolver); + auto Entry = LineColFun{3, 0, "main"}; + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, DISABLED_HandleArrayTest_07) { @@ -359,7 +421,9 @@ TEST_F(IFDSConstAnalysisTest, HandleArrayTest_09) { initialize({PathToLlFiles + "array/array_09_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({0}, Llvmconstsolver); + auto Entry = LineColFun{3, 0, "main"}; + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } /* ============== STL ARRAY TESTS ============== */ @@ -374,7 +438,12 @@ TEST_F(IFDSConstAnalysisTest, HandleSTLArrayTest_02) { initialize({PathToLlFiles + "array/stl_array/stl_array_02_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({0, 1}, Llvmconstsolver); + std::set GroundTruth = { + LineColFun{4, 0, "main"}, + GlobalVar{"__const.main.a"}, + }; + + compareResults(GroundTruth, Llvmconstsolver); } PHASAR_SKIP_TEST(TEST_F(IFDSConstAnalysisTest, HandleSTLArrayTest_03) { @@ -384,7 +453,13 @@ PHASAR_SKIP_TEST(TEST_F(IFDSConstAnalysisTest, HandleSTLArrayTest_03) { initialize({PathToLlFiles + "array/stl_array/stl_array_03_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({0, 1, 2}, Llvmconstsolver); + compareResults( + { + GlobalVar{"__const.main.a"}, + GlobalVar{".str"}, + LineColFun{4, 0, "main"}, + }, + Llvmconstsolver); }) TEST_F(IFDSConstAnalysisTest, DISABLED_HandleSTLArrayTest_04) { @@ -407,7 +482,9 @@ TEST_F(IFDSConstAnalysisTest, HandleSTLArrayTest_06) { initialize({PathToLlFiles + "array/stl_array/stl_array_06_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({2}, Llvmconstsolver); + auto Entry = LineColFun{4, 0, "main"}; + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } /* ============== CSTRING TESTS ============== */ @@ -424,7 +501,9 @@ TEST_F(IFDSConstAnalysisTest, DISABLED_HandleCStringTest_02) { initialize({PathToLlFiles + "array/cstring/cstring_02_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({2}, Llvmconstsolver); + auto Entry = LineColFun{4, 0, "main"}; + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } /* ============== STRUCTURE TESTS ============== */ diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp index e050acc5dc..8b60573548 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp @@ -2,22 +2,25 @@ #include "phasar/DataFlow/IfdsIde/Solver/IFDSSolver.h" #include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" -#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/HelperAnalyses.h" -#include "phasar/PhasarLLVM/Passes/ValueAnnotationPass.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h" #include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" #include "phasar/PhasarLLVM/TaintConfig/LLVMTaintConfig.h" #include "phasar/PhasarLLVM/TaintConfig/TaintConfigBase.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" +#include "phasar/Utils/DebugOutput.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Value.h" + +#include "SrcCodeLocationEntry.h" #include "TestConfig.h" #include "gtest/gtest.h" -#include - -using namespace std; using namespace psr; +using namespace psr::unittest; /* ============== TEST FIXTURE ============== */ @@ -32,9 +35,6 @@ class IFDSTaintAnalysisTest : public ::testing::Test { std::optional TaintProblem; std::optional TSF; - IFDSTaintAnalysisTest() = default; - ~IFDSTaintAnalysisTest() override = default; - static LLVMTaintConfig getDefaultConfig() { auto SourceCB = [](const llvm::Instruction *Inst) { std::set Ret; @@ -78,113 +78,120 @@ class IFDSTaintAnalysisTest : public ::testing::Test { if (!TSF) { TSF = getDefaultConfig(); } + TaintProblem = createAnalysisProblem(*HA, &*TSF, EntryPoints); } - static void doAnalysis(const llvm::Twine &IRFile, - const LLVMTaintConfig &Config, - const map> &GroundTruth) { - HelperAnalyses HA(PathToLlFiles + IRFile, EntryPoints); - - auto TaintProblem = - createAnalysisProblem(HA, &Config, EntryPoints); - - IFDSSolver TaintSolver(TaintProblem, &HA.getICFG()); - TaintSolver.solve(); - - TaintSolver.dumpResults(); - - compare(TaintProblem.Leaks, GroundTruth); + void initialize(const llvm::Twine &IRFile, const LLVMTaintConfig *Config) { + HA.emplace(IRFile, EntryPoints); + TaintProblem = + createAnalysisProblem(*HA, Config, EntryPoints); } - static void doAnalysis(const llvm::Twine &IRFile, - const map> &GroundTruth) { - doAnalysis(IRFile, getDefaultConfig(), GroundTruth); - } + using GroundTruthTy = + std::map>; template - static void compare(const LeaksTy &Leaks, - const map> &GroundTruth) { - map> FoundLeaks; - for (const auto &Leak : Leaks) { - int SinkId = stoi(getMetaDataID(Leak.first)); - set LeakedValueIds; - for (const auto *LV : Leak.second) { - LeakedValueIds.insert(getMetaDataID(LV)); - } - FoundLeaks.insert(make_pair(SinkId, LeakedValueIds)); - } - EXPECT_EQ(FoundLeaks, GroundTruth); + void compare(const LeaksTy &Leaks, const GroundTruthTy &GroundTruth) { + auto GroundTruthEntries = + convertTestingLocationSetMapInIR(GroundTruth, HA->getProjectIRDB()); + + EXPECT_EQ(Leaks, GroundTruthEntries) + << "Taint Leaks do not match:\n Expected: " + << PrettyPrinter{GroundTruthEntries} + << "\n Got: " << PrettyPrinter{Leaks}; } - void compareResults(const map> &GroundTruth) noexcept { - compare(TaintProblem->Leaks, GroundTruth); - } }; // Test Fixture TEST_F(IFDSTaintAnalysisTest, TaintTest_01) { initialize({PathToLlFiles + "dummy_source_sink/taint_01_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - map> GroundTruth; - GroundTruth[13] = set{"12"}; - compareResults(GroundTruth); + + auto Entry = LineColFun{6, 3, "main"}; + auto EntryTwo = LineColFun{6, 8, "main"}; + GroundTruthTy GroundTruth{{Entry, {EntryTwo}}}; + + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_01_m2r) { initialize({PathToLlFiles + "dummy_source_sink/taint_01_cpp_m2r_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - map> GroundTruth; - GroundTruth[4] = set{"2"}; - compareResults(GroundTruth); + + auto Entry = LineColFun{6, 3, "main"}; + auto EntryTwo = LineColFun{5, 11, "main"}; + GroundTruthTy GroundTruth{{Entry, {EntryTwo}}}; + + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_02) { initialize({PathToLlFiles + "dummy_source_sink/taint_02_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - map> GroundTruth; - GroundTruth[9] = set{"8"}; - compareResults(GroundTruth); + + auto Entry = LineColFun{5, 3, "main"}; + auto EntryTwo = LineColFun{5, 8, "main"}; + GroundTruthTy GroundTruth{{Entry, {EntryTwo}}}; + + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_03) { initialize({PathToLlFiles + "dummy_source_sink/taint_03_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - map> GroundTruth; - GroundTruth[18] = set{"17"}; - compareResults(GroundTruth); + + auto Entry = LineColFun{6, 3, "main"}; + auto EntryTwo = LineColFun{6, 8, "main"}; + GroundTruthTy GroundTruth{{Entry, {EntryTwo}}}; + + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_04) { initialize({PathToLlFiles + "dummy_source_sink/taint_04_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - map> GroundTruth; - GroundTruth[19] = set{"18"}; - GroundTruth[24] = set{"23"}; - compareResults(GroundTruth); + + auto Entry = LineColFun{6, 3, "main"}; + auto EntryTwo = LineColFun{6, 8, "main"}; + auto EntryThree = LineColFun{8, 3, "main"}; + auto EntryFour = LineColFun{8, 8, "main"}; + GroundTruthTy GroundTruth{ + {Entry, {EntryTwo}}, + {EntryThree, {EntryFour}}, + }; + + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_05) { initialize({PathToLlFiles + "dummy_source_sink/taint_05_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - map> GroundTruth; - GroundTruth[22] = set{"21"}; - compareResults(GroundTruth); + + auto Entry = LineColFun{6, 3, "main"}; + auto EntryTwo = LineColFun{6, 8, "main"}; + GroundTruthTy GroundTruth{{Entry, {EntryTwo}}}; + + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_06) { initialize({PathToLlFiles + "dummy_source_sink/taint_06_cpp_m2r_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - map> GroundTruth; - GroundTruth[5] = set{"main.0"}; - compareResults(GroundTruth); + + auto Entry = LineColFun{5, 3, "main"}; + auto Main0 = ArgInFun{0, "main"}; + GroundTruthTy GroundTruth{{Entry, {Main0}}}; + + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_01) { @@ -192,9 +199,12 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_01) { {PathToLlFiles + "dummy_source_sink/taint_exception_01_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - map> GroundTruth; - GroundTruth[14] = set{"13"}; - compareResults(GroundTruth); + + auto Entry = LineColFun{12, 3, "main"}; + auto EntryTwo = LineColFun{12, 8, "main"}; + GroundTruthTy GroundTruth{{Entry, {EntryTwo}}}; + + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_01_m2r) { @@ -202,9 +212,12 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_01_m2r) { {PathToLlFiles + "dummy_source_sink/taint_exception_01_cpp_m2r_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - map> GroundTruth; - GroundTruth[5] = set{"0"}; - compareResults(GroundTruth); + + auto Entry = LineColFun{12, 3, "main"}; + auto EntryTwo = LineColFun{10, 14, "main"}; + GroundTruthTy GroundTruth{{Entry, {EntryTwo}}}; + + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_02) { @@ -212,9 +225,12 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_02) { {PathToLlFiles + "dummy_source_sink/taint_exception_02_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - map> GroundTruth; - GroundTruth[16] = set{"15"}; - compareResults(GroundTruth); + + auto Entry = LineColFun{11, 3, "main"}; + auto EntryTwo = LineColFun{11, 8, "main"}; + GroundTruthTy GroundTruth{{Entry, {EntryTwo}}}; + + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_03) { @@ -222,10 +238,17 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_03) { {PathToLlFiles + "dummy_source_sink/taint_exception_03_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - map> GroundTruth; - GroundTruth[11] = set{"10"}; - GroundTruth[20] = set{"19"}; - compareResults(GroundTruth); + + auto Entry = LineColFun{11, 3, "main"}; + auto EntryTwo = LineColFun{11, 8, "main"}; + auto EntryThree = LineColFun{14, 3, "main"}; + auto EntryFour = LineColFun{14, 8, "main"}; + GroundTruthTy GroundTruth{ + {Entry, {EntryTwo}}, + {EntryThree, {EntryFour}}, + }; + + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_04) { @@ -233,9 +256,12 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_04) { {PathToLlFiles + "dummy_source_sink/taint_exception_04_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - map> GroundTruth; - GroundTruth[32] = set{"31"}; - compareResults(GroundTruth); + + auto Entry = LineColFun{16, 3, "main"}; + auto EntryTwo = LineColFun{16, 8, "main"}; + GroundTruthTy GroundTruth{{Entry, {EntryTwo}}}; + + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_05) { @@ -244,9 +270,11 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_05) { IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - map> GroundTruth; - GroundTruth[32] = set{"31"}; - compareResults(GroundTruth); + auto Entry = LineColFun{16, 3, "main"}; + auto EntryTwo = LineColFun{16, 8, "main"}; + GroundTruthTy GroundTruth{{Entry, {EntryTwo}}}; + + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_06) { @@ -254,9 +282,12 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_06) { {PathToLlFiles + "dummy_source_sink/taint_exception_06_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - map> GroundTruth; - GroundTruth[14] = set{"13"}; - compareResults(GroundTruth); + + auto Entry = LineColFun{13, 5, "main"}; + auto EntryTwo = LineColFun{13, 10, "main"}; + GroundTruthTy GroundTruth{{Entry, {EntryTwo}}}; + + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_07) { @@ -264,9 +295,12 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_07) { {PathToLlFiles + "dummy_source_sink/taint_exception_07_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - map> GroundTruth; - GroundTruth[30] = set{"29"}; - compareResults(GroundTruth); + + auto Entry = LineColFun{14, 5, "main"}; + auto EntryTwo = LineColFun{14, 10, "main"}; + GroundTruthTy GroundTruth{{Entry, {EntryTwo}}}; + + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_08) { @@ -274,9 +308,12 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_08) { {PathToLlFiles + "dummy_source_sink/taint_exception_08_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - map> GroundTruth; - GroundTruth[32] = set{"31"}; - compareResults(GroundTruth); + + auto Entry = LineColFun{19, 3, "main"}; + auto EntryTwo = LineColFun{19, 8, "main"}; + GroundTruthTy GroundTruth{{Entry, {EntryTwo}}}; + + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_09) { @@ -284,9 +321,12 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_09) { {PathToLlFiles + "dummy_source_sink/taint_exception_09_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - map> GroundTruth; - GroundTruth[62] = set{"61"}; - compareResults(GroundTruth); + + auto Entry = LineColFun{20, 3, "main"}; + auto EntryTwo = LineColFun{20, 8, "main"}; + GroundTruthTy GroundTruth{{Entry, {EntryTwo}}}; + + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_10) { @@ -294,32 +334,50 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_10) { {PathToLlFiles + "dummy_source_sink/taint_exception_10_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - map> GroundTruth; - GroundTruth[60] = set{"59"}; - compareResults(GroundTruth); + + auto Entry = LineColFun{19, 5, "main"}; + auto EntryTwo = LineColFun{19, 10, "main"}; + GroundTruthTy GroundTruth{{Entry, {EntryTwo}}}; + + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_DoubleFree_01) { - doAnalysis("double_free_01_c.ll", getDoubleFreeConfig(), - { - {6, {"5"}}, - }); + auto DoubleFreeConf = getDoubleFreeConfig(); + initialize({PathToLlFiles + "double_free_01_c_dbg.ll"}, &DoubleFreeConf); + IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); + TaintSolver.solve(); + + auto Entry = LineColFun{6, 3, "main"}; + auto EntryTwo = LineColFun{6, 8, "main"}; + GroundTruthTy GroundTruth{{Entry, {EntryTwo}}}; + + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_DoubleFree_02) { - doAnalysis("double_free_02_c.ll", getDoubleFreeConfig(), - { - {11, {"10"}}, - }); + auto DoubleFreeConf = getDoubleFreeConfig(); + initialize({PathToLlFiles + "double_free_02_c_dbg.ll"}, &DoubleFreeConf); + IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); + TaintSolver.solve(); + + auto Entry = LineColFun{8, 3, "main"}; + auto EntryTwo = LineColFun{8, 8, "main"}; + GroundTruthTy GroundTruth{{Entry, {EntryTwo}}}; + + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_LibSummary_01) { initialize({PathToLlFiles + "dummy_source_sink/taint_lib_sum_01_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - map> GroundTruth; - GroundTruth[20] = {"19"}; - compareResults(GroundTruth); + + auto Entry = LineColFun{8, 3, "main"}; + auto EntryTwo = LineColFunOp{8, 8, "main", llvm::Instruction::FPToSI}; + GroundTruthTy GroundTruth{{Entry, {EntryTwo}}}; + + compare(TaintProblem->Leaks, GroundTruth); } int main(int Argc, char **Argv) { diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp index 51d7b04649..c3b1be5260 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp @@ -3,23 +3,23 @@ #include "phasar/DataFlow/IfdsIde/Solver/IFDSSolver.h" #include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" -#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/HelperAnalyses.h" -#include "phasar/PhasarLLVM/Passes/ValueAnnotationPass.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h" #include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" -#include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" +#include "phasar/Utils/DebugOutput.h" -#include "llvm/IR/Module.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Value.h" +#include "SrcCodeLocationEntry.h" #include "TestConfig.h" #include "gtest/gtest.h" -#include #include -using namespace std; using namespace psr; +using namespace psr::unittest; /* ============== TEST FIXTURE ============== */ @@ -33,41 +33,34 @@ class IFDSUninitializedVariablesTest : public ::testing::Test { std::optional UninitProblem; - IFDSUninitializedVariablesTest() = default; - ~IFDSUninitializedVariablesTest() override = default; - void initialize(const llvm::Twine &IRFile) { HA.emplace(IRFile, EntryPoints); UninitProblem = createAnalysisProblem(*HA, EntryPoints); } - void SetUp() override { ValueAnnotationPass::resetValueID(); } - - void TearDown() override {} - - void compareResults(map> &GroundTruth) { + using GroundTruthTy = + std::map>; - map> FoundUninitUses; - for (const auto &Kvp : UninitProblem->getAllUndefUses()) { - auto InstID = stoi(getMetaDataID(Kvp.first)); - set UndefValueIds; - for (const auto *UV : Kvp.second) { - UndefValueIds.insert(getMetaDataID(UV)); - } - FoundUninitUses[InstID] = UndefValueIds; - } + void compareResults(const GroundTruthTy &GroundTruthEntries) { + auto ConvGroundTruth = convertTestingLocationSetMapInIR( + GroundTruthEntries, HA->getProjectIRDB()); - EXPECT_EQ(FoundUninitUses, GroundTruth); + EXPECT_EQ(UninitProblem->getAllUndefUses(), ConvGroundTruth) + << "UndefUses do not match:\n Expected: " + << PrettyPrinter{ConvGroundTruth} + << "\n Got: " << PrettyPrinter{UninitProblem->getAllUndefUses()}; } + }; // Test Fixture TEST_F(IFDSUninitializedVariablesTest, UninitTest_01_SHOULD_NOT_LEAK) { initialize({PathToLlFiles + "all_uninit_cpp_dbg.ll"}); IFDSSolver Solver(*UninitProblem, &HA->getICFG()); Solver.solve(); + // all_uninit.cpp does not contain undef-uses - map> GroundTruth; + GroundTruthTy GroundTruth; compareResults(GroundTruth); } @@ -77,32 +70,36 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_02_SHOULD_LEAK) { Solver.solve(); // binop_uninit uses uninitialized variable i in 'int j = i + 10;' - map> GroundTruth; + GroundTruthTy GroundTruth; + // %4 = load i32, i32* %2, ID: 6 ; %2 is the uninitialized variable i - GroundTruth[6] = {"1"}; // %5 = add nsw i32 %4, 10 ; %4 is undef, since it is loaded from // undefined alloca; not sure if it is necessary to report again - GroundTruth[7] = {"6"}; + const auto Entry = LineColFun{2, 0, "main"}; + const auto EntryTwo = LineColFun{3, 11, "main"}; + const auto EntryThree = LineColFun{3, 13, "main"}; + GroundTruth.insert({EntryTwo, {Entry}}); + GroundTruth.insert({EntryThree, {EntryTwo}}); + compareResults(GroundTruth); } + TEST_F(IFDSUninitializedVariablesTest, UninitTest_03_SHOULD_LEAK) { initialize({PathToLlFiles + "callnoret_c_dbg.ll"}); IFDSSolver Solver(*UninitProblem, &HA->getICFG()); Solver.solve(); // callnoret uses uninitialized variable a in 'return a + 10;' of addTen(int) - map> GroundTruth; + GroundTruthTy GroundTruth; - // %4 = load i32, i32* %2 ; %2 is the parameter a of addTen(int) containing - // undef - GroundTruth[5] = {"0"}; - // The same as in test2: is it necessary to report again? - GroundTruth[6] = {"5"}; - // %5 = load i32, i32* %2 ; %2 is the uninitialized variable a - GroundTruth[16] = {"9"}; - // The same as in test2: is it necessary to report again? (the analysis does - // not) - // GroundTruth[17] = {"16"}; + const auto IntA = LineColFun{7, 7, "main"}; + const auto CopyA = LineColFun{9, 10, "main"}; + const auto ArgA = LineColFun{1, 16, "addTen"}; + const auto LoadA = LineColFun{3, 10, "addTen"}; + const auto Add = LineColFun{3, 12, "addTen"}; + GroundTruth.insert({CopyA, {IntA}}); + GroundTruth.insert({Add, {LoadA}}); + GroundTruth.insert({LoadA, {ArgA}}); compareResults(GroundTruth); } @@ -111,25 +108,31 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_04_SHOULD_NOT_LEAK) { initialize({PathToLlFiles + "ctor_default_cpp_dbg.ll"}); IFDSSolver Solver(*UninitProblem, &HA->getICFG()); Solver.solve(); + // ctor.cpp does not contain undef-uses - map> GroundTruth; + GroundTruthTy GroundTruth; + compareResults(GroundTruth); } - TEST_F(IFDSUninitializedVariablesTest, UninitTest_05_SHOULD_NOT_LEAK) { initialize({PathToLlFiles + "struct_member_init_cpp_dbg.ll"}); IFDSSolver Solver(*UninitProblem, &HA->getICFG()); Solver.solve(); + // struct_member_init.cpp does not contain undef-uses - map> GroundTruth; + GroundTruthTy GroundTruth; + compareResults(GroundTruth); } + TEST_F(IFDSUninitializedVariablesTest, UninitTest_06_SHOULD_NOT_LEAK) { initialize({PathToLlFiles + "struct_member_uninit_cpp_dbg.ll"}); IFDSSolver Solver(*UninitProblem, &HA->getICFG()); Solver.solve(); + // struct_member_uninit.cpp does not contain undef-uses - map> GroundTruth; + GroundTruthTy GroundTruth; + compareResults(GroundTruth); } /**************************************************************************************** @@ -151,12 +154,15 @@ Solver(*UninitProblem, false); Solver.solve(); compareResults(GroundTruth); } *****************************************************************************************/ + TEST_F(IFDSUninitializedVariablesTest, UninitTest_08_SHOULD_NOT_LEAK) { initialize({PathToLlFiles + "global_variable_cpp_dbg.ll"}); IFDSSolver Solver(*UninitProblem, &HA->getICFG()); Solver.solve(); + // global_variable.cpp does not contain undef-uses - map> GroundTruth; + GroundTruthTy GroundTruth; + compareResults(GroundTruth); } /**************************************************************************************** @@ -176,17 +182,19 @@ Solver(*UninitProblem, false); Solver.solve(); compareResults(GroundTruth); } *****************************************************************************************/ + TEST_F(IFDSUninitializedVariablesTest, UninitTest_10_SHOULD_LEAK) { initialize({PathToLlFiles + "return_uninit_cpp_dbg.ll"}); IFDSSolver Solver(*UninitProblem, &HA->getICFG()); Solver.solve(); - UninitProblem->emitTextReport(Solver.getSolverResults(), llvm::outs()); - map> GroundTruth; - //%2 = load i32, i32 %1 - GroundTruth[2] = {"0"}; - // What about this call? - // %3 = call i32 @_Z3foov() - // GroundTruth[8] = {""}; + + GroundTruthTy GroundTruth; + + const auto IntI = LineColFun{2, 7, "_Z3foov"}; + const auto UseOfI = LineColFun{3, 10, "_Z3foov"}; + + GroundTruth.insert({UseOfI, {IntI}}); + compareResults(GroundTruth); } @@ -195,15 +203,21 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_11_SHOULD_NOT_LEAK) { initialize({PathToLlFiles + "sanitizer_cpp_dbg.ll"}); IFDSSolver Solver(*UninitProblem, &HA->getICFG()); Solver.solve(); - map> GroundTruth; + + GroundTruthTy GroundTruth; // all undef-uses are sanitized; // However, the uninitialized variable j is read, which causes the analysis to // report an undef-use // 6 => {2} - GroundTruth[6] = {"2"}; + const auto IntI = LineColFun{3, 7, "main"}; + const auto UseOfI = LineColFun{4, 7, "main"}; + + GroundTruth.insert({UseOfI, {IntI}}); + compareResults(GroundTruth); } + //--------------------------------------------------------------------- // Not relevant any more; Test case covered by UninitTest_11 //--------------------------------------------------------------------- @@ -225,23 +239,40 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_13_SHOULD_NOT_LEAK) { initialize({PathToLlFiles + "sanitizer2_cpp_dbg.ll"}); IFDSSolver Solver(*UninitProblem, &HA->getICFG()); Solver.solve(); + // The undef-uses do not affect the program behaviour, but are of course still // found and reported - map> GroundTruth; - GroundTruth[9] = {"2"}; + GroundTruthTy GroundTruth; + + const auto IntJ = LineColFun{3, 7, "main"}; + const auto LoadJ = LineColFun{5, 7, "main"}; + + GroundTruth.insert({LoadJ, {IntJ}}); + compareResults(GroundTruth); } + TEST_F(IFDSUninitializedVariablesTest, UninitTest_14_SHOULD_LEAK) { initialize({PathToLlFiles + "uninit_c_dbg.ll"}); IFDSSolver Solver(*UninitProblem, &HA->getICFG()); Solver.solve(); - map> GroundTruth; - GroundTruth[14] = {"1"}; - GroundTruth[15] = {"2"}; - GroundTruth[16] = {"14", "15"}; + + GroundTruthTy GroundTruth; + + const auto IntA = LineColFun{2, 7, "main"}; + const auto IntB = LineColFun{3, 7, "main"}; + const auto LoadA = LineColFun{6, 11, "main"}; + const auto Multiply = LineColFun{6, 13, "main"}; + const auto LoadB = LineColFun{6, 15, "main"}; + + GroundTruth.insert({LoadA, {IntA}}); + GroundTruth.insert({LoadB, {IntB}}); + GroundTruth.insert({Multiply, {LoadA, LoadB}}); + compareResults(GroundTruth); } + /**************************************************************************************** * Fails probably due to field-insensitivity * @@ -275,20 +306,28 @@ GroundTruth; compareResults(GroundTruth); } *****************************************************************************************/ + TEST_F(IFDSUninitializedVariablesTest, UninitTest_16_SHOULD_LEAK) { initialize({PathToLlFiles + "growing_example_cpp_dbg.ll"}); IFDSSolver Solver(*UninitProblem, &HA->getICFG()); Solver.solve(); - map> GroundTruth; - // TODO remove GT[11] - GroundTruth[11] = {"0"}; - - GroundTruth[16] = {"2"}; - GroundTruth[18] = {"16"}; - GroundTruth[34] = {"24"}; - + GroundTruthTy GroundTruth; + + const auto ArgX = LineColFun{1, 18, "_Z8functionii"}; + const auto IntI = LineColFun{2, 7, "_Z8functionii"}; + const auto LoadX = LineColFun{3, 11, "_Z8functionii"}; + const auto LoadI = LineColFun{5, 10, "_Z8functionii"}; + const auto Add = LineColFun{5, 12, "_Z8functionii"}; + const auto IntJ = LineColFun{10, 7, "main"}; + const auto LoadJ = LineColFun{12, 16, "main"}; + + // TODO remove GroundTruth.insert({LoadX, ArgX}) below + GroundTruth.insert({LoadX, {ArgX}}); + GroundTruth.insert({LoadI, {IntI}}); + GroundTruth.insert({Add, {LoadI}}); + GroundTruth.insert({LoadJ, {IntJ}}); compareResults(GroundTruth); } @@ -345,42 +384,109 @@ Solver(*UninitProblem, false); Solver.solve(); compareResults(GroundTruth); } *****************************************************************************************/ + TEST_F(IFDSUninitializedVariablesTest, UninitTest_20_SHOULD_LEAK) { initialize({PathToLlFiles + "recursion_cpp_dbg.ll"}); IFDSSolver Solver(*UninitProblem, &HA->getICFG()); Solver.solve(); - map> GroundTruth; - // Leaks at 11 and 14 due to field-insensitivity - GroundTruth[11] = {"2"}; - GroundTruth[14] = {"2"}; + GroundTruthTy GroundTruth; + + // Leaks due to field-insensitivity + + // %1 = load ptr, ptr %x.addr, align 8, !dbg !240, !psr.id !241 | ID: 11 + LineColFun LoadX{4, 12, "_Z3fooRii"}; + // %x.addr = alloca ptr, align 8 + LineColFun ArgAddrX{2, 15, "_Z3fooRii"}; + GroundTruth.insert({LoadX, {ArgAddrX}}); + // %2 = load ptr, ptr %x.addr + LineColFun LoadXTwo{5, 14, "_Z3fooRii"}; + GroundTruth.insert({LoadXTwo, {ArgAddrX}}); + + // Load uninitialized variable + + // %1 = load i32, ptr %j, align 4, !dbg !274, !psr.id !275 | ID: 31 + LineColFun LoadJ{11, 18, "main"}; + // %j = alloca i32, align 4 + LineColFun IntJ{10, 7, "main"}; + GroundTruth.insert({LoadJ, {IntJ}}); - // Load uninitialized variable i - GroundTruth[31] = {"24"}; // Load recursive return-value for returning it - GroundTruth[20] = {"1"}; + + // %4 = load ptr, ptr %retval + LineColFun FooExit{6, 1, "_Z3fooRii"}; + GroundTruth.insert({FooExit, {OperandOf{0, FooExit}}}); // Load return-value of foo in main - GroundTruth[29] = {"28"}; - // Analysis does not check uninit on actualparameters - // GroundTruth[32] = {"31"}; + // %0 = load i32, ptr %call, align 4 + LineColFunOp Load0{10, 11, "main", llvm::Instruction::Load}; + // %call = call noundef nonnull align 4 dereferenceable(4) ptr @_Z3fooRii(ptr + // noundef nonnull align 4 dereferenceable(4) %i, i32 noundef 10) + LineColFunOp CallFooRec{10, 11, "main", llvm::Instruction::Call}; + GroundTruth.insert({Load0, {CallFooRec}}); + // // Load return-value of foo in main + // GroundTruth.insert({FooExit, IntJ}); + + // *********** + // Load recursive return-value for returning it + // GroundTruth.insert({RetOfFoo, IntJ}); + // *********** + + // Load return-value of foo in main + // GroundTruth.insert({IntJ, RetOfFoo}); + compareResults(GroundTruth); } + TEST_F(IFDSUninitializedVariablesTest, UninitTest_21_SHOULD_LEAK) { initialize({PathToLlFiles + "virtual_call_cpp_dbg.ll"}); IFDSSolver Solver(*UninitProblem, &HA->getICFG()); Solver.solve(); - map> GroundTruth = { - {3, {"0"}}, {8, {"5"}}, {10, {"5"}}, {35, {"34"}}, {37, {"17"}}}; + GroundTruthTy GroundTruth; + // %x.addr = alloca ptr, align 8 + const auto FooXAddr = LineColFun{3, 15, "_Z3fooRi"}; + // %0 = load ptr, ptr %x.addr, align 8 + const auto FooXLoad = LineColFun{3, 27, "_Z3fooRi"}; + // %x.addr = alloca ptr, align 8 + const auto BarXAddr = LineColFun{4, 15, "_Z3barRi"}; + // %0 = load ptr, ptr %x.addr, align 8 + const auto Load = LineColFun{5, 3, "_Z3barRi"}; + // %1 = load ptr, ptr %x.addr, align 8 + const auto LoadX = LineColFun{6, 10, "_Z3barRi"}; + + // %j = alloca i32, align 4 + const auto IntJ = LineColFun{16, 7, "main"}; + // %call = call noundef nonnull align 4 dereferenceable(4) ptr %1 + const auto BazCall = LineColFunOp{16, 11, "main", llvm::Instruction::Call}; + + // %2 = load i32, ptr %call, align 4 + const auto SecondLoadInIfEnd = OperandOf{ + // The value operand of the store + 1 - llvm::StoreInst::getPointerOperandIndex(), + LineColFunOp{16, 7, "main", llvm::Instruction::Store}, + }; + // %3 = load i32, ptr %j, align 4 + const auto LoadJ = LineColFun{17, 10, "main"}; + // is passed as a reference, so I isn't being loaded here + // const auto LoadI = + // LineColFun{16, 15, "main"}; + // 3 => {0}; due to field-insensitivity + GroundTruth.insert({FooXLoad, {FooXAddr}}); // 8 => {5}; due to field-insensitivity + GroundTruth.insert({Load, {BarXAddr}}); // 10 => {5}; due to alias-unawareness + GroundTruth.insert({LoadX, {BarXAddr}}); // 35 => {34}; actual leak + GroundTruth.insert({SecondLoadInIfEnd, {BazCall}}); // 37 => {17}; actual leak + GroundTruth.insert({LoadJ, {IntJ}}); + compareResults(GroundTruth); } + int main(int Argc, char **Argv) { ::testing::InitGoogleTest(&Argc, Argv); return RUN_ALL_TESTS(); diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/SparseIDESolverTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/SparseIDESolverTest.cpp index 060f438271..ee0353254a 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/SparseIDESolverTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/SparseIDESolverTest.cpp @@ -194,8 +194,8 @@ static constexpr std::string_view LCATestFiles[] = { }; static constexpr std::string_view TaintTestFiles[] = { - "double_free_01_c.ll", - "double_free_02_c.ll", + "double_free_01_c_dbg.ll", + "double_free_02_c_dbg.ll", }; INSTANTIATE_TEST_SUITE_P(SparseIDETest, LinearConstant, diff --git a/unittests/PhasarLLVM/Pointer/FilteredLLVMAliasSetTest.cpp b/unittests/PhasarLLVM/Pointer/FilteredLLVMAliasSetTest.cpp index ccfb76b605..d7a2eff826 100644 --- a/unittests/PhasarLLVM/Pointer/FilteredLLVMAliasSetTest.cpp +++ b/unittests/PhasarLLVM/Pointer/FilteredLLVMAliasSetTest.cpp @@ -123,8 +123,8 @@ static constexpr std::string_view TaintTestFiles[] = { "dummy_source_sink/taint_exception_09_cpp_dbg.ll", "dummy_source_sink/taint_exception_10_cpp_dbg.ll", // -- double-free - "double_free_01_c.ll", - "double_free_02_c.ll", + "double_free_01_c_dbg.ll", + "double_free_02_c_dbg.ll", }; INSTANTIATE_TEST_SUITE_P(InteractiveIDESolverTest, TaintAnalysis, diff --git a/unittests/PhasarLLVM/TypeHierarchy/CMakeLists.txt b/unittests/PhasarLLVM/TypeHierarchy/CMakeLists.txt index fc190151ac..75f52a91d5 100644 --- a/unittests/PhasarLLVM/TypeHierarchy/CMakeLists.txt +++ b/unittests/PhasarLLVM/TypeHierarchy/CMakeLists.txt @@ -1,5 +1,5 @@ set(PointerSources - DIBasedTypeHierarchySerializationTest.cpp + DIBasedTypeHierarchySerializationTest.cpp DIBasedTypeHierarchyTest.cpp LLVMTypeHierarchySerializationTest.cpp LLVMTypeHierarchyTest.cpp diff --git a/unittests/TestUtils/SrcCodeLocationEntry.h b/unittests/TestUtils/SrcCodeLocationEntry.h new file mode 100644 index 0000000000..c13ca7f8d4 --- /dev/null +++ b/unittests/TestUtils/SrcCodeLocationEntry.h @@ -0,0 +1,450 @@ +#ifndef PHASAR_UNITTESTS_TESTUTILS_SRCCODELOCATIONENTRY_H +#define PHASAR_UNITTESTS_TESTUTILS_SRCCODELOCATIONENTRY_H + +#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" +#include "phasar/PhasarLLVM/Utils/LLVMIRToSrc.h" +#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" +#include "phasar/Utils/Utilities.h" + +#include "llvm/ADT/Hashing.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/InstIterator.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Value.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace psr::unittest { + +struct GlobalVar { + llvm::StringRef Name; + + friend bool operator<(GlobalVar G1, GlobalVar G2) noexcept { + return G1.Name < G2.Name; + } + friend bool operator==(GlobalVar G1, GlobalVar G2) noexcept { + return G1.Name == G2.Name; + } + + [[nodiscard]] std::string str() const { + return std::string("GlobalVar { Name: ") + Name.str() + " }"; + } +}; +struct LineCol { + uint32_t Line{}; + uint32_t Col{}; + + friend bool operator<(LineCol LC1, LineCol LC2) noexcept { + return std::tie(LC1.Line, LC1.Col) < std::tie(LC2.Line, LC2.Col); + } + friend bool operator==(LineCol LC1, LineCol LC2) noexcept { + return std::tie(LC1.Line, LC1.Col) == std::tie(LC2.Line, LC2.Col); + } + [[nodiscard]] std::string str() const { + return std::string("LineCol { Line: ") + std::to_string(Line) + + "; Col: " + std::to_string(Col) + " }"; + } +}; + +struct LineColFunOp { + uint32_t Line{}; + uint32_t Col{}; + llvm::StringRef InFunction{}; + uint32_t OpCode{}; + + friend bool operator<(LineColFunOp LC1, LineColFunOp LC2) noexcept { + return std::tie(LC1.InFunction, LC1.Line, LC1.Col, LC1.OpCode) < + std::tie(LC2.InFunction, LC2.Line, LC2.Col, LC2.OpCode); + } + friend bool operator==(LineColFunOp LC1, LineColFunOp LC2) noexcept { + return std::tie(LC1.Line, LC1.Col, LC1.InFunction, LC1.OpCode) == + std::tie(LC2.Line, LC2.Col, LC2.InFunction, LC2.OpCode); + } + [[nodiscard]] std::string str() const { + return std::string("LineColFunOp { Line: ") + std::to_string(Line) + + "; Col: " + std::to_string(Col) + + "; InFunction: " + InFunction.str() + + "; OpCode: " + llvm::Instruction::getOpcodeName(OpCode) + " }"; + } +}; + +struct LineColFun { + uint32_t Line{}; + uint32_t Col{}; + llvm::StringRef InFunction{}; + + friend bool operator<(LineColFun LC1, LineColFun LC2) noexcept { + return std::tie(LC1.InFunction, LC1.Line, LC1.Col) < + std::tie(LC2.InFunction, LC2.Line, LC2.Col); + } + friend bool operator==(LineColFun LC1, LineColFun LC2) noexcept { + return std::tie(LC1.Line, LC1.Col, LC1.InFunction) == + std::tie(LC2.Line, LC2.Col, LC2.InFunction); + } + [[nodiscard]] std::string str() const { + return std::string("LineColFun { Line: ") + std::to_string(Line) + + "; Col: " + std::to_string(Col) + + "; InFunction: " + InFunction.str() + " }"; + } + + constexpr operator LineColFunOp() const noexcept { + // 0 is the wildcard opcode + return {Line, Col, InFunction, 0}; + } +}; + +struct ArgNo { + uint32_t Idx{}; + + friend bool operator<(ArgNo A1, ArgNo A2) noexcept { return A1.Idx < A2.Idx; } + friend bool operator==(ArgNo A1, ArgNo A2) noexcept { + return A1.Idx == A2.Idx; + } + [[nodiscard]] std::string str() const { + return std::string("ArgNo { Idx: ") + std::to_string(Idx) + " }"; + } +}; +struct ArgInFun { + uint32_t Idx{}; + llvm::StringRef InFunction{}; + + friend bool operator<(ArgInFun A1, ArgInFun A2) noexcept { + return std::tie(A1.InFunction, A1.Idx) < std::tie(A2.InFunction, A2.Idx); + } + friend bool operator==(ArgInFun A1, ArgInFun A2) noexcept { + return std::tie(A1.Idx, A1.InFunction) == std::tie(A2.Idx, A2.InFunction); + } + [[nodiscard]] std::string str() const { + return std::string("ArgInFun { Idx: ") + std::to_string(Idx) + + "; InFunction: " + InFunction.str() + " }"; + } +}; + +struct RetVal { + llvm::StringRef InFunction; + + friend bool operator<(RetVal R1, RetVal R2) noexcept { + return R1.InFunction < R2.InFunction; + } + friend bool operator==(RetVal R1, RetVal R2) noexcept { + return R1.InFunction == R2.InFunction; + } + [[nodiscard]] std::string str() const { + return std::string("RetVal { InFunction: ") + InFunction.str() + " }"; + } +}; +struct RetStmt { + llvm::StringRef InFunction; + + friend bool operator<(RetStmt R1, RetStmt R2) noexcept { + return R1.InFunction < R2.InFunction; + } + friend bool operator==(RetStmt R1, RetStmt R2) noexcept { + return R1.InFunction == R2.InFunction; + } + [[nodiscard]] std::string str() const { + return std::string("RetStmt { InFunction: ") + InFunction.str() + " }"; + } +}; + +struct OperandOf { + uint32_t OperandIndex{}; + LineColFunOp Inst{}; + + friend bool operator<(OperandOf R1, OperandOf R2) noexcept { + return std::tie(R1.OperandIndex, R2.Inst) < + std::tie(R2.OperandIndex, R2.Inst); + } + friend bool operator==(OperandOf R1, OperandOf R2) noexcept { + return R1.OperandIndex == R2.OperandIndex && R1.Inst == R2.Inst; + } + [[nodiscard]] std::string str() const { + return std::string("OperandOf { OperandIndex: ") + + std::to_string(OperandIndex) + "; Inst: " + Inst.str() + " }"; + } +}; + +struct TestingSrcLocation + : public std::variant { + using VarT = std::variant; + using VarT::variant; + + template [[nodiscard]] constexpr bool isa() const noexcept { + return std::holds_alternative(*this); + } + template + [[nodiscard]] constexpr const T *dyn_cast() const noexcept { + return std::get_if(this); + } + template [[nodiscard]] constexpr T *dyn_cast() noexcept { + return std::get_if(this); + } + [[nodiscard]] std::string str() const { + return std::visit([](const auto &Val) { return Val.str(); }, *this); + } + + friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const TestingSrcLocation &Loc) { + return OS << Loc.str(); + } + friend std::ostream &operator<<(std::ostream &OS, + const TestingSrcLocation &Loc) { + return OS << Loc.str(); + } +}; + +} // namespace psr::unittest + +namespace std { +template <> struct hash { + size_t operator()(psr::unittest::LineCol LC) const noexcept { + return llvm::hash_value(std::make_pair(LC.Line, LC.Col)); + } +}; +template <> struct hash { + size_t operator()(psr::unittest::LineColFun LCF) const noexcept { + return llvm::hash_combine( + llvm::hash_value(std::make_pair(LCF.Line, LCF.Col)), LCF.InFunction); + } +}; + +template <> struct hash { + size_t operator()(psr::unittest::LineColFunOp LCF) const noexcept { + return llvm::hash_combine( + llvm::hash_value(std::make_pair(LCF.Line, LCF.Col)), LCF.InFunction, + LCF.OpCode); + } +}; +template <> struct hash { + size_t operator()(psr::unittest::GlobalVar GV) const noexcept { + return llvm::hash_value(GV.Name); + } +}; +template <> struct hash { + size_t operator()(psr::unittest::ArgNo Arg) const noexcept { + return llvm::hash_value(Arg.Idx); + } +}; +template <> struct hash { + size_t operator()(psr::unittest::ArgInFun Arg) const noexcept { + return llvm::hash_combine(Arg.Idx, Arg.InFunction); + } +}; + +template <> struct hash { + size_t operator()(psr::unittest::RetVal Ret) const noexcept { + return llvm::hash_value(Ret.InFunction); + } +}; + +template <> struct hash { + size_t operator()(psr::unittest::RetStmt Ret) const noexcept { + return llvm::hash_value(Ret.InFunction); + } +}; + +template <> struct hash { + size_t operator()(psr::unittest::OperandOf Op) const noexcept { + return llvm::hash_combine(Op.OperandIndex, + hash{}(Op.Inst)); + } +}; + +template <> struct hash { + size_t + operator()(const psr::unittest::TestingSrcLocation &Loc) const noexcept { + return std::hash{}(Loc); + } +}; +} // namespace std + +namespace psr::unittest { + +template +[[nodiscard]] inline const llvm::Instruction * +getInstAtOrNull(const llvm::Function *F, uint32_t ReqLine, + uint32_t ReqColumn = 0, PredFn Pred = {}) { + assert(F != nullptr); + for (const auto &I : llvm::instructions(F)) { + if (I.isDebugOrPseudoInst()) { + continue; + } + + auto [Line, Column] = psr::getLineAndColFromIR(&I); + if (Line == ReqLine && (ReqColumn == 0 || ReqColumn == Column) && + std::invoke(Pred, &I)) { + return &I; + } + } + return nullptr; +} + +[[nodiscard]] inline const llvm::Value * +testingLocInIR(TestingSrcLocation Loc, + const ProjectIRDBBase &IRDB, + const llvm::Function *InterestingFunction = nullptr) { + const auto GetFunction = [&IRDB](llvm::StringRef Name) { + const auto *InFun = IRDB.getFunctionDefinition(Name); + if (!InFun) { + llvm::report_fatal_error("Required function '" + Name + + "' does not exist in the IR!"); + } + return InFun; + }; + const auto *Ret = std::visit( + psr::Overloaded{ + [=](LineCol LC) -> llvm ::Value const * { + if (!InterestingFunction) { + llvm::report_fatal_error( + "You must provide an InterestingFunction as last parameter " + "to testingLocInIR(), if trying to resolve a LineCol; " + "alternatively use LineColFun instead."); + } + + return getInstAtOrNull(InterestingFunction, LC.Line, LC.Col); + }, + [&](LineColFun LC) -> llvm ::Value const * { + const auto *InFun = GetFunction(LC.InFunction); + return getInstAtOrNull(InFun, LC.Line, LC.Col); + }, + [&](LineColFunOp LC) -> llvm ::Value const * { + const auto *InFun = GetFunction(LC.InFunction); + return getInstAtOrNull( + InFun, LC.Line, LC.Col, + [Op = LC.OpCode](const llvm::Instruction *Inst) { + // According to LLVM's doc on llvm::Value::getValueID(), there + // cannot be any opcode==0, so we use it as wildcard here + return Op == 0 || Inst->getOpcode() == Op; + }); + }, + [&IRDB](GlobalVar GV) -> llvm ::Value const * { + return IRDB.getModule()->getGlobalVariable(GV.Name, true); + }, + [=](ArgNo A) -> llvm ::Value const * { + if (!InterestingFunction) { + llvm::report_fatal_error( + "You must provide an InterestingFunction as last parameter " + "to testingLocInIR(), if trying to resolve an ArgNo; " + "alternatively use ArgInFun instead."); + } + if (InterestingFunction->arg_size() <= A.Idx) { + llvm::report_fatal_error( + "Argument index " + llvm::Twine(A.Idx) + + " is out of range (" + + llvm::Twine(InterestingFunction->arg_size()) + ")!"); + } + return InterestingFunction->getArg(A.Idx); + }, + [&](ArgInFun A) -> llvm ::Value const * { + const auto *InFun = GetFunction(A.InFunction); + if (InFun->arg_size() <= A.Idx) { + llvm::report_fatal_error("Argument index " + llvm::Twine(A.Idx) + + " is out of range (" + + llvm::Twine(InFun->arg_size()) + ")!"); + } + return InFun->getArg(A.Idx); + }, + [&](RetVal R) -> llvm::Value const * { + const auto *InFun = GetFunction(R.InFunction); + for (const auto &BB : llvm::reverse(InFun->getBasicBlockList())) { + if (const auto *Ret = + llvm::dyn_cast(BB.getTerminator())) { + return Ret->getReturnValue(); + } + } + llvm::report_fatal_error("No return stmt in function " + + R.InFunction); + }, + [&](RetStmt R) -> llvm::Value const * { + const auto *InFun = GetFunction(R.InFunction); + for (const auto &BB : llvm::reverse(InFun->getBasicBlockList())) { + if (const auto *Ret = + llvm::dyn_cast(BB.getTerminator())) { + return Ret; + } + } + llvm::report_fatal_error("No return stmt in function " + + R.InFunction); + }, + [&](OperandOf Op) -> llvm::Value const * { + const auto *Inst = llvm::dyn_cast_if_present( + testingLocInIR(Op.Inst, IRDB)); + if (!Inst) { + return nullptr; + } + + if (Inst->getNumOperands() <= Op.OperandIndex) { + llvm::report_fatal_error("Requested operand index " + + llvm::Twine(Op.OperandIndex) + + " is out of bounds for instruction " + + llvm::Twine(llvmIRToString(Inst))); + } + + return Inst->getOperand(Op.OperandIndex); + }, + }, + Loc); + if (!Ret) { + llvm::report_fatal_error("Cannot convert " + llvm::Twine(Loc.str()) + + " to LLVM"); + } + return Ret; +} + +template +[[nodiscard]] inline std::set +convertTestingLocationSetInIR( + const SetTy &Locs, const ProjectIRDBBase &IRDB, + const llvm::Function *InterestingFunction = nullptr) { + std::set Ret; + llvm::transform(Locs, std::inserter(Ret, Ret.end()), + [&](TestingSrcLocation Loc) { + return testingLocInIR(Loc, IRDB, InterestingFunction); + }); + return Ret; +} + +template +[[nodiscard]] inline auto convertTestingLocationSetMapInIR( + const MapTy &Locs, const ProjectIRDBBase &IRDB, + const llvm::Function *InterestingFunction = nullptr) { + std::map> Ret; + llvm::transform( + Locs, std::inserter(Ret, Ret.end()), [&](const auto &LocAndSet) { + const auto &[InstLoc, Set] = LocAndSet; + const auto *LocVal = testingLocInIR(InstLoc, IRDB, InterestingFunction); + const auto *LocInst = + llvm::dyn_cast_if_present(LocVal); + if (!LocInst) { + llvm::report_fatal_error( + "Cannot convert " + llvm::Twine(InstLoc.str()) + + (LocVal ? " aka. " + llvmIRToString(LocVal) : "") + + " to an LLVM instruction"); + } + auto ConvSet = + convertTestingLocationSetInIR(Set, IRDB, InterestingFunction); + return std::make_pair(LocInst, std::move(ConvSet)); + }); + return Ret; +} + +} // namespace psr::unittest + +#endif // PHASAR_UNITTESTS_TESTUTILS_SRCCODELOCATIONENTRY_H diff --git a/unittests/Utils/AnalysisPrinterTest.cpp b/unittests/Utils/AnalysisPrinterTest.cpp index f189afef29..c51ccb862d 100644 --- a/unittests/Utils/AnalysisPrinterTest.cpp +++ b/unittests/Utils/AnalysisPrinterTest.cpp @@ -11,12 +11,16 @@ #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "phasar/Utils/DefaultAnalysisPrinter.h" -#include "llvm/ADT/DenseMap.h" +#include "llvm/IR/Instruction.h" +#include "llvm/Support/raw_ostream.h" +#include "SrcCodeLocationEntry.h" #include "TestConfig.h" #include "gtest/gtest.h" using namespace psr; +using namespace psr::unittest; + using CallBackPairTy = std::pair::config_callback_t, IDEExtendedTaintAnalysis<>::config_callback_t>; @@ -30,36 +34,47 @@ class GroundTruthCollector public: // constructor init Groundtruth in each fixture - GroundTruthCollector(llvm::DenseMap> &GroundTruth) - : GroundTruth(GroundTruth) {}; - - void findAndRemove(llvm::DenseMap> &Map1, - llvm::DenseMap> &Map2) { - for (auto Entry = Map1.begin(); Entry != Map1.end();) { - auto Iter = Map2.find(Entry->first); - if (Iter != Map2.end() && Iter->second == Entry->second) { - Map2.erase(Iter); - } - ++Entry; - } - } + GroundTruthCollector( + const LLVMProjectIRDB &IRDB, + const std::map> + &GroundTruth) + : GroundTruth(convertTestingLocationSetMapInIR(GroundTruth, IRDB)) {}; private: void doOnResult(n_t Instr, d_t DfFact, l_t /*LatticeElement*/, DataFlowAnalysisType /*AnalysisType*/) override { - llvm::DenseMap> FoundLeak; - int SinkId = stoi(getMetaDataID(Instr)); - std::set LeakedValueIds; - LeakedValueIds.insert(getMetaDataID((DfFact)->base())); - FoundLeak.try_emplace(SinkId, LeakedValueIds); - findAndRemove(FoundLeak, GroundTruth); + + auto It = GroundTruth.find(Instr); + EXPECT_TRUE(It != GroundTruth.end() && It->second.erase(DfFact->base())) + << "Did not expect finding a leak of " << DToString(DfFact) << " at " + << llvmIRToString(Instr) << '\n'; + if (It != GroundTruth.end() && It->second.empty()) { + GroundTruth.erase(It); + } + } + + std::string printGroundTruth() { + std::string Ret; + llvm::raw_string_ostream OS(Ret); + OS << "{\n"; + for (const auto &[Inst, Facts] : GroundTruth) { + OS << " " << llvmIRToString(Inst) << ": {\n"; + for (const auto *Val : Facts) { + OS << " " << llvmIRToString(Val) << '\n'; + } + } + OS << "}\n"; + + return Ret; } void doOnFinalize(llvm::raw_ostream & /*OS*/) override { - EXPECT_TRUE(GroundTruth.empty()); + EXPECT_TRUE(GroundTruth.empty()) + << "Elements of GroundTruth not found: " << printGroundTruth(); } - llvm::DenseMap> GroundTruth{}; + std::map> + GroundTruth{}; }; class AnalysisPrinterTest : public ::testing::Test { @@ -68,7 +83,8 @@ class AnalysisPrinterTest : public ::testing::Test { const std::vector EntryPoints = {"main"}; void doAnalysisTest( - llvm::StringRef IRFile, GroundTruthCollector >Printer, + llvm::StringRef IRFile, + const std::map> >, std::variant Config) { HelperAnalyses Helpers(PathToLlFiles + IRFile, EntryPoints); @@ -89,7 +105,8 @@ class AnalysisPrinterTest : public ::testing::Test { auto TaintProblem = createAnalysisProblem>( Helpers, TConfig, EntryPoints); - TaintProblem.setAnalysisPrinter(>Printer); + GroundTruthCollector GTCollector(Helpers.getProjectIRDB(), GT); + TaintProblem.setAnalysisPrinter(>Collector); IDESolver Solver(TaintProblem, &Helpers.getICFG()); Solver.solve(); @@ -100,8 +117,10 @@ class AnalysisPrinterTest : public ::testing::Test { /* ============== BASIC TESTS ============== */ TEST_F(AnalysisPrinterTest, HandleBasicTest_01) { - llvm::DenseMap> GroundTruth; - GroundTruth[7] = {"0"}; + std::map> GroundTruth; + GroundTruth[LineColFun{8, 3, "main"}] = { + LineColFun{4, 14, "main"}, + }; TaintConfigData Config; @@ -116,16 +135,16 @@ TEST_F(AnalysisPrinterTest, HandleBasicTest_01) { Config.Functions.push_back(std::move(FuncDataMain)); Config.Functions.push_back(std::move(FuncDataPrint)); - GroundTruthCollector GroundTruthPrinter = {GroundTruth}; - doAnalysisTest("xtaint01_json_cpp_dbg.ll", GroundTruthPrinter, &Config); + doAnalysisTest("xtaint01_json_cpp_dbg.ll", GroundTruth, &Config); } TEST_F(AnalysisPrinterTest, XTaint01) { - llvm::DenseMap> GroundTruth; + std::map> GroundTruth; - GroundTruth[13] = {"7"}; - GroundTruthCollector GroundTruthPrinter = {GroundTruth}; - doAnalysisTest("xtaint01_cpp.ll", GroundTruthPrinter, std::monostate{}); + GroundTruth[LineColFun{8, 3, "main"}] = { + LineColFun{7, 48, "main"}, + }; + doAnalysisTest("xtaint01_cpp_dbg.ll", GroundTruth, std::monostate{}); } // main function for the test case