From 23e288ee0acaa94b8989eef9be4e89e1772893a6 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Mon, 23 Jun 2025 18:19:35 +0200 Subject: [PATCH 01/35] Add utility function to aid src-code based unittests --- unittests/TestUtils/SourceMapping.h | 31 +++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 unittests/TestUtils/SourceMapping.h diff --git a/unittests/TestUtils/SourceMapping.h b/unittests/TestUtils/SourceMapping.h new file mode 100644 index 0000000000..d69d864286 --- /dev/null +++ b/unittests/TestUtils/SourceMapping.h @@ -0,0 +1,31 @@ +#ifndef UNITTEST_TESTUTILS_SOURCEMAPPING_H +#define UNITTEST_TESTUTILS_SOURCEMAPPING_H + +#include "phasar/PhasarLLVM/Utils/LLVMIRToSrc.h" +#include "phasar/Utils/TypeTraits.h" + +#include "llvm/IR/InstIterator.h" +#include "llvm/IR/Instruction.h" + +#include + +namespace psr::unittest { + +template +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)) { + auto [Line, Column] = psr::getLineAndColFromIR(&I); + if (Line == ReqLine && (ReqColumn == 0 || ReqColumn == Column) && + std::invoke(Pred, &I)) { + return &I; + } + } + return nullptr; +} + +} // namespace psr::unittest + +#endif // UNITTEST_TESTUTILS_SOURCEMAPPING_H From b895ceee9471425196338572c8cb3aed28e6b548 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Sun, 29 Jun 2025 00:17:54 +0200 Subject: [PATCH 02/35] half of xtaint test, stuck on 12 --- test/llvm_test_code/xtaint/CMakeLists.txt | 11 +- .../Problems/IDEExtendedTaintAnalysisTest.cpp | 307 +++++++++++++++--- .../PhasarLLVM/TypeHierarchy/CMakeLists.txt | 2 +- 3 files changed, 265 insertions(+), 55 deletions(-) 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..c65b714ec0 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp @@ -18,16 +18,19 @@ #include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" #include "phasar/PhasarLLVM/TaintConfig/LLVMTaintConfig.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" +#include "phasar/PhasarLLVM/Utils/LLVMShorthands.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/InstrTypes.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" #include "llvm/Support/Casting.h" +#include "SourceMapping.h" #include "TestConfig.h" #include "gtest/gtest.h" #include "nlohmann/json.hpp" @@ -55,10 +58,9 @@ class IDETaintAnalysisTest : public ::testing::Test { ~IDETaintAnalysisTest() override = default; void doAnalysis( - const llvm::Twine &IRFile, const map> &GroundTruth, + HelperAnalyses &HA, const map> &GroundTruth, std::variant Config, bool DumpResults = true) { - HelperAnalyses HA(IRFile, EntryPoints); auto TC = std::visit(Overloaded{[&](std::monostate) { @@ -134,7 +136,9 @@ 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); + HelperAnalyses HA({PathToLLFiles + "xtaint01_json_cpp_dbg.ll"}, EntryPoints); + + doAnalysis(HA, Gt, &Config); } TEST_F(IDETaintAnalysisTest, XTaint01) { @@ -142,7 +146,9 @@ TEST_F(IDETaintAnalysisTest, XTaint01) { Gt[13] = {"12"}; - doAnalysis({PathToLLFiles + "xtaint01_cpp.ll"}, Gt, std::monostate{}); + HelperAnalyses HA({PathToLLFiles + "xtaint01_cpp_dbg.ll"}, EntryPoints); + + doAnalysis(HA, Gt, std::monostate{}); } TEST_F(IDETaintAnalysisTest, XTaint02) { @@ -150,14 +156,18 @@ TEST_F(IDETaintAnalysisTest, XTaint02) { Gt[18] = {"17"}; - doAnalysis({PathToLLFiles + "xtaint02_cpp.ll"}, Gt, std::monostate{}, true); + HelperAnalyses HA({PathToLLFiles + "xtaint02_cpp_dbg.ll"}, EntryPoints); + + doAnalysis(HA, Gt, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint03) { map> Gt; Gt[21] = {"20"}; - doAnalysis({PathToLLFiles + "xtaint03_cpp.ll"}, Gt, std::monostate{}); + HelperAnalyses HA({PathToLLFiles + "xtaint03_cpp_dbg.ll"}, EntryPoints); + + doAnalysis(HA, Gt, std::monostate{}); } TEST_F(IDETaintAnalysisTest, XTaint04) { @@ -165,7 +175,9 @@ TEST_F(IDETaintAnalysisTest, XTaint04) { Gt[16] = {"15"}; - doAnalysis({PathToLLFiles + "xtaint04_cpp.ll"}, Gt, std::monostate{}); + HelperAnalyses HA({PathToLLFiles + "xtaint04_cpp_dbg.ll"}, EntryPoints); + + doAnalysis(HA, Gt, std::monostate{}); } // XTaint05 is similar to 06, but even harder @@ -175,7 +187,9 @@ TEST_F(IDETaintAnalysisTest, XTaint06) { // no leaks expected - doAnalysis({PathToLLFiles + "xtaint06_cpp.ll"}, Gt, std::monostate{}); + HelperAnalyses HA({PathToLLFiles + "xtaint06_cpp_dbg.ll"}, EntryPoints); + + doAnalysis(HA, Gt, std::monostate{}); } /// In the new TaintConfig specifying source/sink/sanitizer properties for extra @@ -186,7 +200,9 @@ TEST_F(IDETaintAnalysisTest, DISABLED_XTaint07) { Gt[21] = {"20"}; - doAnalysis({PathToLLFiles + "xtaint07_cpp.ll"}, Gt, std::monostate{}); + HelperAnalyses HA({PathToLLFiles + "xtaint07_cpp_dbg.ll"}, EntryPoints); + + doAnalysis(HA, Gt, std::monostate{}); } TEST_F(IDETaintAnalysisTest, DISABLED_XTaint08) { @@ -194,7 +210,9 @@ TEST_F(IDETaintAnalysisTest, DISABLED_XTaint08) { Gt[24] = {"23"}; - doAnalysis({PathToLLFiles + "xtaint08_cpp.ll"}, Gt, std::monostate{}); + HelperAnalyses HA({PathToLLFiles + "xtaint08_cpp_dbg.ll"}, EntryPoints); + + doAnalysis(HA, Gt, std::monostate{}); } TEST_F(IDETaintAnalysisTest, XTaint09_1) { @@ -202,7 +220,9 @@ TEST_F(IDETaintAnalysisTest, XTaint09_1) { Gt[25] = {"24"}; - doAnalysis({PathToLLFiles + "xtaint09_1_cpp.ll"}, Gt, std::monostate{}); + HelperAnalyses HA({PathToLLFiles + "xtaint09_1_cpp_dbg.ll"}, EntryPoints); + + doAnalysis(HA, Gt, std::monostate{}); } TEST_F(IDETaintAnalysisTest, XTaint09) { @@ -210,7 +230,9 @@ TEST_F(IDETaintAnalysisTest, XTaint09) { Gt[24] = {"23"}; - doAnalysis({PathToLLFiles + "xtaint09_cpp.ll"}, Gt, std::monostate{}); + HelperAnalyses HA({PathToLLFiles + "xtaint09_cpp_dbg.ll"}, EntryPoints); + + doAnalysis(HA, Gt, std::monostate{}); } TEST_F(IDETaintAnalysisTest, DISABLED_XTaint10) { @@ -225,7 +247,9 @@ TEST_F(IDETaintAnalysisTest, DISABLED_XTaint10) { // TODO: Also update the Gt Gt[33] = {"32"}; - doAnalysis({PathToLLFiles + "xtaint10_cpp.ll"}, Gt, std::monostate{}); + HelperAnalyses HA({PathToLLFiles + "xtaint10_cpp_dbg.ll"}, EntryPoints); + + doAnalysis(HA, Gt, std::monostate{}); } TEST_F(IDETaintAnalysisTest, DISABLED_XTaint11) { @@ -233,33 +257,103 @@ TEST_F(IDETaintAnalysisTest, DISABLED_XTaint11) { // no leaks expected; actually finds "27" at 28 - doAnalysis({PathToLLFiles + "xtaint11_cpp.ll"}, Gt, std::monostate{}); + HelperAnalyses HA({PathToLLFiles + "xtaint11_cpp_dbg.ll"}, EntryPoints); + + doAnalysis(HA, Gt, std::monostate{}); } TEST_F(IDETaintAnalysisTest, XTaint12) { map> Gt; + HelperAnalyses HA({PathToLLFiles + "xtaint12_cpp_dbg.ll"}, EntryPoints); + + const auto &IRDB = HA.getProjectIRDB(); + const auto *MainFunc = IRDB.getFunction("main"); + + // %0 = load i32, ptr %call2, align 4, !dbg !81, !psr.id !82 | ID: 32 + const auto *LeakLoadInst = unittest::getInstAtOrNull( + MainFunc, 19, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + ASSERT_TRUE(LeakLoadInst); + + // sink(*getPtr(&ptaint)); + const auto *LeakCallInst = unittest::getInstAtOrNull( + MainFunc, 19, 0, [](const llvm::Instruction *Inst) { + if (llvm::isa(Inst)) { + llvm::outs() << "Inst: " << *(llvm::cast(Inst)) + << "\n"; + llvm::outs() << "Inst->getFunctionType(): " + << *(llvm::cast(Inst)->getFunctionType()) + << "\n"; + } + return llvm::isa(Inst); + }); + ASSERT_TRUE(LeakCallInst); + + const auto LeakLoadID = getMetaDataID(LeakLoadInst); + const auto LeakCallID = getMetaDataID(LeakCallInst); - // We sanitize an alias - since we don't have must-alias relations, we cannot - // kill aliases at all - Gt[28] = {"27"}; + Gt[stoi(LeakCallID)] = {LeakLoadID}; - doAnalysis({PathToLLFiles + "xtaint12_cpp.ll"}, Gt, std::monostate{}); + doAnalysis(HA, Gt, std::monostate{}); } +#if false + TEST_F(IDETaintAnalysisTest, XTaint13) { map> Gt; - - Gt[30] = {"29"}; - - doAnalysis({PathToLLFiles + "xtaint13_cpp.ll"}, Gt, std::monostate{}); + HelperAnalyses HA({PathToLLFiles + "xtaint13_cpp_dbg.ll"}, EntryPoints); + const auto &IRDB = HA.getProjectIRDB(); + const auto *MainFunc = IRDB.getFunction("main"); + + // + const auto *LeakLoadInst = unittest::getInstAtOrNull( + MainFunc, 17, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + ASSERT_TRUE(LeakLoadInst); + + // sink(x); + const auto *LeakCallInst = unittest::getInstAtOrNull( + MainFunc, 17, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + ASSERT_TRUE(LeakCallInst); + + const auto LeakLoadID = getMetaDataID(LeakLoadInst); + const auto LeakCallID = getMetaDataID(LeakCallInst); + + Gt[stoi(LeakCallID)] = {LeakLoadID}; + + doAnalysis(HA, Gt, std::monostate{}); } TEST_F(IDETaintAnalysisTest, XTaint14) { map> Gt; - - Gt[33] = {"32"}; - - doAnalysis({PathToLLFiles + "xtaint14_cpp.ll"}, Gt, std::monostate{}); + HelperAnalyses HA({PathToLLFiles + "xtaint14_cpp_dbg.ll"}, EntryPoints); + const auto &IRDB = HA.getProjectIRDB(); + const auto *MainFunc = IRDB.getFunction("main"); + + // %3 = load i32, ptr %x, align 4, !dbg !93, !psr.id !94 | ID: 37 + const auto *LeakLoadInst = unittest::getInstAtOrNull( + MainFunc, 24, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + ASSERT_TRUE(LeakLoadInst); + + // sink(x); + const auto *LeakCallInst = unittest::getInstAtOrNull( + MainFunc, 24, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + ASSERT_TRUE(LeakCallInst); + + const auto LeakLoadID = getMetaDataID(LeakLoadInst); + const auto LeakCallID = getMetaDataID(LeakCallInst); + + Gt[stoi(LeakCallID)] = {LeakLoadID}; + + doAnalysis(HA, Gt, std::monostate{}); } /// The TaintConfig fails to get all call-sites of Source::get, because it has @@ -267,33 +361,83 @@ TEST_F(IDETaintAnalysisTest, XTaint14) { TEST_F(IDETaintAnalysisTest, DISABLED_XTaint15) { map> Gt; + // TODO: convert from hardcoded values to using the new dynamic approach (see + // xtaint20 for example). Gt[47] = {"46"}; - doAnalysis({PathToLLFiles + "xtaint15_cpp.ll"}, Gt, std::monostate{}); + HelperAnalyses HA({PathToLLFiles + "xtaint15_cpp_dbg.ll"}, EntryPoints); + + doAnalysis(HA, Gt, std::monostate{}); } TEST_F(IDETaintAnalysisTest, XTaint16) { map> Gt; - - Gt[24] = {"23"}; - - doAnalysis({PathToLLFiles + "xtaint16_cpp.ll"}, Gt, std::monostate{}); + HelperAnalyses HA({PathToLLFiles + "xtaint16_cpp_dbg.ll"}, EntryPoints); + const auto &IRDB = HA.getProjectIRDB(); + const auto *MainFunc = IRDB.getFunction("main"); + + // %1 = load i32, ptr %x, align 4, !dbg !64, !psr.id !65 | ID: 27 + const auto *LeakLoadInst = unittest::getInstAtOrNull( + MainFunc, 13, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + ASSERT_TRUE(LeakLoadInst); + + // we can skip the sanitizer => leak here + // sink(x); + const auto *LeakCallInst = unittest::getInstAtOrNull( + MainFunc, 13, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + ASSERT_TRUE(LeakCallInst); + + const auto LeakLoadID = getMetaDataID(LeakLoadInst); + const auto LeakCallID = getMetaDataID(LeakCallInst); + + Gt[stoi(LeakCallID)] = {LeakLoadID}; + + doAnalysis(HA, Gt, std::monostate{}); } TEST_F(IDETaintAnalysisTest, XTaint17) { map> Gt; - - Gt[27] = {"26"}; - - doAnalysis({PathToLLFiles + "xtaint17_cpp.ll"}, Gt, std::monostate{}); + HelperAnalyses HA({PathToLLFiles + "xtaint17_cpp_dbg.ll"}, EntryPoints); + const auto &IRDB = HA.getProjectIRDB(); + const auto *MainFunc = IRDB.getFunction("main"); + + // %1 = load i32, ptr %x, align 4, !dbg !76, !psr.id !77 | ID: 31 + const auto *LeakLoadInst = unittest::getInstAtOrNull( + MainFunc, 17, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + ASSERT_TRUE(LeakLoadInst); + + // we can skip the sanitizer => leak here + // sink(x); + const auto *LeakCallInst = unittest::getInstAtOrNull( + MainFunc, 17, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + ASSERT_TRUE(LeakCallInst); + + const auto LeakLoadID = getMetaDataID(LeakLoadInst); + const auto LeakCallID = getMetaDataID(LeakCallInst); + + Gt[stoi(LeakCallID)] = {LeakLoadID}; + + doAnalysis(HA, Gt, std::monostate{}); } TEST_F(IDETaintAnalysisTest, XTaint18) { map> Gt; + // TODO: convert from hardcoded values to using the new dynamic approach (see + // xtaint20 for example). // Gt[26] = {"25"}; - doAnalysis({PathToLLFiles + "xtaint18_cpp.ll"}, Gt, std::monostate{}); + HelperAnalyses HA({PathToLLFiles + "xtaint18_cpp_dbg.ll"}, EntryPoints); + + doAnalysis(HA, Gt, std::monostate{}); } PHASAR_SKIP_TEST(TEST_F(IDETaintAnalysisTest, XTaint19) { @@ -301,25 +445,97 @@ PHASAR_SKIP_TEST(TEST_F(IDETaintAnalysisTest, XTaint19) { GTEST_SKIP(); map> Gt; + // TODO: convert from hardcoded values to using the new dynamic approach (see + // xtaint20 for example). Gt[22] = {"21"}; - doAnalysis({PathToLLFiles + "xtaint19_cpp.ll"}, Gt, std::monostate{}); + HelperAnalyses HA({PathToLLFiles + "xtaint19_cpp_dbg.ll"}, EntryPoints); + + doAnalysis(HA, Gt, std::monostate{}); }) TEST_F(IDETaintAnalysisTest, XTaint20) { map> Gt; - Gt[22] = {"14"}; - Gt[24] = {"23"}; - - doAnalysis({PathToLLFiles + "xtaint20_cpp.ll"}, Gt, std::monostate{}); + HelperAnalyses HA({PathToLLFiles + "xtaint20_cpp_dbg.ll"}, EntryPoints); + const auto &IRDB = HA.getProjectIRDB(); + const auto *MainFunc = IRDB.getFunction("main"); + + // %x = alloca i32, align 4, !psr.id !48 | ID: 16 + const auto *FirstLeakAllocaInst = unittest::getInstAtOrNull(MainFunc, 6, 0); + ASSERT_TRUE(FirstLeakAllocaInst); + + // srcsink(x); // leak + const auto *FirstLeakCallInst = unittest::getInstAtOrNull( + MainFunc, 12, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + ASSERT_TRUE(FirstLeakCallInst); + + // %0 = load i32, ptr %y, align 4, !dbg !72, !psr.id !73 | ID: 29 + const auto *SecondLeakLoadInst = unittest::getInstAtOrNull( + MainFunc, 13, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + ASSERT_TRUE(SecondLeakLoadInst); + + // sink(y); // leak + const auto *SecondLeakCallInst = unittest::getInstAtOrNull( + MainFunc, 13, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + ASSERT_TRUE(SecondLeakCallInst); + + const auto FirstLeakAllocaID = getMetaDataID(FirstLeakAllocaInst); + const auto FirstLeakCallID = getMetaDataID(FirstLeakCallInst); + const auto SecondLeakLoadID = getMetaDataID(SecondLeakLoadInst); + const auto SecondLeakCallID = getMetaDataID(SecondLeakCallInst); + + Gt[stoi(FirstLeakCallID)] = {FirstLeakAllocaID}; + Gt[stoi(SecondLeakCallID)] = {SecondLeakLoadID}; + + doAnalysis(HA, Gt, std::monostate{}); } TEST_F(IDETaintAnalysisTest, XTaint21) { map> Gt; - Gt[10] = {"2"}; - Gt[12] = {"11"}; + HelperAnalyses HA({PathToLLFiles + "xtaint21_cpp_dbg.ll"}, EntryPoints); + const auto &IRDB = HA.getProjectIRDB(); + const auto *MainFunc = IRDB.getFunction("main"); + + // %x = alloca i32, align 4, !psr.id !21 | ID: 2 + const auto *FirstLeakAllocaInst = unittest::getInstAtOrNull(MainFunc, 11); + ASSERT_TRUE(FirstLeakAllocaInst); + + // srcsink(x); // leak + const auto *FirstLeakCallInst = unittest::getInstAtOrNull( + MainFunc, 17, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + ASSERT_TRUE(FirstLeakCallInst); + + // %0 = load i32, ptr %y, align 4, !dbg !45, !psr.id !46 | ID: 15 + const auto *SecondLeakLoadInst = unittest::getInstAtOrNull( + MainFunc, 18, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + ASSERT_TRUE(SecondLeakLoadInst); + + // sink(y); // leak + const auto *SecondLeakCallInst = unittest::getInstAtOrNull( + MainFunc, 18, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + ASSERT_TRUE(SecondLeakCallInst); + + const auto FirstLeakAllocaID = getMetaDataID(FirstLeakAllocaInst); + const auto FirstLeakCallID = getMetaDataID(FirstLeakCallInst); + const auto SecondLeakLoadID = getMetaDataID(SecondLeakLoadInst); + const auto SecondLeakCallID = getMetaDataID(SecondLeakCallInst); + + Gt[stoi(FirstLeakCallID)] = {FirstLeakAllocaID}; + Gt[stoi(SecondLeakCallID)] = {SecondLeakLoadID}; IDEExtendedTaintAnalysis<>::config_callback_t SourceCB = [](const llvm::Instruction *Inst) { @@ -343,10 +559,11 @@ TEST_F(IDETaintAnalysisTest, XTaint21) { return Ret; }; - doAnalysis({PathToLLFiles + "xtaint21_cpp.ll"}, Gt, - CallBackPairTy{std::move(SourceCB), std::move(SinkCB)}); + doAnalysis(HA, Gt, CallBackPairTy{std::move(SourceCB), std::move(SinkCB)}); } +#endif + int main(int Argc, char **Argv) { ::testing::InitGoogleTest(&Argc, Argv); return RUN_ALL_TESTS(); 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 From d602cf4578fdd07f6f7c172b27a69b0746bb1dda Mon Sep 17 00:00:00 2001 From: mxHuber Date: Sun, 29 Jun 2025 21:08:17 +0200 Subject: [PATCH 03/35] Fixed all but 09 and 12 --- .../Problems/IDEExtendedTaintAnalysisTest.cpp | 181 +++++++++++++++--- 1 file changed, 159 insertions(+), 22 deletions(-) diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp index c65b714ec0..af85f49b2f 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp @@ -143,39 +143,116 @@ TEST_F(IDETaintAnalysisTest, XTaint01_Json) { TEST_F(IDETaintAnalysisTest, XTaint01) { map> Gt; + HelperAnalyses HA({PathToLLFiles + "xtaint01_cpp_dbg.ll"}, EntryPoints); - Gt[13] = {"12"}; + const auto &IRDB = HA.getProjectIRDB(); + const auto *MainFunc = IRDB.getFunction("main"); - HelperAnalyses HA({PathToLLFiles + "xtaint01_cpp_dbg.ll"}, EntryPoints); + // + const auto *LeakLoadInst = unittest::getInstAtOrNull( + MainFunc, 8, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + ASSERT_TRUE(LeakLoadInst); + + // print(argc); + const auto *LeakCallInst = unittest::getInstAtOrNull( + MainFunc, 8, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + ASSERT_TRUE(LeakCallInst); + + const auto LeakLoadID = getMetaDataID(LeakLoadInst); + const auto LeakCallID = getMetaDataID(LeakCallInst); + + Gt[stoi(LeakCallID)] = {LeakLoadID}; doAnalysis(HA, Gt, std::monostate{}); } TEST_F(IDETaintAnalysisTest, XTaint02) { map> Gt; + HelperAnalyses HA({PathToLLFiles + "xtaint02_cpp_dbg.ll"}, EntryPoints); - Gt[18] = {"17"}; + const auto &IRDB = HA.getProjectIRDB(); + const auto *MainFunc = IRDB.getFunction("main"); - HelperAnalyses HA({PathToLLFiles + "xtaint02_cpp_dbg.ll"}, EntryPoints); + // + const auto *LeakLoadInst = unittest::getInstAtOrNull( + MainFunc, 9, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + ASSERT_TRUE(LeakLoadInst); + + // print(array[0]); + const auto *LeakCallInst = unittest::getInstAtOrNull( + MainFunc, 9, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + ASSERT_TRUE(LeakCallInst); + + const auto LeakLoadID = getMetaDataID(LeakLoadInst); + const auto LeakCallID = getMetaDataID(LeakCallInst); + + Gt[stoi(LeakCallID)] = {LeakLoadID}; doAnalysis(HA, Gt, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint03) { map> Gt; + HelperAnalyses HA({PathToLLFiles + "xtaint03_cpp_dbg.ll"}, EntryPoints); - Gt[21] = {"20"}; + const auto &IRDB = HA.getProjectIRDB(); + const auto *MainFunc = IRDB.getFunction("main"); - HelperAnalyses HA({PathToLLFiles + "xtaint03_cpp_dbg.ll"}, EntryPoints); + // %2 = load i32, ptr %arrayidx2, align 4, !dbg !62, !psr.id !64 | ID: 24 + const auto *LeakLoadInst = unittest::getInstAtOrNull( + MainFunc, 10, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + ASSERT_TRUE(LeakLoadInst); + + // print(array[1]); + const auto *LeakCallInst = unittest::getInstAtOrNull( + MainFunc, 10, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + ASSERT_TRUE(LeakCallInst); + + const auto LeakLoadID = getMetaDataID(LeakLoadInst); + const auto LeakCallID = getMetaDataID(LeakCallInst); + + Gt[stoi(LeakCallID)] = {LeakLoadID}; doAnalysis(HA, Gt, std::monostate{}); } TEST_F(IDETaintAnalysisTest, XTaint04) { map> Gt; + HelperAnalyses HA({PathToLLFiles + "xtaint04_cpp_dbg.ll"}, EntryPoints); + + const auto &IRDB = HA.getProjectIRDB(); + const auto *MainFunc = IRDB.getFunction("_Z3barPi"); - Gt[16] = {"15"}; + // %3 = load i32, ptr %arrayidx1, align 4, !dbg !42, !psr.id !45 | ID: 17 + const auto *LeakLoadInst = unittest::getInstAtOrNull( + MainFunc, 6, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst) && + Inst->getOperand(0)->getName().str() == "arrayidx1"; + }); + ASSERT_TRUE(LeakLoadInst); - HelperAnalyses HA({PathToLLFiles + "xtaint04_cpp_dbg.ll"}, EntryPoints); + // print(arr[0]); + const auto *LeakCallInst = unittest::getInstAtOrNull( + MainFunc, 6, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + ASSERT_TRUE(LeakCallInst); + + const auto LeakLoadID = getMetaDataID(LeakLoadInst); + const auto LeakCallID = getMetaDataID(LeakCallInst); + + Gt[stoi(LeakCallID)] = {LeakLoadID}; doAnalysis(HA, Gt, std::monostate{}); } @@ -183,10 +260,9 @@ TEST_F(IDETaintAnalysisTest, XTaint04) { // XTaint05 is similar to 06, but even harder TEST_F(IDETaintAnalysisTest, XTaint06) { - map> Gt; - // no leaks expected + map> Gt; HelperAnalyses HA({PathToLLFiles + "xtaint06_cpp_dbg.ll"}, EntryPoints); doAnalysis(HA, Gt, std::monostate{}); @@ -200,6 +276,8 @@ TEST_F(IDETaintAnalysisTest, DISABLED_XTaint07) { Gt[21] = {"20"}; + // TODO: convert from hardcoded values to using the new dynamic approach (see + // xtaint20 for example). HelperAnalyses HA({PathToLLFiles + "xtaint07_cpp_dbg.ll"}, EntryPoints); doAnalysis(HA, Gt, std::monostate{}); @@ -210,6 +288,8 @@ TEST_F(IDETaintAnalysisTest, DISABLED_XTaint08) { Gt[24] = {"23"}; + // TODO: convert from hardcoded values to using the new dynamic approach (see + // xtaint20 for example). HelperAnalyses HA({PathToLLFiles + "xtaint08_cpp_dbg.ll"}, EntryPoints); doAnalysis(HA, Gt, std::monostate{}); @@ -217,24 +297,85 @@ TEST_F(IDETaintAnalysisTest, DISABLED_XTaint08) { TEST_F(IDETaintAnalysisTest, XTaint09_1) { map> Gt; + HelperAnalyses HA({PathToLLFiles + "xtaint09_1_cpp_dbg.ll"}, EntryPoints); - Gt[25] = {"24"}; + const auto &IRDB = HA.getProjectIRDB(); + const auto *MainFunc = IRDB.getFunction("main"); - HelperAnalyses HA({PathToLLFiles + "xtaint09_1_cpp_dbg.ll"}, EntryPoints); + // sink(*mem); + const auto *LeakCallInst = unittest::getInstAtOrNull( + MainFunc, 14, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + ASSERT_TRUE(LeakCallInst); + + llvm::outs() << "(LeakCallInst->getOperand(0): " + << *(LeakCallInst->getOperand(0)) << "\n"; + + // TODO: ask fabian if this is okay. I am not using getInstAtOrNull here and I + // am not tying the unit test to the .cpp file. + const auto *LeakLoadInst = LeakCallInst->getOperand(0); +#if false + const auto *LeakLoadInst = unittest::getInstAtOrNull( + MainFunc, 14, 0, [LeakCallInst](const llvm::Instruction *Inst) { + if (Inst) { + llvm::outs() << "Inst op 0: " << Inst->getOperand(0)->getName().str() + << "\n"; + } + return Inst == LeakCallInst->getOperand(0); + }); +#endif + ASSERT_TRUE(LeakLoadInst); + + const auto LeakLoadID = getMetaDataID(LeakLoadInst); + const auto LeakCallID = getMetaDataID(LeakCallInst); + + Gt[stoi(LeakCallID)] = {LeakLoadID}; doAnalysis(HA, Gt, std::monostate{}); } TEST_F(IDETaintAnalysisTest, XTaint09) { map> Gt; + HelperAnalyses HA({PathToLLFiles + "xtaint09_cpp_dbg.ll"}, EntryPoints); + const auto &IRDB = HA.getProjectIRDB(); + const auto *MainFunc = IRDB.getFunction("main"); - Gt[24] = {"23"}; + // sink(*mem); + const auto *LeakCallInst = unittest::getInstAtOrNull( + MainFunc, 16, 0, [](const llvm::Instruction *Inst) { + // TODO: this one func call prob has a weird ll with multiple call stuff + // going on. The PredFn needs to catch that (somehow). + return llvm::isa(Inst); + }); + ASSERT_TRUE(LeakCallInst); - HelperAnalyses HA({PathToLLFiles + "xtaint09_cpp_dbg.ll"}, EntryPoints); +#if false + // %0 = load i32, ptr %call4, align 4, !dbg !1076, !psr.id !1078 | ID: 25 + const auto *LeakLoadInst = unittest::getInstAtOrNull( + MainFunc, 16, 0, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); +#endif + + llvm::outs() << "*(LeakCallInst->getOperand(0)): " + << *(LeakCallInst->getOperand(0)) << "\n"; + + // %0 = load i32, ptr %call4, align 4, !dbg !1076, !psr.id !1078 | ID: 25 + const auto *LeakLoadInst = LeakCallInst->getOperand(0); + ASSERT_TRUE(LeakLoadInst); + + ASSERT_TRUE(false); + + const auto LeakLoadID = getMetaDataID(LeakLoadInst); + const auto LeakCallID = getMetaDataID(LeakCallInst); + + Gt[stoi(LeakCallID)] = {LeakLoadID}; doAnalysis(HA, Gt, std::monostate{}); } +#if false TEST_F(IDETaintAnalysisTest, DISABLED_XTaint10) { map> Gt; @@ -247,6 +388,8 @@ TEST_F(IDETaintAnalysisTest, DISABLED_XTaint10) { // TODO: Also update the Gt Gt[33] = {"32"}; + // TODO: convert from hardcoded values to using the new dynamic approach (see + // xtaint20 for example). HelperAnalyses HA({PathToLLFiles + "xtaint10_cpp_dbg.ll"}, EntryPoints); doAnalysis(HA, Gt, std::monostate{}); @@ -257,6 +400,8 @@ TEST_F(IDETaintAnalysisTest, DISABLED_XTaint11) { // no leaks expected; actually finds "27" at 28 + // TODO: convert from hardcoded values to using the new dynamic approach (see + // xtaint20 for example). HelperAnalyses HA({PathToLLFiles + "xtaint11_cpp_dbg.ll"}, EntryPoints); doAnalysis(HA, Gt, std::monostate{}); @@ -279,13 +424,6 @@ TEST_F(IDETaintAnalysisTest, XTaint12) { // sink(*getPtr(&ptaint)); const auto *LeakCallInst = unittest::getInstAtOrNull( MainFunc, 19, 0, [](const llvm::Instruction *Inst) { - if (llvm::isa(Inst)) { - llvm::outs() << "Inst: " << *(llvm::cast(Inst)) - << "\n"; - llvm::outs() << "Inst->getFunctionType(): " - << *(llvm::cast(Inst)->getFunctionType()) - << "\n"; - } return llvm::isa(Inst); }); ASSERT_TRUE(LeakCallInst); @@ -298,7 +436,6 @@ TEST_F(IDETaintAnalysisTest, XTaint12) { doAnalysis(HA, Gt, std::monostate{}); } -#if false TEST_F(IDETaintAnalysisTest, XTaint13) { map> Gt; From 9c092e9701f7484d02cd3ce26f1b335100720cb7 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Mon, 30 Jun 2025 22:09:00 +0200 Subject: [PATCH 04/35] fixed all enabled ext taint tests --- .../Problems/IDEExtendedTaintAnalysisTest.cpp | 52 ++++++++----------- 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp index af85f49b2f..ddcd612036 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp @@ -277,7 +277,7 @@ TEST_F(IDETaintAnalysisTest, DISABLED_XTaint07) { Gt[21] = {"20"}; // TODO: convert from hardcoded values to using the new dynamic approach (see - // xtaint20 for example). + // xtaint20 for example). Reenable test to check if everything works. HelperAnalyses HA({PathToLLFiles + "xtaint07_cpp_dbg.ll"}, EntryPoints); doAnalysis(HA, Gt, std::monostate{}); @@ -289,7 +289,7 @@ TEST_F(IDETaintAnalysisTest, DISABLED_XTaint08) { Gt[24] = {"23"}; // TODO: convert from hardcoded values to using the new dynamic approach (see - // xtaint20 for example). + // xtaint20 for example). Reenable test to check if everything works. HelperAnalyses HA({PathToLLFiles + "xtaint08_cpp_dbg.ll"}, EntryPoints); doAnalysis(HA, Gt, std::monostate{}); @@ -309,9 +309,6 @@ TEST_F(IDETaintAnalysisTest, XTaint09_1) { }); ASSERT_TRUE(LeakCallInst); - llvm::outs() << "(LeakCallInst->getOperand(0): " - << *(LeakCallInst->getOperand(0)) << "\n"; - // TODO: ask fabian if this is okay. I am not using getInstAtOrNull here and I // am not tying the unit test to the .cpp file. const auto *LeakLoadInst = LeakCallInst->getOperand(0); @@ -344,29 +341,20 @@ TEST_F(IDETaintAnalysisTest, XTaint09) { // sink(*mem); const auto *LeakCallInst = unittest::getInstAtOrNull( MainFunc, 16, 0, [](const llvm::Instruction *Inst) { - // TODO: this one func call prob has a weird ll with multiple call stuff - // going on. The PredFn needs to catch that (somehow). - return llvm::isa(Inst); + // TODO: ask Fabian if the call inst with the empty name is the correct + // one. It is detected as a leak, but I am not sure if that is correct. + return llvm::isa(Inst) && + llvm::cast(Inst)->getName().empty(); }); ASSERT_TRUE(LeakCallInst); -#if false // %0 = load i32, ptr %call4, align 4, !dbg !1076, !psr.id !1078 | ID: 25 const auto *LeakLoadInst = unittest::getInstAtOrNull( MainFunc, 16, 0, [](const llvm::Instruction *Inst) { return llvm::isa(Inst); }); -#endif - - llvm::outs() << "*(LeakCallInst->getOperand(0)): " - << *(LeakCallInst->getOperand(0)) << "\n"; - - // %0 = load i32, ptr %call4, align 4, !dbg !1076, !psr.id !1078 | ID: 25 - const auto *LeakLoadInst = LeakCallInst->getOperand(0); ASSERT_TRUE(LeakLoadInst); - ASSERT_TRUE(false); - const auto LeakLoadID = getMetaDataID(LeakLoadInst); const auto LeakCallID = getMetaDataID(LeakCallInst); @@ -375,7 +363,6 @@ TEST_F(IDETaintAnalysisTest, XTaint09) { doAnalysis(HA, Gt, std::monostate{}); } -#if false TEST_F(IDETaintAnalysisTest, DISABLED_XTaint10) { map> Gt; @@ -388,8 +375,9 @@ TEST_F(IDETaintAnalysisTest, DISABLED_XTaint10) { // TODO: Also update the Gt Gt[33] = {"32"}; + // TODO: ask Fabian, if this needs to be converted in the first place. // TODO: convert from hardcoded values to using the new dynamic approach (see - // xtaint20 for example). + // xtaint20 for example). Reenable test to check if everything works. HelperAnalyses HA({PathToLLFiles + "xtaint10_cpp_dbg.ll"}, EntryPoints); doAnalysis(HA, Gt, std::monostate{}); @@ -400,8 +388,6 @@ TEST_F(IDETaintAnalysisTest, DISABLED_XTaint11) { // no leaks expected; actually finds "27" at 28 - // TODO: convert from hardcoded values to using the new dynamic approach (see - // xtaint20 for example). HelperAnalyses HA({PathToLLFiles + "xtaint11_cpp_dbg.ll"}, EntryPoints); doAnalysis(HA, Gt, std::monostate{}); @@ -424,7 +410,10 @@ TEST_F(IDETaintAnalysisTest, XTaint12) { // sink(*getPtr(&ptaint)); const auto *LeakCallInst = unittest::getInstAtOrNull( MainFunc, 19, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); + // TODO: ask Fabian if the call inst with the empty name is the correct + // one. It is detected as a leak, but I am not sure if that is correct. + return llvm::isa(Inst) && + llvm::cast(Inst)->getName().empty(); }); ASSERT_TRUE(LeakCallInst); @@ -436,10 +425,10 @@ TEST_F(IDETaintAnalysisTest, XTaint12) { doAnalysis(HA, Gt, std::monostate{}); } - TEST_F(IDETaintAnalysisTest, XTaint13) { map> Gt; HelperAnalyses HA({PathToLLFiles + "xtaint13_cpp_dbg.ll"}, EntryPoints); + const auto &IRDB = HA.getProjectIRDB(); const auto *MainFunc = IRDB.getFunction("main"); @@ -468,6 +457,7 @@ TEST_F(IDETaintAnalysisTest, XTaint13) { TEST_F(IDETaintAnalysisTest, XTaint14) { map> Gt; HelperAnalyses HA({PathToLLFiles + "xtaint14_cpp_dbg.ll"}, EntryPoints); + const auto &IRDB = HA.getProjectIRDB(); const auto *MainFunc = IRDB.getFunction("main"); @@ -499,7 +489,7 @@ TEST_F(IDETaintAnalysisTest, DISABLED_XTaint15) { map> Gt; // TODO: convert from hardcoded values to using the new dynamic approach (see - // xtaint20 for example). + // xtaint20 for example). Reenable test to check if everything works. Gt[47] = {"46"}; HelperAnalyses HA({PathToLLFiles + "xtaint15_cpp_dbg.ll"}, EntryPoints); @@ -510,6 +500,7 @@ TEST_F(IDETaintAnalysisTest, DISABLED_XTaint15) { TEST_F(IDETaintAnalysisTest, XTaint16) { map> Gt; HelperAnalyses HA({PathToLLFiles + "xtaint16_cpp_dbg.ll"}, EntryPoints); + const auto &IRDB = HA.getProjectIRDB(); const auto *MainFunc = IRDB.getFunction("main"); @@ -539,6 +530,7 @@ TEST_F(IDETaintAnalysisTest, XTaint16) { TEST_F(IDETaintAnalysisTest, XTaint17) { map> Gt; HelperAnalyses HA({PathToLLFiles + "xtaint17_cpp_dbg.ll"}, EntryPoints); + const auto &IRDB = HA.getProjectIRDB(); const auto *MainFunc = IRDB.getFunction("main"); @@ -569,7 +561,7 @@ TEST_F(IDETaintAnalysisTest, XTaint18) { map> Gt; // TODO: convert from hardcoded values to using the new dynamic approach (see - // xtaint20 for example). + // xtaint20 for example). Reenable test to check if everything works. // Gt[26] = {"25"}; HelperAnalyses HA({PathToLLFiles + "xtaint18_cpp_dbg.ll"}, EntryPoints); @@ -583,7 +575,7 @@ PHASAR_SKIP_TEST(TEST_F(IDETaintAnalysisTest, XTaint19) { map> Gt; // TODO: convert from hardcoded values to using the new dynamic approach (see - // xtaint20 for example). + // xtaint20 for example). Reenable test to check if everything works. Gt[22] = {"21"}; HelperAnalyses HA({PathToLLFiles + "xtaint19_cpp_dbg.ll"}, EntryPoints); @@ -593,8 +585,8 @@ PHASAR_SKIP_TEST(TEST_F(IDETaintAnalysisTest, XTaint19) { TEST_F(IDETaintAnalysisTest, XTaint20) { map> Gt; - HelperAnalyses HA({PathToLLFiles + "xtaint20_cpp_dbg.ll"}, EntryPoints); + const auto &IRDB = HA.getProjectIRDB(); const auto *MainFunc = IRDB.getFunction("main"); @@ -636,8 +628,8 @@ TEST_F(IDETaintAnalysisTest, XTaint20) { TEST_F(IDETaintAnalysisTest, XTaint21) { map> Gt; - HelperAnalyses HA({PathToLLFiles + "xtaint21_cpp_dbg.ll"}, EntryPoints); + const auto &IRDB = HA.getProjectIRDB(); const auto *MainFunc = IRDB.getFunction("main"); @@ -699,8 +691,6 @@ TEST_F(IDETaintAnalysisTest, XTaint21) { doAnalysis(HA, Gt, CallBackPairTy{std::move(SourceCB), std::move(SinkCB)}); } -#endif - int main(int Argc, char **Argv) { ::testing::InitGoogleTest(&Argc, Argv); return RUN_ALL_TESTS(); From e12334e59bc0179b0407d6bb5a19fb2ca0bb2a60 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Wed, 2 Jul 2025 16:35:01 +0200 Subject: [PATCH 05/35] reworked test structure --- .../Problems/IDEExtendedTaintAnalysisTest.cpp | 561 +++++------------- .../Problems/IDEGeneralizedLCATest.cpp | 12 + 2 files changed, 162 insertions(+), 411 deletions(-) diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp index ddcd612036..464deaf6b9 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp @@ -40,6 +40,8 @@ #include #include +#include + using namespace std; using namespace psr; using json = nlohmann::json; @@ -47,6 +49,16 @@ using json = nlohmann::json; using CallBackPairTy = std::pair::config_callback_t, IDEExtendedTaintAnalysis<>::config_callback_t>; +struct SrcCodeLocEntry { + SrcCodeLocEntry(u_int32_t Line, std::vector Column) + : Line(Line), Column(std::move(Column)) {} + u_int32_t Line{}; + std::vector Column; + bool operator==(const SrcCodeLocEntry &Other) const { + return Line == Other.Line && Column == Other.Column; + } +}; + // /* ============== TEST FIXTURE ============== */ class IDETaintAnalysisTest : public ::testing::Test { @@ -58,7 +70,7 @@ class IDETaintAnalysisTest : public ::testing::Test { ~IDETaintAnalysisTest() override = default; void doAnalysis( - HelperAnalyses &HA, const map> &GroundTruth, + HelperAnalyses &HA, const std::vector &GroundTruth, std::variant Config, bool DumpResults = true) { @@ -101,23 +113,55 @@ class IDETaintAnalysisTest : public ::testing::Test { void compareResults(IDEExtendedTaintAnalysis<> &TaintProblem, IDESolver_P> &Solver, - const map> &GroundTruth) { + const std::vector &GroundTruth) { + std::vector FoundLeaks; + FoundLeaks.reserve( + TaintProblem.getAllLeaks(Solver.getSolverResults()).size()); - map> FoundLeaks; for (const auto &Leak : TaintProblem.getAllLeaks(Solver.getSolverResults())) { llvm::errs() << "Leak: " << PrettyPrinter{Leak} << '\n'; - int SinkId = stoi(getMetaDataID(Leak.first)); - set LeakedValueIds; + u_int32_t SinkId = Leak.first->getDebugLoc()->getLine(); + std::vector LeakedValueIds; + LeakedValueIds.reserve(Leak.second.size()); + for (const auto &LV : Leak.second) { - LeakedValueIds.insert(getMetaDataID(LV)); + if (const auto &Instr = llvm::dyn_cast_or_null(LV)) { + if (Instr->getDebugLoc()) { + LeakedValueIds.emplace_back(Instr->getDebugLoc()->getColumn()); + } else { + // getDebugLoc was null + llvm::outs() << "*Instr:\n"; + llvm::outs() << *Instr << "\n"; + ASSERT_TRUE(false); + } + } else { + // Instr was null + llvm::outs() << "LV Value: " << LV << "\n"; + ASSERT_TRUE(false); + } } - FoundLeaks.emplace(SinkId, LeakedValueIds); + + FoundLeaks.emplace_back(SinkId, LeakedValueIds); } + EXPECT_EQ(FoundLeaks, GroundTruth); + + llvm::outs() << "--------------------------------------------:\n"; + for (const auto &Leak : FoundLeaks) { + llvm::outs() << "Line:\n"; + llvm::outs() << Leak.Line << "\n"; + llvm::outs() << "Columns:\n"; + for (const auto &Vec : Leak.Column) { + llvm::outs() << Vec << "\n"; + } + } + llvm::outs() << "--------------------------------------------:\n"; } }; // Test Fixture +// TODO: +#if false TEST_F(IDETaintAnalysisTest, XTaint01_Json) { map> Gt; @@ -140,531 +184,225 @@ TEST_F(IDETaintAnalysisTest, XTaint01_Json) { doAnalysis(HA, Gt, &Config); } +#endif TEST_F(IDETaintAnalysisTest, XTaint01) { - map> Gt; + std::vector GroundTruth; + GroundTruth.reserve(1); HelperAnalyses HA({PathToLLFiles + "xtaint01_cpp_dbg.ll"}, EntryPoints); - const auto &IRDB = HA.getProjectIRDB(); - const auto *MainFunc = IRDB.getFunction("main"); + GroundTruth.emplace_back(SrcCodeLocEntry(8, {9})); - // - const auto *LeakLoadInst = unittest::getInstAtOrNull( - MainFunc, 8, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - ASSERT_TRUE(LeakLoadInst); - - // print(argc); - const auto *LeakCallInst = unittest::getInstAtOrNull( - MainFunc, 8, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - ASSERT_TRUE(LeakCallInst); - - const auto LeakLoadID = getMetaDataID(LeakLoadInst); - const auto LeakCallID = getMetaDataID(LeakCallInst); - - Gt[stoi(LeakCallID)] = {LeakLoadID}; - - doAnalysis(HA, Gt, std::monostate{}); + doAnalysis(HA, GroundTruth, std::monostate{}); } TEST_F(IDETaintAnalysisTest, XTaint02) { - map> Gt; + std::vector GroundTruth; + GroundTruth.reserve(1); HelperAnalyses HA({PathToLLFiles + "xtaint02_cpp_dbg.ll"}, EntryPoints); - const auto &IRDB = HA.getProjectIRDB(); - const auto *MainFunc = IRDB.getFunction("main"); - - // - const auto *LeakLoadInst = unittest::getInstAtOrNull( - MainFunc, 9, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - ASSERT_TRUE(LeakLoadInst); - - // print(array[0]); - const auto *LeakCallInst = unittest::getInstAtOrNull( - MainFunc, 9, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - ASSERT_TRUE(LeakCallInst); + GroundTruth.emplace_back(SrcCodeLocEntry(9, {9})); - const auto LeakLoadID = getMetaDataID(LeakLoadInst); - const auto LeakCallID = getMetaDataID(LeakCallInst); - - Gt[stoi(LeakCallID)] = {LeakLoadID}; - - doAnalysis(HA, Gt, std::monostate{}, true); + doAnalysis(HA, GroundTruth, std::monostate{}, true); } + TEST_F(IDETaintAnalysisTest, XTaint03) { - map> Gt; + std::vector GroundTruth; + GroundTruth.reserve(1); HelperAnalyses HA({PathToLLFiles + "xtaint03_cpp_dbg.ll"}, EntryPoints); - const auto &IRDB = HA.getProjectIRDB(); - const auto *MainFunc = IRDB.getFunction("main"); - - // %2 = load i32, ptr %arrayidx2, align 4, !dbg !62, !psr.id !64 | ID: 24 - const auto *LeakLoadInst = unittest::getInstAtOrNull( - MainFunc, 10, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - ASSERT_TRUE(LeakLoadInst); - - // print(array[1]); - const auto *LeakCallInst = unittest::getInstAtOrNull( - MainFunc, 10, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - ASSERT_TRUE(LeakCallInst); + GroundTruth.emplace_back(SrcCodeLocEntry(10, {9})); - const auto LeakLoadID = getMetaDataID(LeakLoadInst); - const auto LeakCallID = getMetaDataID(LeakCallInst); - - Gt[stoi(LeakCallID)] = {LeakLoadID}; - - doAnalysis(HA, Gt, std::monostate{}); + doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint04) { - map> Gt; + std::vector GroundTruth; + GroundTruth.reserve(1); HelperAnalyses HA({PathToLLFiles + "xtaint04_cpp_dbg.ll"}, EntryPoints); - const auto &IRDB = HA.getProjectIRDB(); - const auto *MainFunc = IRDB.getFunction("_Z3barPi"); - - // %3 = load i32, ptr %arrayidx1, align 4, !dbg !42, !psr.id !45 | ID: 17 - const auto *LeakLoadInst = unittest::getInstAtOrNull( - MainFunc, 6, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst) && - Inst->getOperand(0)->getName().str() == "arrayidx1"; - }); - ASSERT_TRUE(LeakLoadInst); - - // print(arr[0]); - const auto *LeakCallInst = unittest::getInstAtOrNull( - MainFunc, 6, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - ASSERT_TRUE(LeakCallInst); - - const auto LeakLoadID = getMetaDataID(LeakLoadInst); - const auto LeakCallID = getMetaDataID(LeakCallInst); - - Gt[stoi(LeakCallID)] = {LeakLoadID}; + GroundTruth.emplace_back(SrcCodeLocEntry(6, {9})); - doAnalysis(HA, Gt, std::monostate{}); + doAnalysis(HA, GroundTruth, std::monostate{}, true); } // XTaint05 is similar to 06, but even harder TEST_F(IDETaintAnalysisTest, XTaint06) { - // no leaks expected - - map> Gt; + std::vector GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint06_cpp_dbg.ll"}, EntryPoints); - doAnalysis(HA, Gt, std::monostate{}); + // no leaks expected + + doAnalysis(HA, 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. TEST_F(IDETaintAnalysisTest, DISABLED_XTaint07) { - map> Gt; - - Gt[21] = {"20"}; - - // TODO: convert from hardcoded values to using the new dynamic approach (see - // xtaint20 for example). Reenable test to check if everything works. + std::vector GroundTruth; + GroundTruth.reserve(1); HelperAnalyses HA({PathToLLFiles + "xtaint07_cpp_dbg.ll"}, EntryPoints); - doAnalysis(HA, Gt, std::monostate{}); + GroundTruth.emplace_back(SrcCodeLocEntry(10, {18})); + + doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, DISABLED_XTaint08) { - map> Gt; - - Gt[24] = {"23"}; - - // TODO: convert from hardcoded values to using the new dynamic approach (see - // xtaint20 for example). Reenable test to check if everything works. + std::vector GroundTruth; + GroundTruth.reserve(1); HelperAnalyses HA({PathToLLFiles + "xtaint08_cpp_dbg.ll"}, EntryPoints); - doAnalysis(HA, Gt, std::monostate{}); + GroundTruth.emplace_back(SrcCodeLocEntry(20, {18})); + + doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint09_1) { - map> Gt; + std::vector GroundTruth; + GroundTruth.reserve(1); HelperAnalyses HA({PathToLLFiles + "xtaint09_1_cpp_dbg.ll"}, EntryPoints); - const auto &IRDB = HA.getProjectIRDB(); - const auto *MainFunc = IRDB.getFunction("main"); - - // sink(*mem); - const auto *LeakCallInst = unittest::getInstAtOrNull( - MainFunc, 14, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - ASSERT_TRUE(LeakCallInst); - - // TODO: ask fabian if this is okay. I am not using getInstAtOrNull here and I - // am not tying the unit test to the .cpp file. - const auto *LeakLoadInst = LeakCallInst->getOperand(0); -#if false - const auto *LeakLoadInst = unittest::getInstAtOrNull( - MainFunc, 14, 0, [LeakCallInst](const llvm::Instruction *Inst) { - if (Inst) { - llvm::outs() << "Inst op 0: " << Inst->getOperand(0)->getName().str() - << "\n"; - } - return Inst == LeakCallInst->getOperand(0); - }); -#endif - ASSERT_TRUE(LeakLoadInst); + GroundTruth.emplace_back(SrcCodeLocEntry(14, {8})); - const auto LeakLoadID = getMetaDataID(LeakLoadInst); - const auto LeakCallID = getMetaDataID(LeakCallInst); - - Gt[stoi(LeakCallID)] = {LeakLoadID}; - - doAnalysis(HA, Gt, std::monostate{}); + doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint09) { - map> Gt; + std::vector GroundTruth; + GroundTruth.reserve(1); HelperAnalyses HA({PathToLLFiles + "xtaint09_cpp_dbg.ll"}, EntryPoints); - const auto &IRDB = HA.getProjectIRDB(); - const auto *MainFunc = IRDB.getFunction("main"); - - // sink(*mem); - const auto *LeakCallInst = unittest::getInstAtOrNull( - MainFunc, 16, 0, [](const llvm::Instruction *Inst) { - // TODO: ask Fabian if the call inst with the empty name is the correct - // one. It is detected as a leak, but I am not sure if that is correct. - return llvm::isa(Inst) && - llvm::cast(Inst)->getName().empty(); - }); - ASSERT_TRUE(LeakCallInst); - - // %0 = load i32, ptr %call4, align 4, !dbg !1076, !psr.id !1078 | ID: 25 - const auto *LeakLoadInst = unittest::getInstAtOrNull( - MainFunc, 16, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - ASSERT_TRUE(LeakLoadInst); - - const auto LeakLoadID = getMetaDataID(LeakLoadInst); - const auto LeakCallID = getMetaDataID(LeakCallInst); - - Gt[stoi(LeakCallID)] = {LeakLoadID}; - - doAnalysis(HA, Gt, std::monostate{}); + + GroundTruth.emplace_back(SrcCodeLocEntry(16, {8})); + + doAnalysis(HA, 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"}; - - // TODO: ask Fabian, if this needs to be converted in the first place. - // TODO: convert from hardcoded values to using the new dynamic approach (see - // xtaint20 for example). Reenable test to check if everything works. + std::vector GroundTruth; + GroundTruth.reserve(1); HelperAnalyses HA({PathToLLFiles + "xtaint10_cpp_dbg.ll"}, EntryPoints); - doAnalysis(HA, Gt, std::monostate{}); + // GroundTruth.emplace_back(SrcCodeLocEntry(, {})); + + doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, DISABLED_XTaint11) { - map> Gt; - - // no leaks expected; actually finds "27" at 28 - + std::vector GroundTruth; + GroundTruth.reserve(1); HelperAnalyses HA({PathToLLFiles + "xtaint11_cpp_dbg.ll"}, EntryPoints); - doAnalysis(HA, Gt, std::monostate{}); + // GroundTruth.emplace_back(SrcCodeLocEntry(, {})); + + doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint12) { - map> Gt; + std::vector GroundTruth; + GroundTruth.reserve(1); HelperAnalyses HA({PathToLLFiles + "xtaint12_cpp_dbg.ll"}, EntryPoints); - const auto &IRDB = HA.getProjectIRDB(); - const auto *MainFunc = IRDB.getFunction("main"); + GroundTruth.emplace_back(SrcCodeLocEntry(19, {8})); - // %0 = load i32, ptr %call2, align 4, !dbg !81, !psr.id !82 | ID: 32 - const auto *LeakLoadInst = unittest::getInstAtOrNull( - MainFunc, 19, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - ASSERT_TRUE(LeakLoadInst); - - // sink(*getPtr(&ptaint)); - const auto *LeakCallInst = unittest::getInstAtOrNull( - MainFunc, 19, 0, [](const llvm::Instruction *Inst) { - // TODO: ask Fabian if the call inst with the empty name is the correct - // one. It is detected as a leak, but I am not sure if that is correct. - return llvm::isa(Inst) && - llvm::cast(Inst)->getName().empty(); - }); - ASSERT_TRUE(LeakCallInst); - - const auto LeakLoadID = getMetaDataID(LeakLoadInst); - const auto LeakCallID = getMetaDataID(LeakCallInst); - - Gt[stoi(LeakCallID)] = {LeakLoadID}; - - doAnalysis(HA, Gt, std::monostate{}); + doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint13) { - map> Gt; + std::vector GroundTruth; + GroundTruth.reserve(1); HelperAnalyses HA({PathToLLFiles + "xtaint13_cpp_dbg.ll"}, EntryPoints); - const auto &IRDB = HA.getProjectIRDB(); - const auto *MainFunc = IRDB.getFunction("main"); - - // - const auto *LeakLoadInst = unittest::getInstAtOrNull( - MainFunc, 17, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - ASSERT_TRUE(LeakLoadInst); - - // sink(x); - const auto *LeakCallInst = unittest::getInstAtOrNull( - MainFunc, 17, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - ASSERT_TRUE(LeakCallInst); + GroundTruth.emplace_back(SrcCodeLocEntry(17, {8})); - const auto LeakLoadID = getMetaDataID(LeakLoadInst); - const auto LeakCallID = getMetaDataID(LeakCallInst); - - Gt[stoi(LeakCallID)] = {LeakLoadID}; - - doAnalysis(HA, Gt, std::monostate{}); + doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint14) { - map> Gt; + std::vector GroundTruth; + GroundTruth.reserve(1); HelperAnalyses HA({PathToLLFiles + "xtaint14_cpp_dbg.ll"}, EntryPoints); - const auto &IRDB = HA.getProjectIRDB(); - const auto *MainFunc = IRDB.getFunction("main"); - - // %3 = load i32, ptr %x, align 4, !dbg !93, !psr.id !94 | ID: 37 - const auto *LeakLoadInst = unittest::getInstAtOrNull( - MainFunc, 24, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - ASSERT_TRUE(LeakLoadInst); - - // sink(x); - const auto *LeakCallInst = unittest::getInstAtOrNull( - MainFunc, 24, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - ASSERT_TRUE(LeakCallInst); - - const auto LeakLoadID = getMetaDataID(LeakLoadInst); - const auto LeakCallID = getMetaDataID(LeakCallInst); + GroundTruth.emplace_back(SrcCodeLocEntry(24, {8})); - Gt[stoi(LeakCallID)] = {LeakLoadID}; - - doAnalysis(HA, Gt, std::monostate{}); + doAnalysis(HA, 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; - - // TODO: convert from hardcoded values to using the new dynamic approach (see - // xtaint20 for example). Reenable test to check if everything works. - Gt[47] = {"46"}; - + std::vector GroundTruth; + GroundTruth.reserve(1); HelperAnalyses HA({PathToLLFiles + "xtaint15_cpp_dbg.ll"}, EntryPoints); - doAnalysis(HA, Gt, std::monostate{}); + // GroundTruth.emplace_back(SrcCodeLocEntry(, {})); + + doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint16) { - map> Gt; + std::vector GroundTruth; + GroundTruth.reserve(1); HelperAnalyses HA({PathToLLFiles + "xtaint16_cpp_dbg.ll"}, EntryPoints); - const auto &IRDB = HA.getProjectIRDB(); - const auto *MainFunc = IRDB.getFunction("main"); - - // %1 = load i32, ptr %x, align 4, !dbg !64, !psr.id !65 | ID: 27 - const auto *LeakLoadInst = unittest::getInstAtOrNull( - MainFunc, 13, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - ASSERT_TRUE(LeakLoadInst); + GroundTruth.emplace_back(SrcCodeLocEntry(13, {8})); - // we can skip the sanitizer => leak here - // sink(x); - const auto *LeakCallInst = unittest::getInstAtOrNull( - MainFunc, 13, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - ASSERT_TRUE(LeakCallInst); - - const auto LeakLoadID = getMetaDataID(LeakLoadInst); - const auto LeakCallID = getMetaDataID(LeakCallInst); - - Gt[stoi(LeakCallID)] = {LeakLoadID}; - - doAnalysis(HA, Gt, std::monostate{}); + doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint17) { - map> Gt; + std::vector GroundTruth; + GroundTruth.reserve(1); HelperAnalyses HA({PathToLLFiles + "xtaint17_cpp_dbg.ll"}, EntryPoints); - const auto &IRDB = HA.getProjectIRDB(); - const auto *MainFunc = IRDB.getFunction("main"); - - // %1 = load i32, ptr %x, align 4, !dbg !76, !psr.id !77 | ID: 31 - const auto *LeakLoadInst = unittest::getInstAtOrNull( - MainFunc, 17, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - ASSERT_TRUE(LeakLoadInst); - - // we can skip the sanitizer => leak here - // sink(x); - const auto *LeakCallInst = unittest::getInstAtOrNull( - MainFunc, 17, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - ASSERT_TRUE(LeakCallInst); + GroundTruth.emplace_back(SrcCodeLocEntry(17, {8})); - const auto LeakLoadID = getMetaDataID(LeakLoadInst); - const auto LeakCallID = getMetaDataID(LeakCallInst); - - Gt[stoi(LeakCallID)] = {LeakLoadID}; - - doAnalysis(HA, Gt, std::monostate{}); + doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint18) { - map> Gt; - - // TODO: convert from hardcoded values to using the new dynamic approach (see - // xtaint20 for example). Reenable test to check if everything works. - // Gt[26] = {"25"}; - + std::vector GroundTruth; + GroundTruth.reserve(1); HelperAnalyses HA({PathToLLFiles + "xtaint18_cpp_dbg.ll"}, EntryPoints); - doAnalysis(HA, Gt, std::monostate{}); + // TODO: ask Fabian why there are no leaks found for this test + // I added a random GT, so that the test fails and it won't be overlooked. + GroundTruth.emplace_back(SrcCodeLocEntry(100000, {100000})); + + doAnalysis(HA, GroundTruth, std::monostate{}, true); } PHASAR_SKIP_TEST(TEST_F(IDETaintAnalysisTest, XTaint19) { // Is now the same as XTaint17 GTEST_SKIP(); - map> Gt; - - // TODO: convert from hardcoded values to using the new dynamic approach (see - // xtaint20 for example). Reenable test to check if everything works. - Gt[22] = {"21"}; + std::vector GroundTruth; + GroundTruth.reserve(1); HelperAnalyses HA({PathToLLFiles + "xtaint19_cpp_dbg.ll"}, EntryPoints); - doAnalysis(HA, Gt, std::monostate{}); + GroundTruth.emplace_back(SrcCodeLocEntry(17, {8})); + + doAnalysis(HA, GroundTruth, std::monostate{}, true); }) TEST_F(IDETaintAnalysisTest, XTaint20) { - map> Gt; + std::vector GroundTruth; + GroundTruth.reserve(2); HelperAnalyses HA({PathToLLFiles + "xtaint20_cpp_dbg.ll"}, EntryPoints); - const auto &IRDB = HA.getProjectIRDB(); - const auto *MainFunc = IRDB.getFunction("main"); - - // %x = alloca i32, align 4, !psr.id !48 | ID: 16 - const auto *FirstLeakAllocaInst = unittest::getInstAtOrNull(MainFunc, 6, 0); - ASSERT_TRUE(FirstLeakAllocaInst); - - // srcsink(x); // leak - const auto *FirstLeakCallInst = unittest::getInstAtOrNull( - MainFunc, 12, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - ASSERT_TRUE(FirstLeakCallInst); - - // %0 = load i32, ptr %y, align 4, !dbg !72, !psr.id !73 | ID: 29 - const auto *SecondLeakLoadInst = unittest::getInstAtOrNull( - MainFunc, 13, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - ASSERT_TRUE(SecondLeakLoadInst); - - // sink(y); // leak - const auto *SecondLeakCallInst = unittest::getInstAtOrNull( - MainFunc, 13, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - ASSERT_TRUE(SecondLeakCallInst); - - const auto FirstLeakAllocaID = getMetaDataID(FirstLeakAllocaInst); - const auto FirstLeakCallID = getMetaDataID(FirstLeakCallInst); - const auto SecondLeakLoadID = getMetaDataID(SecondLeakLoadInst); - const auto SecondLeakCallID = getMetaDataID(SecondLeakCallInst); - - Gt[stoi(FirstLeakCallID)] = {FirstLeakAllocaID}; - Gt[stoi(SecondLeakCallID)] = {SecondLeakLoadID}; - - doAnalysis(HA, Gt, std::monostate{}); + GroundTruth.emplace_back(SrcCodeLocEntry(17, {8})); + + doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint21) { - map> Gt; + std::vector GroundTruth; + GroundTruth.reserve(1); HelperAnalyses HA({PathToLLFiles + "xtaint21_cpp_dbg.ll"}, EntryPoints); - const auto &IRDB = HA.getProjectIRDB(); - const auto *MainFunc = IRDB.getFunction("main"); - - // %x = alloca i32, align 4, !psr.id !21 | ID: 2 - const auto *FirstLeakAllocaInst = unittest::getInstAtOrNull(MainFunc, 11); - ASSERT_TRUE(FirstLeakAllocaInst); - - // srcsink(x); // leak - const auto *FirstLeakCallInst = unittest::getInstAtOrNull( - MainFunc, 17, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - ASSERT_TRUE(FirstLeakCallInst); - - // %0 = load i32, ptr %y, align 4, !dbg !45, !psr.id !46 | ID: 15 - const auto *SecondLeakLoadInst = unittest::getInstAtOrNull( - MainFunc, 18, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - ASSERT_TRUE(SecondLeakLoadInst); - - // sink(y); // leak - const auto *SecondLeakCallInst = unittest::getInstAtOrNull( - MainFunc, 18, 0, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - ASSERT_TRUE(SecondLeakCallInst); - - const auto FirstLeakAllocaID = getMetaDataID(FirstLeakAllocaInst); - const auto FirstLeakCallID = getMetaDataID(FirstLeakCallInst); - const auto SecondLeakLoadID = getMetaDataID(SecondLeakLoadInst); - const auto SecondLeakCallID = getMetaDataID(SecondLeakCallInst); - - Gt[stoi(FirstLeakCallID)] = {FirstLeakAllocaID}; - Gt[stoi(SecondLeakCallID)] = {SecondLeakLoadID}; + GroundTruth.emplace_back(SrcCodeLocEntry(17, {8})); IDEExtendedTaintAnalysis<>::config_callback_t SourceCB = [](const llvm::Instruction *Inst) { @@ -688,7 +426,8 @@ TEST_F(IDETaintAnalysisTest, XTaint21) { return Ret; }; - doAnalysis(HA, Gt, CallBackPairTy{std::move(SourceCB), std::move(SinkCB)}); + doAnalysis(HA, GroundTruth, + CallBackPairTy{std::move(SourceCB), std::move(SinkCB)}); } int main(int Argc, char **Argv) { diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp index d81885c43f..1295ac7f26 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp @@ -27,12 +27,24 @@ #include #include +#include + using namespace psr; using namespace psr::glca; using groundTruth_t = std::tuple; +struct SrcCodeLocEntry { + SrcCodeLocEntry(u_int32_t Line, std::vector Column) + : Line(Line), Column(std::move(Column)) {} + u_int32_t Line{}; + std::vector Column; + bool operator==(const SrcCodeLocEntry &Other) const { + return Line == Other.Line && Column == Other.Column; + } +}; + /* ============== TEST FIXTURE ============== */ class IDEGeneralizedLCATest : public ::testing::Test { From 2ea2e4ffdd60f8e5f75f04560703e102def065e5 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Tue, 8 Jul 2025 23:42:13 +0200 Subject: [PATCH 06/35] refractor + more tests. Weird errors --- include/phasar/Utils/SrcCodeLocationEntry.h | 25 +++ .../Problems/IDEExtendedTaintAnalysisTest.cpp | 143 +++++++----------- .../Problems/IDEGeneralizedLCATest.cpp | 89 ++++++++--- .../Problems/IFDSTaintAnalysisTest.cpp | 132 +++++++++------- .../IFDSUninitializedVariablesTest.cpp | 45 ++++-- 5 files changed, 254 insertions(+), 180 deletions(-) create mode 100644 include/phasar/Utils/SrcCodeLocationEntry.h diff --git a/include/phasar/Utils/SrcCodeLocationEntry.h b/include/phasar/Utils/SrcCodeLocationEntry.h new file mode 100644 index 0000000000..1c29322188 --- /dev/null +++ b/include/phasar/Utils/SrcCodeLocationEntry.h @@ -0,0 +1,25 @@ +#ifndef PHASAR_UTILS_SRCCODELOCATIONENTRY_H +#define PHASAR_UTILS_SRCCODELOCATIONENTRY_H + +#include + +#include + +namespace psr { + +struct SrcCodeLocationEntry { + SrcCodeLocationEntry(u_int32_t Line, std::set Column) + : Line(Line), Column(std::move(Column)) {} + u_int32_t Line{}; + std::set Column; + bool operator==(const SrcCodeLocationEntry &Other) const { + return Line == Other.Line && Column == Other.Column; + } + bool operator<(const SrcCodeLocationEntry &Other) const { + return Line < Other.Line && Column < Other.Column; + } +}; + +} // namespace psr + +#endif diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp index 464deaf6b9..c5c8b27c66 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp @@ -20,6 +20,7 @@ #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "phasar/Utils/DebugOutput.h" +#include "phasar/Utils/SrcCodeLocationEntry.h" #include "phasar/Utils/Utilities.h" #include "llvm/ADT/DenseSet.h" @@ -40,8 +41,6 @@ #include #include -#include - using namespace std; using namespace psr; using json = nlohmann::json; @@ -49,16 +48,6 @@ using json = nlohmann::json; using CallBackPairTy = std::pair::config_callback_t, IDEExtendedTaintAnalysis<>::config_callback_t>; -struct SrcCodeLocEntry { - SrcCodeLocEntry(u_int32_t Line, std::vector Column) - : Line(Line), Column(std::move(Column)) {} - u_int32_t Line{}; - std::vector Column; - bool operator==(const SrcCodeLocEntry &Other) const { - return Line == Other.Line && Column == Other.Column; - } -}; - // /* ============== TEST FIXTURE ============== */ class IDETaintAnalysisTest : public ::testing::Test { @@ -70,7 +59,7 @@ class IDETaintAnalysisTest : public ::testing::Test { ~IDETaintAnalysisTest() override = default; void doAnalysis( - HelperAnalyses &HA, const std::vector &GroundTruth, + HelperAnalyses &HA, const std::set &GroundTruth, std::variant Config, bool DumpResults = true) { @@ -113,27 +102,25 @@ class IDETaintAnalysisTest : public ::testing::Test { void compareResults(IDEExtendedTaintAnalysis<> &TaintProblem, IDESolver_P> &Solver, - const std::vector &GroundTruth) { - std::vector FoundLeaks; - FoundLeaks.reserve( - TaintProblem.getAllLeaks(Solver.getSolverResults()).size()); + const std::set &GroundTruth) { + std::set FoundLeaks; for (const auto &Leak : TaintProblem.getAllLeaks(Solver.getSolverResults())) { llvm::errs() << "Leak: " << PrettyPrinter{Leak} << '\n'; u_int32_t SinkId = Leak.first->getDebugLoc()->getLine(); - std::vector LeakedValueIds; - LeakedValueIds.reserve(Leak.second.size()); + std::set LeakedValueIds; for (const auto &LV : Leak.second) { if (const auto &Instr = llvm::dyn_cast_or_null(LV)) { + // TODO: Why is getDebugLoc() null sometimes? if (Instr->getDebugLoc()) { - LeakedValueIds.emplace_back(Instr->getDebugLoc()->getColumn()); + LeakedValueIds.insert(Instr->getDebugLoc()->getColumn()); } else { // getDebugLoc was null llvm::outs() << "*Instr:\n"; llvm::outs() << *Instr << "\n"; - ASSERT_TRUE(false); + // ASSERT_TRUE(false); } } else { // Instr was null @@ -142,7 +129,7 @@ class IDETaintAnalysisTest : public ::testing::Test { } } - FoundLeaks.emplace_back(SinkId, LeakedValueIds); + FoundLeaks.insert({SinkId, LeakedValueIds}); } EXPECT_EQ(FoundLeaks, GroundTruth); @@ -160,12 +147,8 @@ class IDETaintAnalysisTest : public ::testing::Test { } }; // Test Fixture -// TODO: -#if false TEST_F(IDETaintAnalysisTest, XTaint01_Json) { - map> Gt; - - Gt[7] = {"6"}; + std::set GroundTruth; TaintConfigData Config; @@ -182,46 +165,41 @@ TEST_F(IDETaintAnalysisTest, XTaint01_Json) { HelperAnalyses HA({PathToLLFiles + "xtaint01_json_cpp_dbg.ll"}, EntryPoints); - doAnalysis(HA, Gt, &Config); + doAnalysis(HA, GroundTruth, &Config); } -#endif TEST_F(IDETaintAnalysisTest, XTaint01) { - std::vector GroundTruth; - GroundTruth.reserve(1); + std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint01_cpp_dbg.ll"}, EntryPoints); - GroundTruth.emplace_back(SrcCodeLocEntry(8, {9})); + GroundTruth.insert(SrcCodeLocationEntry(8, {9})); doAnalysis(HA, GroundTruth, std::monostate{}); } TEST_F(IDETaintAnalysisTest, XTaint02) { - std::vector GroundTruth; - GroundTruth.reserve(1); + std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint02_cpp_dbg.ll"}, EntryPoints); - GroundTruth.emplace_back(SrcCodeLocEntry(9, {9})); + GroundTruth.insert(SrcCodeLocationEntry(9, {9})); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint03) { - std::vector GroundTruth; - GroundTruth.reserve(1); + std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint03_cpp_dbg.ll"}, EntryPoints); - GroundTruth.emplace_back(SrcCodeLocEntry(10, {9})); + GroundTruth.insert(SrcCodeLocationEntry(10, {9})); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint04) { - std::vector GroundTruth; - GroundTruth.reserve(1); + std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint04_cpp_dbg.ll"}, EntryPoints); - GroundTruth.emplace_back(SrcCodeLocEntry(6, {9})); + GroundTruth.insert(SrcCodeLocationEntry(6, {9})); doAnalysis(HA, GroundTruth, std::monostate{}, true); } @@ -229,7 +207,7 @@ TEST_F(IDETaintAnalysisTest, XTaint04) { // XTaint05 is similar to 06, but even harder TEST_F(IDETaintAnalysisTest, XTaint06) { - std::vector GroundTruth; + std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint06_cpp_dbg.ll"}, EntryPoints); // no leaks expected @@ -241,91 +219,82 @@ TEST_F(IDETaintAnalysisTest, XTaint06) { /// parameters of C-style variadic functions is not (yet?) supported. So, the /// tests XTaint07 and XTaint08 are disabled. TEST_F(IDETaintAnalysisTest, DISABLED_XTaint07) { - std::vector GroundTruth; - GroundTruth.reserve(1); + std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint07_cpp_dbg.ll"}, EntryPoints); - GroundTruth.emplace_back(SrcCodeLocEntry(10, {18})); + GroundTruth.insert(SrcCodeLocationEntry(10, {18})); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, DISABLED_XTaint08) { - std::vector GroundTruth; - GroundTruth.reserve(1); + std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint08_cpp_dbg.ll"}, EntryPoints); - GroundTruth.emplace_back(SrcCodeLocEntry(20, {18})); + GroundTruth.insert(SrcCodeLocationEntry(20, {18})); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint09_1) { - std::vector GroundTruth; - GroundTruth.reserve(1); + std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint09_1_cpp_dbg.ll"}, EntryPoints); - GroundTruth.emplace_back(SrcCodeLocEntry(14, {8})); + GroundTruth.insert(SrcCodeLocationEntry(14, {8})); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint09) { - std::vector GroundTruth; - GroundTruth.reserve(1); + std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint09_cpp_dbg.ll"}, EntryPoints); - GroundTruth.emplace_back(SrcCodeLocEntry(16, {8})); + GroundTruth.insert(SrcCodeLocationEntry(16, {8})); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, DISABLED_XTaint10) { - std::vector GroundTruth; - GroundTruth.reserve(1); + std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint10_cpp_dbg.ll"}, EntryPoints); - // GroundTruth.emplace_back(SrcCodeLocEntry(, {})); + // GroundTruth.insert(SrcCodeLocEntry(, {})); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, DISABLED_XTaint11) { - std::vector GroundTruth; - GroundTruth.reserve(1); + std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint11_cpp_dbg.ll"}, EntryPoints); - // GroundTruth.emplace_back(SrcCodeLocEntry(, {})); + // GroundTruth.insert(SrcCodeLocEntry(, {})); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint12) { - std::vector GroundTruth; - GroundTruth.reserve(1); + std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint12_cpp_dbg.ll"}, EntryPoints); - GroundTruth.emplace_back(SrcCodeLocEntry(19, {8})); + GroundTruth.insert(SrcCodeLocationEntry(19, {8})); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint13) { - std::vector GroundTruth; - GroundTruth.reserve(1); + std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint13_cpp_dbg.ll"}, EntryPoints); - GroundTruth.emplace_back(SrcCodeLocEntry(17, {8})); + GroundTruth.insert(SrcCodeLocationEntry(17, {8})); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint14) { - std::vector GroundTruth; - GroundTruth.reserve(1); + std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint14_cpp_dbg.ll"}, EntryPoints); - GroundTruth.emplace_back(SrcCodeLocEntry(24, {8})); + GroundTruth.insert(SrcCodeLocationEntry(24, {8})); doAnalysis(HA, GroundTruth, std::monostate{}, true); } @@ -333,43 +302,39 @@ TEST_F(IDETaintAnalysisTest, XTaint14) { /// The TaintConfig fails to get all call-sites of Source::get, because it has /// no CallGraph information TEST_F(IDETaintAnalysisTest, DISABLED_XTaint15) { - std::vector GroundTruth; - GroundTruth.reserve(1); + std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint15_cpp_dbg.ll"}, EntryPoints); - // GroundTruth.emplace_back(SrcCodeLocEntry(, {})); + // GroundTruth.insert(SrcCodeLocEntry(, {})); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint16) { - std::vector GroundTruth; - GroundTruth.reserve(1); + std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint16_cpp_dbg.ll"}, EntryPoints); - GroundTruth.emplace_back(SrcCodeLocEntry(13, {8})); + GroundTruth.insert(SrcCodeLocationEntry(13, {8})); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint17) { - std::vector GroundTruth; - GroundTruth.reserve(1); + std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint17_cpp_dbg.ll"}, EntryPoints); - GroundTruth.emplace_back(SrcCodeLocEntry(17, {8})); + GroundTruth.insert(SrcCodeLocationEntry(17, {8})); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint18) { - std::vector GroundTruth; - GroundTruth.reserve(1); + std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint18_cpp_dbg.ll"}, EntryPoints); // TODO: ask Fabian why there are no leaks found for this test // I added a random GT, so that the test fails and it won't be overlooked. - GroundTruth.emplace_back(SrcCodeLocEntry(100000, {100000})); + GroundTruth.insert(SrcCodeLocationEntry(100000, {100000})); doAnalysis(HA, GroundTruth, std::monostate{}, true); } @@ -378,31 +343,29 @@ PHASAR_SKIP_TEST(TEST_F(IDETaintAnalysisTest, XTaint19) { // Is now the same as XTaint17 GTEST_SKIP(); - std::vector GroundTruth; - GroundTruth.reserve(1); + std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint19_cpp_dbg.ll"}, EntryPoints); - GroundTruth.emplace_back(SrcCodeLocEntry(17, {8})); + GroundTruth.insert(SrcCodeLocationEntry(17, {8})); doAnalysis(HA, GroundTruth, std::monostate{}, true); }) TEST_F(IDETaintAnalysisTest, XTaint20) { - std::vector GroundTruth; - GroundTruth.reserve(2); + std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint20_cpp_dbg.ll"}, EntryPoints); - GroundTruth.emplace_back(SrcCodeLocEntry(17, {8})); + GroundTruth.insert(SrcCodeLocationEntry(12, {11})); + GroundTruth.insert(SrcCodeLocationEntry(13, {8})); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint21) { - std::vector GroundTruth; - GroundTruth.reserve(1); + std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint21_cpp_dbg.ll"}, EntryPoints); - GroundTruth.emplace_back(SrcCodeLocEntry(17, {8})); + GroundTruth.insert(SrcCodeLocationEntry(17, {8})); IDEExtendedTaintAnalysis<>::config_callback_t SourceCB = [](const llvm::Instruction *Inst) { diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp index 1295ac7f26..23522e9edb 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp @@ -11,6 +11,7 @@ #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" @@ -18,33 +19,22 @@ #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "phasar/Utils/Logger.h" +#include "phasar/Utils/SrcCodeLocationEntry.h" #include "llvm/Support/raw_ostream.h" +#include "SourceMapping.h" #include "TestConfig.h" #include "gtest/gtest.h" -#include #include -#include - using namespace psr; using namespace psr::glca; using groundTruth_t = std::tuple; -struct SrcCodeLocEntry { - SrcCodeLocEntry(u_int32_t Line, std::vector Column) - : Line(Line), Column(std::move(Column)) {} - u_int32_t Line{}; - std::vector Column; - bool operator==(const SrcCodeLocEntry &Other) const { - return Line == Other.Line && Column == Other.Column; - } -}; - /* ============== TEST FIXTURE ============== */ class IDEGeneralizedLCATest : public ::testing::Test { @@ -79,29 +69,86 @@ class IDEGeneralizedLCATest : public ::testing::Test { // compare results /// \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) { + void compareResults(const std::vector &Expected, + const std::vector &EVal, + const llvm::StringRef FuncName) { + const auto *Func = HA->getProjectIRDB().getFunction(FuncName); + + if (!Func) { + llvm::outs() << "Func is nullptr, wasn't found!!!\n"; + ASSERT_NE(nullptr, Func); + } + + for (const auto &Entry : Expected) { + const auto *Vr = unittest::getInstAtOrNull(Func, 5, 3); + const auto *Inst = unittest::getInstAtOrNull(Func, 6, 3); + + bool Flag = false; + + if (Vr) { + llvm::outs() << "VrId Inst: " << *Vr << "\n"; + } else { + llvm::outs() << "VrId is nullptr\n"; + Flag = true; + } + + if (Inst) { + llvm::outs() << "InstID Inst: " << *Inst << "\n"; + } else { + llvm::outs() << "Inst is nullptr\n"; + Flag = true; + } + + if (Flag) { + continue; + } + + ASSERT_NE(nullptr, Vr); + ASSERT_NE(nullptr, Inst); + + auto Result = LCASolver->resultAt(Inst, Vr); + // EXPECT_EQ(EVal, Result) + // << "vr:" << Vr->getValueID() << " inst:" << Inst->getValueID() + // << " Expected: " << EVal << " Got:" << Result; + } + + /*for (const auto &[EVal, VrId, InstId] : Expected) { const auto *Vr = HA->getProjectIRDB().getInstruction(VrId); const auto *Inst = HA->getProjectIRDB().getInstruction(InstId); + llvm::outs() << "VrId Inst: " << *Vr << "\n"; + llvm::outs() << "InstID Inst: " << *Inst << "\n"; 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; - } + }*/ } }; // class Fixture TEST_F(IDEGeneralizedLCATest, SimpleTest) { initialize("SimpleTest_c.ll"); - std::vector GroundTruth; - GroundTruth.push_back({{EdgeValue(10)}, 3, 20}); - GroundTruth.push_back({{EdgeValue(15)}, 4, 20}); - compareResults(GroundTruth); + std::vector GroundTruth; + // Old ground truth + // GroundTruth.push_back({{EdgeValue(10)}, 3, 20}); + // GroundTruth.push_back({{EdgeValue(15)}, 4, 20}); + + /* + TODO: No column values work?! + */ + + // New ground truth based on src file + GroundTruth.push_back(SrcCodeLocationEntry(5, {3})); + GroundTruth.push_back(SrcCodeLocationEntry(6, {3})); + std::vector EVs = {EdgeValue(10), EdgeValue(15)}; + + compareResults(GroundTruth, EVs, "main"); } +#if false + TEST_F(IDEGeneralizedLCATest, BranchTest) { initialize("BranchTest_c.ll"); std::vector GroundTruth; @@ -204,6 +251,8 @@ TEST_F(IDEGeneralizedLCATest, NullTest) { compareResults(GroundTruth); } +#endif + int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp index e050acc5dc..2eff2a7662 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp @@ -1,5 +1,6 @@ #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.h" +#include "phasar/DataFlow/IfdsIde/EdgeFunction.h" #include "phasar/DataFlow/IfdsIde/Solver/IFDSSolver.h" #include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" #include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" @@ -10,10 +11,17 @@ #include "phasar/PhasarLLVM/TaintConfig/LLVMTaintConfig.h" #include "phasar/PhasarLLVM/TaintConfig/TaintConfigBase.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" +#include "phasar/Utils/SrcCodeLocationEntry.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instruction.h" + +#include "SourceMapping.h" #include "TestConfig.h" #include "gtest/gtest.h" +#include #include using namespace std; @@ -81,10 +89,9 @@ class IFDSTaintAnalysisTest : public ::testing::Test { TaintProblem = createAnalysisProblem(*HA, &*TSF, EntryPoints); } - static void doAnalysis(const llvm::Twine &IRFile, const LLVMTaintConfig &Config, - const map> &GroundTruth) { + const std::set &GroundTruth) { HelperAnalyses HA(PathToLlFiles + IRFile, EntryPoints); auto TaintProblem = @@ -99,26 +106,44 @@ class IFDSTaintAnalysisTest : public ::testing::Test { } static void doAnalysis(const llvm::Twine &IRFile, - const map> &GroundTruth) { + const std::set &GroundTruth) { doAnalysis(IRFile, getDefaultConfig(), GroundTruth); } template static void compare(const LeaksTy &Leaks, - const map> &GroundTruth) { - map> FoundLeaks; + const std::set &GroundTruth) { + // TODO: zu std::set ändern + std::set FoundLeaks; for (const auto &Leak : Leaks) { - int SinkId = stoi(getMetaDataID(Leak.first)); - set LeakedValueIds; + uint32_t SinkId; + if (Leak.first) { + if (const auto *SinkInst = + llvm::dyn_cast_or_null(Leak.first)) { + SinkId = SinkInst->getDebugLoc()->getLine(); + llvm::outs() << "SinkId: " << SinkId << "\n"; + } + } + std::set LeakedValueIds; for (const auto *LV : Leak.second) { - LeakedValueIds.insert(getMetaDataID(LV)); + llvm::outs() << "*LV: " << *LV << "\n"; + if (LV) { + if (const auto *LVInst = + llvm::dyn_cast_or_null(LV)) { + LeakedValueIds.insert(LVInst->getDebugLoc()->getColumn()); + llvm::outs() << "getCol: " << LVInst->getDebugLoc()->getColumn() + << "\n"; + } + } + // LeakedValueIds.insert(getMetaDataID(LV)); } - FoundLeaks.insert(make_pair(SinkId, LeakedValueIds)); + FoundLeaks.insert({SinkId, LeakedValueIds}); } EXPECT_EQ(FoundLeaks, GroundTruth); } - void compareResults(const map> &GroundTruth) noexcept { + void + compareResults(const std::set &GroundTruth) noexcept { compare(TaintProblem->Leaks, GroundTruth); } }; // Test Fixture @@ -127,8 +152,8 @@ 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"}; + SrcCodeLocationEntry Entry(6, {8}); + std::set GroundTruth = {Entry}; compareResults(GroundTruth); } @@ -136,8 +161,8 @@ 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"}; + SrcCodeLocationEntry Entry(6, {11}); + std::set GroundTruth = {Entry}; compareResults(GroundTruth); } @@ -145,8 +170,8 @@ 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"}; + SrcCodeLocationEntry Entry(5, {8}); + std::set GroundTruth = {Entry}; compareResults(GroundTruth); } @@ -154,8 +179,8 @@ 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"}; + SrcCodeLocationEntry Entry(6, {8}); + std::set GroundTruth = {Entry}; compareResults(GroundTruth); } @@ -163,9 +188,9 @@ 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"}; + SrcCodeLocationEntry Entry(6, {8}); + SrcCodeLocationEntry EntryTwo(8, {8}); + std::set GroundTruth = {Entry, EntryTwo}; compareResults(GroundTruth); } @@ -173,11 +198,14 @@ 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"}; + SrcCodeLocationEntry Entry(6, {8}); + std::set GroundTruth = {Entry}; compareResults(GroundTruth); } +// TODO: Fabian fragen, wie man mit Ground Truth von "main.0" hier umgehen soll. +#if false + TEST_F(IFDSTaintAnalysisTest, TaintTest_06) { initialize({PathToLlFiles + "dummy_source_sink/taint_06_cpp_m2r_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); @@ -187,14 +215,14 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_06) { compareResults(GroundTruth); } +#endif + TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_01) { initialize( {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); + compareResults({{12, {8}}}); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_01_m2r) { @@ -202,9 +230,7 @@ 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); + compareResults({{12, {14}}}); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_02) { @@ -212,9 +238,7 @@ 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); + compareResults({{11, {8}}}); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_03) { @@ -222,9 +246,10 @@ 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"}; + // This test weirdly fails, when I just insert {{}, {}} into compareResults. + std::set GroundTruth; + GroundTruth.insert(SrcCodeLocationEntry{11, {8}}); + GroundTruth.insert(SrcCodeLocationEntry{14, {8}}); compareResults(GroundTruth); } @@ -233,9 +258,7 @@ 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); + compareResults({{16, {8}}}); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_05) { @@ -243,10 +266,7 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_05) { {PathToLlFiles + "dummy_source_sink/taint_exception_05_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - - map> GroundTruth; - GroundTruth[32] = set{"31"}; - compareResults(GroundTruth); + compareResults({{16, {8}}}); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_06) { @@ -254,9 +274,7 @@ 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); + compareResults({{13, {10}}}); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_07) { @@ -264,9 +282,7 @@ 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); + compareResults({{14, {10}}}); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_08) { @@ -274,9 +290,7 @@ 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); + compareResults({{19, {8}}}); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_09) { @@ -284,9 +298,7 @@ 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); + compareResults({{20, {8}}}); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_10) { @@ -294,18 +306,20 @@ 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); + compareResults({{19, {10}}}); } +// TODO: fix seg fault +#if false + TEST_F(IFDSTaintAnalysisTest, TaintTest_DoubleFree_01) { doAnalysis("double_free_01_c.ll", getDoubleFreeConfig(), { - {6, {"5"}}, + {6, {5}}, }); } + TEST_F(IFDSTaintAnalysisTest, TaintTest_DoubleFree_02) { doAnalysis("double_free_02_c.ll", getDoubleFreeConfig(), { @@ -322,6 +336,8 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_LibSummary_01) { compareResults(GroundTruth); } +#endif + int main(int Argc, char **Argv) { ::testing::InitGoogleTest(&Argc, Argv); return RUN_ALL_TESTS(); diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp index 51d7b04649..dc8d885842 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp @@ -1,6 +1,7 @@ #include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariables.h" +#include "phasar/DataFlow/IfdsIde/EdgeFunction.h" #include "phasar/DataFlow/IfdsIde/Solver/IFDSSolver.h" #include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" #include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" @@ -9,7 +10,9 @@ #include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h" #include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" +#include "phasar/Utils/SrcCodeLocationEntry.h" +#include "llvm/IR/Instruction.h" #include "llvm/IR/Module.h" #include "TestConfig.h" @@ -18,7 +21,8 @@ #include #include -using namespace std; +#include + using namespace psr; /* ============== TEST FIXTURE ============== */ @@ -46,16 +50,27 @@ class IFDSUninitializedVariablesTest : public ::testing::Test { void TearDown() override {} - void compareResults(map> &GroundTruth) { - - map> FoundUninitUses; + void compareResults(const std::set &GroundTruth) { + std::set FoundUninitUses; for (const auto &Kvp : UninitProblem->getAllUndefUses()) { - auto InstID = stoi(getMetaDataID(Kvp.first)); - set UndefValueIds; + if (!Kvp.first->getDebugLoc()) { + llvm::outs() << "\ngetDebugLoc() returns nullptr\n\n"; + ASSERT_TRUE(false); + } + u_int32_t InstID = Kvp.first->getDebugLoc().getLine(); + std::set UndefValueIds; for (const auto *UV : Kvp.second) { - UndefValueIds.insert(getMetaDataID(UV)); + if (const auto *UVInst = + llvm::dyn_cast_or_null(UV)) { + if (UVInst->getDebugLoc()) { + UndefValueIds.insert(UVInst->getDebugLoc().getCol()); + } else { + llvm::outs() << "\ngetDebugLoc().getCol() returns nullptr\n\n"; + ASSERT_TRUE(false); + } + } } - FoundUninitUses[InstID] = UndefValueIds; + FoundUninitUses.insert(SrcCodeLocationEntry(InstID, UndefValueIds)); } EXPECT_EQ(FoundUninitUses, GroundTruth); @@ -67,7 +82,7 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_01_SHOULD_NOT_LEAK) { IFDSSolver Solver(*UninitProblem, &HA->getICFG()); Solver.solve(); // all_uninit.cpp does not contain undef-uses - map> GroundTruth; + std::set GroundTruth; compareResults(GroundTruth); } @@ -77,14 +92,17 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_02_SHOULD_LEAK) { Solver.solve(); // binop_uninit uses uninitialized variable i in 'int j = i + 10;' - map> GroundTruth; + std::set GroundTruth; // %4 = load i32, i32* %2, ID: 6 ; %2 is the uninitialized variable i - GroundTruth[6] = {"1"}; + GroundTruth.insert(SrcCodeLocationEntry(2, {0})); // %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"}; + GroundTruth.insert(SrcCodeLocationEntry(3, {11})); compareResults(GroundTruth); } + +#if false + TEST_F(IFDSUninitializedVariablesTest, UninitTest_03_SHOULD_LEAK) { initialize({PathToLlFiles + "callnoret_c_dbg.ll"}); IFDSSolver Solver(*UninitProblem, &HA->getICFG()); @@ -381,6 +399,9 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_21_SHOULD_LEAK) { // 37 => {17}; actual leak compareResults(GroundTruth); } + +#endif + int main(int Argc, char **Argv) { ::testing::InitGoogleTest(&Argc, Argv); return RUN_ALL_TESTS(); From d1bd97f07fb3a45a338cc08edd5924c7a23064ac Mon Sep 17 00:00:00 2001 From: mxHuber Date: Tue, 15 Jul 2025 10:37:42 +0200 Subject: [PATCH 07/35] debug commit --- include/phasar/Utils/SrcCodeLocationEntry.h | 99 ++++++- .../Problems/IDEExtendedTaintAnalysisTest.cpp | 243 ++++++++++++------ .../Problems/IFDSConstAnalysisTest.cpp | 82 +++++- .../Problems/IFDSTaintAnalysisTest.cpp | 210 ++++++++++----- .../IFDSUninitializedVariablesTest.cpp | 48 ++-- 5 files changed, 485 insertions(+), 197 deletions(-) diff --git a/include/phasar/Utils/SrcCodeLocationEntry.h b/include/phasar/Utils/SrcCodeLocationEntry.h index 1c29322188..8901b71c94 100644 --- a/include/phasar/Utils/SrcCodeLocationEntry.h +++ b/include/phasar/Utils/SrcCodeLocationEntry.h @@ -1,23 +1,108 @@ #ifndef PHASAR_UTILS_SRCCODELOCATIONENTRY_H #define PHASAR_UTILS_SRCCODELOCATIONENTRY_H -#include +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Value.h" + +#include "SourceMapping.h" -#include +#include +#include +#include +#include namespace psr { struct SrcCodeLocationEntry { - SrcCodeLocationEntry(u_int32_t Line, std::set Column) - : Line(Line), Column(std::move(Column)) {} - u_int32_t Line{}; - std::set Column; + SrcCodeLocationEntry(uint32_t Line, uint32_t Column) + : Line(Line), Column(Column) {} + SrcCodeLocationEntry( + uint32_t Line, uint32_t Column, + std::function LambdaFunc) + : Line(Line), Column(Column), UseLambdaFunc(true), + LambdaFunc(std::move(LambdaFunc)) {} + uint32_t Line = 0; + uint32_t Column = 0; + + [[nodiscard]] bool shouldUseLambdaFunc() const { return UseLambdaFunc; } + [[nodiscard]] std::function + getLambdaFunc() const { + return LambdaFunc; + } + bool operator==(const SrcCodeLocationEntry &Other) const { return Line == Other.Line && Column == Other.Column; } bool operator<(const SrcCodeLocationEntry &Other) const { - return Line < Other.Line && Column < Other.Column; + return std::tie(Line, Column) < std::tie(Other.Line, Other.Column); } + +private: + bool UseLambdaFunc = false; + std::function LambdaFunc; +}; + +static std::set> +getGroundTruthInsts( + const std::set> + &GroundTruth, + const llvm::Function *Func) { + std::set> + GroundTruthEntries; + + for (const auto &Entry : GroundTruth) { + const auto &FirstEntry = std::get<0>(Entry); + const auto &SecondEntry = std::get<1>(Entry); + const llvm::Instruction *CurrInst = nullptr; + const llvm::Value *CurrVal = nullptr; + + if (FirstEntry.shouldUseLambdaFunc()) { + CurrInst = unittest::getInstAtOrNull( + Func, FirstEntry.Line, FirstEntry.Column, FirstEntry.getLambdaFunc()); + } else { + CurrInst = + unittest::getInstAtOrNull(Func, FirstEntry.Line, FirstEntry.Column); + } + + if (SecondEntry.shouldUseLambdaFunc()) { + CurrVal = + unittest::getInstAtOrNull(Func, SecondEntry.Line, SecondEntry.Column, + SecondEntry.getLambdaFunc()); + } else { + CurrVal = + unittest::getInstAtOrNull(Func, SecondEntry.Line, SecondEntry.Column); + } + + if (CurrInst) { + if (CurrVal) { + GroundTruthEntries.insert({CurrInst, CurrVal}); + } + } + } + + return GroundTruthEntries; +}; + +static std::set +getGroundTruthInsts(const std::set &GroundTruth, + const llvm::Function *Func) { + std::set GroundTruthEntries; + + for (const auto &Entry : GroundTruth) { + const llvm::Instruction *CurrInst = nullptr; + if (Entry.shouldUseLambdaFunc()) { + CurrInst = unittest::getInstAtOrNull(Func, Entry.Line, Entry.Column, + Entry.getLambdaFunc()); + } else { + CurrInst = unittest::getInstAtOrNull(Func, Entry.Line, Entry.Column); + } + + if (CurrInst) { + GroundTruthEntries.insert(CurrInst); + } + } + + return GroundTruthEntries; }; } // namespace psr diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp index c5c8b27c66..ca0aeaba3d 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp @@ -25,8 +25,11 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Demangle/Demangle.h" +#include "llvm/IR/Function.h" #include "llvm/IR/InstrTypes.h" +#include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" #include "llvm/Support/Casting.h" @@ -36,6 +39,7 @@ #include "gtest/gtest.h" #include "nlohmann/json.hpp" +#include #include #include #include @@ -59,10 +63,11 @@ class IDETaintAnalysisTest : public ::testing::Test { ~IDETaintAnalysisTest() override = default; void doAnalysis( - HelperAnalyses &HA, const std::set &GroundTruth, + HelperAnalyses &HA, + const std::set> + &GroundTruth, std::variant Config, - bool DumpResults = true) { - + bool DumpResults = true, const llvm::StringRef FuncName = "main") { auto TC = std::visit(Overloaded{[&](std::monostate) { return LLVMTaintConfig(HA.getProjectIRDB()); @@ -93,62 +98,82 @@ class IDETaintAnalysisTest : public ::testing::Test { TaintProblem.emitTextReport(Solver.getSolverResults()); - compareResults(TaintProblem, Solver, GroundTruth); + compareResults(TaintProblem, Solver, GroundTruth, + HA.getProjectIRDB().getFunction(FuncName)); } void SetUp() override { ValueAnnotationPass::resetValueID(); } void TearDown() override {} - void compareResults(IDEExtendedTaintAnalysis<> &TaintProblem, - IDESolver_P> &Solver, - const std::set &GroundTruth) { - std::set FoundLeaks; + void compareResults( + IDEExtendedTaintAnalysis<> &TaintProblem, + IDESolver_P> &Solver, + const std::set> + &GroundTruth, + const llvm::Function *Func) { + auto GroundTruthEntries = getGroundTruthInsts(GroundTruth, Func); + + // Debug stuff + uint32_t Line = 12; + std::set TestSet; + for (uint32_t Col = 0; Col < 30; Col++) { + SrcCodeLocationEntry Curr = {Line, Col}; + TestSet.insert(Curr); + } + llvm::outs() << "TestSet Size: " << TestSet.size() << "\n"; + + int Counter = 0; + + auto TestInsts = getGroundTruthInsts(TestSet, Func); + llvm::outs() << "Line: " << Line << "\n"; + llvm::outs() << "TestInsts Size: " << TestInsts.size() << "\n"; + for (const auto *Elem : TestInsts) { + if (Elem) { + llvm::outs() << Counter << ": " << *Elem << " \n"; + } else { + llvm::outs() << Counter << ": Was nullptr \n"; + } + Counter++; + } + // Debug stuff + + std::set> + FoundLeaks; for (const auto &Leak : TaintProblem.getAllLeaks(Solver.getSolverResults())) { llvm::errs() << "Leak: " << PrettyPrinter{Leak} << '\n'; - u_int32_t SinkId = Leak.first->getDebugLoc()->getLine(); - std::set LeakedValueIds; for (const auto &LV : Leak.second) { - if (const auto &Instr = llvm::dyn_cast_or_null(LV)) { - // TODO: Why is getDebugLoc() null sometimes? - if (Instr->getDebugLoc()) { - LeakedValueIds.insert(Instr->getDebugLoc()->getColumn()); - } else { - // getDebugLoc was null - llvm::outs() << "*Instr:\n"; - llvm::outs() << *Instr << "\n"; - // ASSERT_TRUE(false); - } - } else { - // Instr was null - llvm::outs() << "LV Value: " << LV << "\n"; - ASSERT_TRUE(false); - } + FoundLeaks.insert({Leak.first, LV}); } - - FoundLeaks.insert({SinkId, LeakedValueIds}); } - EXPECT_EQ(FoundLeaks, GroundTruth); + EXPECT_EQ(FoundLeaks, GroundTruthEntries); - llvm::outs() << "--------------------------------------------:\n"; + llvm::outs() << "-----------------GroundTruth----------------:\n"; + for (const auto &Leak : GroundTruthEntries) { + llvm::outs() << "std::get<0>:\n"; + llvm::outs() << *(std::get<0>(Leak)) << "\n"; + llvm::outs() << "std::get<1>:\n"; + llvm::outs() << *(std::get<1>(Leak)) << "\n"; + } + llvm::outs() << "------------------FoundLeaks----------------:\n"; for (const auto &Leak : FoundLeaks) { - llvm::outs() << "Line:\n"; - llvm::outs() << Leak.Line << "\n"; - llvm::outs() << "Columns:\n"; - for (const auto &Vec : Leak.Column) { - llvm::outs() << Vec << "\n"; - } + llvm::outs() << "std::get<0>:\n"; + llvm::outs() << *(std::get<0>(Leak)) << "\n"; + llvm::outs() << "std::get<1>:\n"; + llvm::outs() << *(std::get<1>(Leak)) << "\n"; } llvm::outs() << "--------------------------------------------:\n"; } }; // Test Fixture TEST_F(IDETaintAnalysisTest, XTaint01_Json) { - std::set GroundTruth; + HelperAnalyses HA({PathToLLFiles + "xtaint01_json_cpp_dbg.ll"}, EntryPoints); + + std::set> GroundTruth; TaintConfigData Config; @@ -163,100 +188,146 @@ TEST_F(IDETaintAnalysisTest, XTaint01_Json) { Config.Functions.push_back(std::move(FuncDataMain)); Config.Functions.push_back(std::move(FuncDataPrint)); - HelperAnalyses HA({PathToLLFiles + "xtaint01_json_cpp_dbg.ll"}, EntryPoints); + GroundTruth.insert({{8, 3}, {8, 9}}); doAnalysis(HA, GroundTruth, &Config); } TEST_F(IDETaintAnalysisTest, XTaint01) { - std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint01_cpp_dbg.ll"}, EntryPoints); + std::set> GroundTruth; - GroundTruth.insert(SrcCodeLocationEntry(8, {9})); + GroundTruth.insert({{8, 3}, {8, 9}}); doAnalysis(HA, GroundTruth, std::monostate{}); } TEST_F(IDETaintAnalysisTest, XTaint02) { - std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint02_cpp_dbg.ll"}, EntryPoints); + std::set> GroundTruth; - GroundTruth.insert(SrcCodeLocationEntry(9, {9})); + SrcCodeLocationEntry Call = SrcCodeLocationEntry(9, 3); + SrcCodeLocationEntry Leak = + SrcCodeLocationEntry(9, 9, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + + GroundTruth.insert({Call, Leak}); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint03) { - std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint03_cpp_dbg.ll"}, EntryPoints); + std::set> GroundTruth; + + SrcCodeLocationEntry Call = SrcCodeLocationEntry(10, 3); + SrcCodeLocationEntry Leak = + SrcCodeLocationEntry(10, 9, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); - GroundTruth.insert(SrcCodeLocationEntry(10, {9})); + GroundTruth.insert({Call, Leak}); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint04) { - std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint04_cpp_dbg.ll"}, EntryPoints); + std::set> GroundTruth; - GroundTruth.insert(SrcCodeLocationEntry(6, {9})); + SrcCodeLocationEntry Call = SrcCodeLocationEntry(6, 3); - doAnalysis(HA, GroundTruth, std::monostate{}, true); + // TODO: this counter stuff is not good, but I haven't found a better way to + // implement this yet + int Counter = 0; + SrcCodeLocationEntry Leak = SrcCodeLocationEntry( + 6, 9, [Counter](const llvm::Instruction *Inst) mutable { + llvm::outs() << "Inst: " << *Inst << "\n"; + Counter++; + return Counter == 3; + }); + + GroundTruth.insert({Call, Leak}); + + doAnalysis(HA, GroundTruth, std::monostate{}, true, "_Z3barPi"); } // XTaint05 is similar to 06, but even harder TEST_F(IDETaintAnalysisTest, XTaint06) { - std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint06_cpp_dbg.ll"}, EntryPoints); + std::set> GroundTruth; // no leaks expected doAnalysis(HA, 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) { - std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint07_cpp_dbg.ll"}, EntryPoints); + std::set> GroundTruth; - GroundTruth.insert(SrcCodeLocationEntry(10, {18})); + SrcCodeLocationEntry Call = SrcCodeLocationEntry(10, 0); + SrcCodeLocationEntry Leak = + SrcCodeLocationEntry(10, 18, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + GroundTruth.insert({Call, Leak}); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, DISABLED_XTaint08) { - std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint08_cpp_dbg.ll"}, EntryPoints); + std::set> GroundTruth; - GroundTruth.insert(SrcCodeLocationEntry(20, {18})); + SrcCodeLocationEntry Call = SrcCodeLocationEntry(20, 0); + SrcCodeLocationEntry Leak = + SrcCodeLocationEntry(20, 18, [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + GroundTruth.insert({Call, Leak}); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint09_1) { - std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint09_1_cpp_dbg.ll"}, EntryPoints); + std::set> GroundTruth; - GroundTruth.insert(SrcCodeLocationEntry(14, {8})); + SrcCodeLocationEntry Call = SrcCodeLocationEntry(14, 3); + SrcCodeLocationEntry Leak = SrcCodeLocationEntry(14, 8); + GroundTruth.insert({Call, Leak}); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint09) { - std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint09_cpp_dbg.ll"}, EntryPoints); - - GroundTruth.insert(SrcCodeLocationEntry(16, {8})); + std::set> GroundTruth; + + SrcCodeLocationEntry Call = SrcCodeLocationEntry(16, 3); + // TODO: this counter stuff is not good, but I haven't found a better way to + // implement this yet + int Counter = 0; + SrcCodeLocationEntry Leak = SrcCodeLocationEntry( + 16, 8, [Counter](const llvm::Instruction *Inst) mutable { + llvm::outs() << "Inst: " << *Inst << "\n"; + Counter++; + return Counter == 2; + }); + GroundTruth.insert({Call, Leak}); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, DISABLED_XTaint10) { - std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint10_cpp_dbg.ll"}, EntryPoints); + std::set> GroundTruth; // GroundTruth.insert(SrcCodeLocEntry(, {})); @@ -264,8 +335,8 @@ TEST_F(IDETaintAnalysisTest, DISABLED_XTaint10) { } TEST_F(IDETaintAnalysisTest, DISABLED_XTaint11) { - std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint11_cpp_dbg.ll"}, EntryPoints); + std::set> GroundTruth; // GroundTruth.insert(SrcCodeLocEntry(, {})); @@ -273,28 +344,31 @@ TEST_F(IDETaintAnalysisTest, DISABLED_XTaint11) { } TEST_F(IDETaintAnalysisTest, XTaint12) { - std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint12_cpp_dbg.ll"}, EntryPoints); + std::set> GroundTruth; - GroundTruth.insert(SrcCodeLocationEntry(19, {8})); + GroundTruth.insert( + {SrcCodeLocationEntry(19, 3), SrcCodeLocationEntry(19, 8)}); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint13) { - std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint13_cpp_dbg.ll"}, EntryPoints); + std::set> GroundTruth; - GroundTruth.insert(SrcCodeLocationEntry(17, {8})); + GroundTruth.insert( + {SrcCodeLocationEntry(17, 3), SrcCodeLocationEntry(17, 8)}); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint14) { - std::set GroundTruth; + std::set> GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint14_cpp_dbg.ll"}, EntryPoints); - GroundTruth.insert(SrcCodeLocationEntry(24, {8})); + GroundTruth.insert( + {SrcCodeLocationEntry(24, 3), SrcCodeLocationEntry(24, 8)}); doAnalysis(HA, GroundTruth, std::monostate{}, true); } @@ -302,8 +376,8 @@ TEST_F(IDETaintAnalysisTest, XTaint14) { /// The TaintConfig fails to get all call-sites of Source::get, because it has /// no CallGraph information TEST_F(IDETaintAnalysisTest, DISABLED_XTaint15) { - std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint15_cpp_dbg.ll"}, EntryPoints); + std::set> GroundTruth; // GroundTruth.insert(SrcCodeLocEntry(, {})); @@ -311,30 +385,33 @@ TEST_F(IDETaintAnalysisTest, DISABLED_XTaint15) { } TEST_F(IDETaintAnalysisTest, XTaint16) { - std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint16_cpp_dbg.ll"}, EntryPoints); + std::set> GroundTruth; - GroundTruth.insert(SrcCodeLocationEntry(13, {8})); + GroundTruth.insert( + {SrcCodeLocationEntry(13, 3), SrcCodeLocationEntry(13, 8)}); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint17) { - std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint17_cpp_dbg.ll"}, EntryPoints); + std::set> GroundTruth; - GroundTruth.insert(SrcCodeLocationEntry(17, {8})); + GroundTruth.insert( + {SrcCodeLocationEntry(17, 3), SrcCodeLocationEntry(17, 8)}); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint18) { - std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint18_cpp_dbg.ll"}, EntryPoints); + std::set> GroundTruth; // TODO: ask Fabian why there are no leaks found for this test // I added a random GT, so that the test fails and it won't be overlooked. - GroundTruth.insert(SrcCodeLocationEntry(100000, {100000})); + GroundTruth.insert( + {SrcCodeLocationEntry(8, 10), SrcCodeLocationEntry(8, 14)}); doAnalysis(HA, GroundTruth, std::monostate{}, true); } @@ -343,29 +420,33 @@ PHASAR_SKIP_TEST(TEST_F(IDETaintAnalysisTest, XTaint19) { // Is now the same as XTaint17 GTEST_SKIP(); - std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint19_cpp_dbg.ll"}, EntryPoints); + std::set> GroundTruth; - GroundTruth.insert(SrcCodeLocationEntry(17, {8})); + GroundTruth.insert( + {SrcCodeLocationEntry(17, 3), SrcCodeLocationEntry(17, 8)}); doAnalysis(HA, GroundTruth, std::monostate{}, true); }) TEST_F(IDETaintAnalysisTest, XTaint20) { - std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint20_cpp_dbg.ll"}, EntryPoints); + std::set> GroundTruth; - GroundTruth.insert(SrcCodeLocationEntry(12, {11})); - GroundTruth.insert(SrcCodeLocationEntry(13, {8})); + GroundTruth.insert( + {SrcCodeLocationEntry(12, 3), SrcCodeLocationEntry(12, 11)}); + GroundTruth.insert( + {SrcCodeLocationEntry(13, 3), SrcCodeLocationEntry(13, 8)}); doAnalysis(HA, GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint21) { - std::set GroundTruth; HelperAnalyses HA({PathToLLFiles + "xtaint21_cpp_dbg.ll"}, EntryPoints); + std::set> GroundTruth; - GroundTruth.insert(SrcCodeLocationEntry(17, {8})); + GroundTruth.insert( + {SrcCodeLocationEntry(17, 3), SrcCodeLocationEntry(17, 8)}); IDEExtendedTaintAnalysis<>::config_callback_t SourceCB = [](const llvm::Instruction *Inst) { diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp index b36430c3c6..423dcae64d 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp @@ -10,12 +10,17 @@ #include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" +#include "phasar/Utils/SrcCodeLocationEntry.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" +#include "llvm/Support/Casting.h" #include "TestConfig.h" #include "gtest/gtest.h" +#include #include using namespace std; @@ -59,26 +64,53 @@ class IFDSConstAnalysisTest : public ::testing::Test { return RetOrResInstructions; } - void compareResults(const std::set &GroundTruth, - IFDSSolver_P &Solver) { + void compareResults(const std::set &GroundTruth, + IFDSSolver_P &Solver, + const llvm::Function *Func) { + /* --- Debug --- */ + std::set Test; + uint32_t Line = 3; + for (uint32_t Column = 0; Column < 30; Column++) { + Test.insert({Line, Column}); + } + llvm::outs() << "Line: " << Line << "\n"; + llvm::outs() << "Test size: " << Test.size() << "\n"; + auto TestInsts = getGroundTruthInsts(Test, Func); + for (const auto *Entry : TestInsts) { + llvm::outs() << "Test *Entry: " << *Entry << "\n"; + } + /* --- Debug --- */ + + auto GroundTruthEntriesAsInsts = getGroundTruthInsts(GroundTruth, Func); + std::set GroundTruthEntries; + for (const auto *Entry : GroundTruthEntriesAsInsts) { + llvm::outs() << "GT *Entry: " << *Entry << "\n"; + if (const auto *EntryVal = llvm::dyn_cast_or_null(Entry)) { + GroundTruthEntries.insert(EntryVal); + continue; + } + + llvm::outs() + << "Ground Truth Instruction was not a Value and can't be a " + "correct entry here. Please double check the Ground Truth.\n"; + ASSERT_TRUE(false); + } + 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() << "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(GroundTruthEntries, AllMutableAllocas); } }; @@ -87,28 +119,42 @@ 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, + HA->getProjectIRDB().getFunction("main")); } TEST_F(IFDSConstAnalysisTest, HandleBasicTest_02) { initialize({PathToLlFiles + "basic/basic_02_cpp_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({1}, Llvmconstsolver); + SrcCodeLocationEntry Entry(3, 0); + std::set GroundTruth; + GroundTruth.insert(Entry); + compareResults(GroundTruth, Llvmconstsolver, + HA->getProjectIRDB().getFunction("main")); } TEST_F(IFDSConstAnalysisTest, HandleBasicTest_03) { initialize({PathToLlFiles + "basic/basic_03_cpp_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({1}, Llvmconstsolver); + SrcCodeLocationEntry Entry(3, 0); + std::set GroundTruth; + GroundTruth.insert(Entry); + compareResults(GroundTruth, Llvmconstsolver, + HA->getProjectIRDB().getFunction("main")); } TEST_F(IFDSConstAnalysisTest, HandleBasicTest_04) { initialize({PathToLlFiles + "basic/basic_04_cpp_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({1}, Llvmconstsolver); + SrcCodeLocationEntry Entry(3, 0); + std::set GroundTruth; + GroundTruth.insert(Entry); + compareResults(GroundTruth, Llvmconstsolver, + HA->getProjectIRDB().getFunction("main")); } /* ============== CONTROL FLOW TESTS ============== */ @@ -116,9 +162,15 @@ 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); + SrcCodeLocationEntry Entry(3, 12); + std::set GroundTruth; + GroundTruth.insert(Entry); + compareResults(GroundTruth, Llvmconstsolver, + HA->getProjectIRDB().getFunction("main")); } +#if false + TEST_F(IFDSConstAnalysisTest, HandleCFForTest_02) { initialize({PathToLlFiles + "control_flow/cf_for_02_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); @@ -536,6 +588,8 @@ TEST_F(IFDSConstAnalysisTest, DISABLED_HandleCStringTest_02) { // compareResults({0}, llvmconstsolver); //} +#endif + // main function for the test case int main(int Argc, char **Argv) { ::testing::InitGoogleTest(&Argc, Argv); diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp index 2eff2a7662..b6954283dd 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp @@ -89,9 +89,11 @@ class IFDSTaintAnalysisTest : public ::testing::Test { TaintProblem = createAnalysisProblem(*HA, &*TSF, EntryPoints); } - static void doAnalysis(const llvm::Twine &IRFile, - const LLVMTaintConfig &Config, - const std::set &GroundTruth) { + static void doAnalysis( + const llvm::Twine &IRFile, const LLVMTaintConfig &Config, + const std::set> + &GroundTruth, + const llvm::StringRef FuncName) { HelperAnalyses HA(PathToLlFiles + IRFile, EntryPoints); auto TaintProblem = @@ -102,49 +104,51 @@ class IFDSTaintAnalysisTest : public ::testing::Test { TaintSolver.dumpResults(); - compare(TaintProblem.Leaks, GroundTruth); + compare(TaintProblem.Leaks, GroundTruth, + HA.getProjectIRDB().getFunction(FuncName)); } - static void doAnalysis(const llvm::Twine &IRFile, - const std::set &GroundTruth) { - doAnalysis(IRFile, getDefaultConfig(), GroundTruth); + static void doAnalysis( + const llvm::Twine &IRFile, + const std::set> + &GroundTruth, + const llvm::StringRef FuncName) { + doAnalysis(IRFile, getDefaultConfig(), GroundTruth, FuncName); } template - static void compare(const LeaksTy &Leaks, - const std::set &GroundTruth) { - // TODO: zu std::set ändern - std::set FoundLeaks; + static void + compare(const LeaksTy &Leaks, + const std::set> + &GroundTruth, + const llvm::Function *Func) { + auto GroundTruthEntries = getGroundTruthInsts(GroundTruth, Func); + + std::set> + FoundLeaks; for (const auto &Leak : Leaks) { - uint32_t SinkId; - if (Leak.first) { - if (const auto *SinkInst = - llvm::dyn_cast_or_null(Leak.first)) { - SinkId = SinkInst->getDebugLoc()->getLine(); - llvm::outs() << "SinkId: " << SinkId << "\n"; - } - } - std::set LeakedValueIds; - for (const auto *LV : Leak.second) { - llvm::outs() << "*LV: " << *LV << "\n"; - if (LV) { - if (const auto *LVInst = - llvm::dyn_cast_or_null(LV)) { - LeakedValueIds.insert(LVInst->getDebugLoc()->getColumn()); - llvm::outs() << "getCol: " << LVInst->getDebugLoc()->getColumn() - << "\n"; + if (const auto *SinkInst = + llvm::dyn_cast_or_null(Leak.first)) { + llvm::outs() << "*SinkInst: " << *SinkInst << "\n"; + for (const auto *LV : Leak.second) { + if (LV) { + if (const auto *LVValue = llvm::dyn_cast_or_null(LV)) { + llvm::outs() << "*LVValue: " << *LVValue << "\n"; + FoundLeaks.insert({SinkInst, {LVValue}}); + } } } - // LeakedValueIds.insert(getMetaDataID(LV)); } - FoundLeaks.insert({SinkId, LeakedValueIds}); } - EXPECT_EQ(FoundLeaks, GroundTruth); + EXPECT_EQ(FoundLeaks, GroundTruthEntries); } - void - compareResults(const std::set &GroundTruth) noexcept { - compare(TaintProblem->Leaks, GroundTruth); + void compareResults( + const std::set> + &GroundTruth, + const llvm::StringRef FuncName) noexcept { + compare(TaintProblem->Leaks, GroundTruth, + HA->getProjectIRDB().getFunction(FuncName)); } }; // Test Fixture @@ -152,55 +156,74 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_01) { initialize({PathToLlFiles + "dummy_source_sink/taint_01_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(6, {8}); - std::set GroundTruth = {Entry}; - compareResults(GroundTruth); + SrcCodeLocationEntry Entry = SrcCodeLocationEntry(6, 3); + SrcCodeLocationEntry EntryTwo = SrcCodeLocationEntry(6, 8); + std::set> GroundTruth; + GroundTruth.insert({Entry, EntryTwo}); + compareResults(GroundTruth, "main"); } TEST_F(IFDSTaintAnalysisTest, TaintTest_01_m2r) { initialize({PathToLlFiles + "dummy_source_sink/taint_01_cpp_m2r_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(6, {11}); - std::set GroundTruth = {Entry}; - compareResults(GroundTruth); + SrcCodeLocationEntry Entry(12, 3); + SrcCodeLocationEntry EntryTwo(12, 14); + + std::set> GroundTruth; + GroundTruth.insert({Entry, EntryTwo}); + + compareResults(GroundTruth, "main"); } TEST_F(IFDSTaintAnalysisTest, TaintTest_02) { initialize({PathToLlFiles + "dummy_source_sink/taint_02_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(5, {8}); - std::set GroundTruth = {Entry}; - compareResults(GroundTruth); + SrcCodeLocationEntry Entry(5, 3); + SrcCodeLocationEntry EntryTwo(5, 8); + + std::set> GroundTruth; + GroundTruth.insert({Entry, EntryTwo}); + compareResults(GroundTruth, "main"); } TEST_F(IFDSTaintAnalysisTest, TaintTest_03) { initialize({PathToLlFiles + "dummy_source_sink/taint_03_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(6, {8}); - std::set GroundTruth = {Entry}; - compareResults(GroundTruth); + SrcCodeLocationEntry Entry(6, 3); + SrcCodeLocationEntry EntryTwo(6, 8); + + std::set> GroundTruth; + GroundTruth.insert({Entry, EntryTwo}); + compareResults(GroundTruth, "main"); } TEST_F(IFDSTaintAnalysisTest, TaintTest_04) { initialize({PathToLlFiles + "dummy_source_sink/taint_04_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(6, {8}); - SrcCodeLocationEntry EntryTwo(8, {8}); - std::set GroundTruth = {Entry, EntryTwo}; - compareResults(GroundTruth); + SrcCodeLocationEntry Entry(6, 3); + SrcCodeLocationEntry EntryTwo(6, 8); + SrcCodeLocationEntry EntryThree(8, 3); + SrcCodeLocationEntry EntryFour(8, 8); + + std::set> GroundTruth; + GroundTruth.insert({{Entry, EntryTwo}, {EntryThree, EntryFour}}); + compareResults(GroundTruth, "main"); } TEST_F(IFDSTaintAnalysisTest, TaintTest_05) { initialize({PathToLlFiles + "dummy_source_sink/taint_05_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(6, {8}); - std::set GroundTruth = {Entry}; - compareResults(GroundTruth); + SrcCodeLocationEntry Entry(6, 3); + SrcCodeLocationEntry EntryTwo(6, 8); + + std::set> GroundTruth; + GroundTruth.insert({Entry, EntryTwo}); + compareResults(GroundTruth, "main"); } // TODO: Fabian fragen, wie man mit Ground Truth von "main.0" hier umgehen soll. @@ -222,7 +245,12 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_01) { {PathToLlFiles + "dummy_source_sink/taint_exception_01_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - compareResults({{12, {8}}}); + SrcCodeLocationEntry Entry(12, 3); + SrcCodeLocationEntry EntryTwo(12, 8); + + std::set> GroundTruth; + GroundTruth.insert({Entry, EntryTwo}); + compareResults(GroundTruth, "main"); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_01_m2r) { @@ -230,7 +258,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(); - compareResults({{12, {14}}}); + SrcCodeLocationEntry Entry(12, 3); + SrcCodeLocationEntry EntryTwo(12, 14); + + std::set> GroundTruth; + GroundTruth.insert({Entry, EntryTwo}); + compareResults(GroundTruth, "main"); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_02) { @@ -238,7 +271,12 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_02) { {PathToLlFiles + "dummy_source_sink/taint_exception_02_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - compareResults({{11, {8}}}); + SrcCodeLocationEntry Entry(11, 3); + SrcCodeLocationEntry EntryTwo(11, 8); + + std::set> GroundTruth; + GroundTruth.insert({Entry, EntryTwo}); + compareResults(GroundTruth, "main"); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_03) { @@ -246,11 +284,12 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_03) { {PathToLlFiles + "dummy_source_sink/taint_exception_03_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - // This test weirdly fails, when I just insert {{}, {}} into compareResults. - std::set GroundTruth; - GroundTruth.insert(SrcCodeLocationEntry{11, {8}}); - GroundTruth.insert(SrcCodeLocationEntry{14, {8}}); - compareResults(GroundTruth); + SrcCodeLocationEntry Entry(14, 3); + SrcCodeLocationEntry EntryTwo(14, 8); + + std::set> GroundTruth; + GroundTruth.insert({Entry, EntryTwo}); + compareResults(GroundTruth, "main"); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_04) { @@ -258,7 +297,12 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_04) { {PathToLlFiles + "dummy_source_sink/taint_exception_04_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - compareResults({{16, {8}}}); + SrcCodeLocationEntry Entry(16, 3); + SrcCodeLocationEntry EntryTwo(16, 8); + + std::set> GroundTruth; + GroundTruth.insert({Entry, EntryTwo}); + compareResults(GroundTruth, "main"); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_05) { @@ -266,7 +310,12 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_05) { {PathToLlFiles + "dummy_source_sink/taint_exception_05_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - compareResults({{16, {8}}}); + SrcCodeLocationEntry Entry(16, 3); + SrcCodeLocationEntry EntryTwo(16, 8); + + std::set> GroundTruth; + GroundTruth.insert({Entry, EntryTwo}); + compareResults(GroundTruth, "main"); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_06) { @@ -274,7 +323,12 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_06) { {PathToLlFiles + "dummy_source_sink/taint_exception_06_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - compareResults({{13, {10}}}); + SrcCodeLocationEntry Entry(13, 3); + SrcCodeLocationEntry EntryTwo(13, 8); + + std::set> GroundTruth; + GroundTruth.insert({Entry, EntryTwo}); + compareResults(GroundTruth, "main"); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_07) { @@ -282,7 +336,12 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_07) { {PathToLlFiles + "dummy_source_sink/taint_exception_07_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - compareResults({{14, {10}}}); + SrcCodeLocationEntry Entry(14, 3); + SrcCodeLocationEntry EntryTwo(14, 8); + + std::set> GroundTruth; + GroundTruth.insert({Entry, EntryTwo}); + compareResults(GroundTruth, "main"); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_08) { @@ -290,7 +349,12 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_08) { {PathToLlFiles + "dummy_source_sink/taint_exception_08_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - compareResults({{19, {8}}}); + SrcCodeLocationEntry Entry(19, 3); + SrcCodeLocationEntry EntryTwo(19, 8); + + std::set> GroundTruth; + GroundTruth.insert({Entry, EntryTwo}); + compareResults(GroundTruth, "main"); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_09) { @@ -298,7 +362,12 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_09) { {PathToLlFiles + "dummy_source_sink/taint_exception_09_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - compareResults({{20, {8}}}); + SrcCodeLocationEntry Entry(20, 3); + SrcCodeLocationEntry EntryTwo(20, 8); + + std::set> GroundTruth; + GroundTruth.insert({Entry, EntryTwo}); + compareResults(GroundTruth, "main"); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_10) { @@ -306,7 +375,12 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_10) { {PathToLlFiles + "dummy_source_sink/taint_exception_10_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - compareResults({{19, {10}}}); + SrcCodeLocationEntry Entry(19, 3); + SrcCodeLocationEntry EntryTwo(19, 8); + + std::set> GroundTruth; + GroundTruth.insert({Entry, EntryTwo}); + compareResults(GroundTruth, "main"); } // TODO: fix seg fault diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp index dc8d885842..dd88c9fa14 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp @@ -12,16 +12,18 @@ #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" #include "phasar/Utils/SrcCodeLocationEntry.h" +#include "llvm/IR/Function.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Value.h" +#include "SourceMapping.h" #include "TestConfig.h" #include "gtest/gtest.h" #include #include - -#include +#include using namespace psr; @@ -50,30 +52,23 @@ class IFDSUninitializedVariablesTest : public ::testing::Test { void TearDown() override {} - void compareResults(const std::set &GroundTruth) { - std::set FoundUninitUses; + void compareResults( + const std::set> + &GroundTruth, + const llvm::Function *Func) { + auto GroundTruthEntries = getGroundTruthInsts(GroundTruth, Func); + + std::set> + FoundUninitUses; for (const auto &Kvp : UninitProblem->getAllUndefUses()) { - if (!Kvp.first->getDebugLoc()) { - llvm::outs() << "\ngetDebugLoc() returns nullptr\n\n"; - ASSERT_TRUE(false); - } - u_int32_t InstID = Kvp.first->getDebugLoc().getLine(); - std::set UndefValueIds; + const auto *SourceInst = Kvp.first; + for (const auto *UV : Kvp.second) { - if (const auto *UVInst = - llvm::dyn_cast_or_null(UV)) { - if (UVInst->getDebugLoc()) { - UndefValueIds.insert(UVInst->getDebugLoc().getCol()); - } else { - llvm::outs() << "\ngetDebugLoc().getCol() returns nullptr\n\n"; - ASSERT_TRUE(false); - } - } + FoundUninitUses.insert({SourceInst, UV}); } - FoundUninitUses.insert(SrcCodeLocationEntry(InstID, UndefValueIds)); } - EXPECT_EQ(FoundUninitUses, GroundTruth); + EXPECT_EQ(FoundUninitUses, GroundTruthEntries); } }; // Test Fixture @@ -82,8 +77,8 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_01_SHOULD_NOT_LEAK) { IFDSSolver Solver(*UninitProblem, &HA->getICFG()); Solver.solve(); // all_uninit.cpp does not contain undef-uses - std::set GroundTruth; - compareResults(GroundTruth); + std::set> GroundTruth; + compareResults(GroundTruth, HA->getProjectIRDB().getFunction("main")); } TEST_F(IFDSUninitializedVariablesTest, UninitTest_02_SHOULD_LEAK) { @@ -92,13 +87,12 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_02_SHOULD_LEAK) { Solver.solve(); // binop_uninit uses uninitialized variable i in 'int j = i + 10;' - std::set GroundTruth; + std::set> GroundTruth; // %4 = load i32, i32* %2, ID: 6 ; %2 is the uninitialized variable i - GroundTruth.insert(SrcCodeLocationEntry(2, {0})); // %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.insert(SrcCodeLocationEntry(3, {11})); - compareResults(GroundTruth); + GroundTruth.insert({SrcCodeLocationEntry(2, 0), SrcCodeLocationEntry(3, 11)}); + compareResults(GroundTruth, HA->getICFG().getIRDB()->getFunction("main")); } #if false From 3e57880f698479c696fb7162dc673fda5578efca Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Tue, 15 Jul 2025 11:00:39 +0200 Subject: [PATCH 08/35] Fix psr::getDILocation() --- include/phasar/Utils/SrcCodeLocationEntry.h | 2 +- lib/PhasarLLVM/Utils/LLVMIRToSrc.cpp | 12 ++++++++---- .../Problems/IDEExtendedTaintAnalysisTest.cpp | 7 ++++--- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/include/phasar/Utils/SrcCodeLocationEntry.h b/include/phasar/Utils/SrcCodeLocationEntry.h index 8901b71c94..8f886f6144 100644 --- a/include/phasar/Utils/SrcCodeLocationEntry.h +++ b/include/phasar/Utils/SrcCodeLocationEntry.h @@ -83,7 +83,7 @@ getGroundTruthInsts( return GroundTruthEntries; }; -static std::set +inline std::set getGroundTruthInsts(const std::set &GroundTruth, const llvm::Function *Func) { std::set GroundTruthEntries; diff --git a/lib/PhasarLLVM/Utils/LLVMIRToSrc.cpp b/lib/PhasarLLVM/Utils/LLVMIRToSrc.cpp index ac36114d33..5f308c6c83 100644 --- a/lib/PhasarLLVM/Utils/LLVMIRToSrc.cpp +++ b/lib/PhasarLLVM/Utils/LLVMIRToSrc.cpp @@ -99,15 +99,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/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp index ca0aeaba3d..06a090fb2a 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp @@ -433,8 +433,7 @@ TEST_F(IDETaintAnalysisTest, XTaint20) { HelperAnalyses HA({PathToLLFiles + "xtaint20_cpp_dbg.ll"}, EntryPoints); std::set> GroundTruth; - GroundTruth.insert( - {SrcCodeLocationEntry(12, 3), SrcCodeLocationEntry(12, 11)}); + GroundTruth.insert({SrcCodeLocationEntry(12, 3), SrcCodeLocationEntry(6, 7)}); GroundTruth.insert( {SrcCodeLocationEntry(13, 3), SrcCodeLocationEntry(13, 8)}); @@ -446,7 +445,9 @@ TEST_F(IDETaintAnalysisTest, XTaint21) { std::set> GroundTruth; GroundTruth.insert( - {SrcCodeLocationEntry(17, 3), SrcCodeLocationEntry(17, 8)}); + {SrcCodeLocationEntry(17, 3), SrcCodeLocationEntry(11, 7)}); + GroundTruth.insert( + {SrcCodeLocationEntry(18, 3), SrcCodeLocationEntry(18, 8)}); IDEExtendedTaintAnalysis<>::config_callback_t SourceCB = [](const llvm::Instruction *Inst) { From d878a9ce118adc9b9c6a1832030cfa5f27c496e7 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Tue, 15 Jul 2025 19:27:08 +0200 Subject: [PATCH 09/35] std::variant for SrcCodeLocationEntry --- include/phasar/Utils/SrcCodeLocationEntry.h | 83 ++++---- .../Problems/IDEExtendedTaintAnalysisTest.cpp | 178 ++++++++---------- .../Problems/IDEGeneralizedLCATest.cpp | 35 ++-- .../Problems/IFDSConstAnalysisTest.cpp | 103 +++++----- .../Problems/IFDSTaintAnalysisTest.cpp | 136 +++++++------ .../IFDSUninitializedVariablesTest.cpp | 14 +- 6 files changed, 280 insertions(+), 269 deletions(-) diff --git a/include/phasar/Utils/SrcCodeLocationEntry.h b/include/phasar/Utils/SrcCodeLocationEntry.h index 8f886f6144..1b23700761 100644 --- a/include/phasar/Utils/SrcCodeLocationEntry.h +++ b/include/phasar/Utils/SrcCodeLocationEntry.h @@ -1,8 +1,12 @@ #ifndef PHASAR_UTILS_SRCCODELOCATIONENTRY_H #define PHASAR_UTILS_SRCCODELOCATIONENTRY_H +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Value.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/raw_ostream.h" #include "SourceMapping.h" @@ -10,25 +14,27 @@ #include #include #include +#include namespace psr { struct SrcCodeLocationEntry { - SrcCodeLocationEntry(uint32_t Line, uint32_t Column) - : Line(Line), Column(Column) {} SrcCodeLocationEntry( uint32_t Line, uint32_t Column, + std::variant + Context) + : Line(Line), Column(Column), Context(Context) {} + SrcCodeLocationEntry( + uint32_t Line, uint32_t Column, + std::variant + Context, std::function LambdaFunc) - : Line(Line), Column(Column), UseLambdaFunc(true), - LambdaFunc(std::move(LambdaFunc)) {} + : Line(Line), Column(Column), LambdaFunc(std::move(LambdaFunc)), + Context(Context) {} uint32_t Line = 0; uint32_t Column = 0; - - [[nodiscard]] bool shouldUseLambdaFunc() const { return UseLambdaFunc; } - [[nodiscard]] std::function - getLambdaFunc() const { - return LambdaFunc; - } + std::function LambdaFunc = nullptr; + std::variant Context; bool operator==(const SrcCodeLocationEntry &Other) const { return Line == Other.Line && Column == Other.Column; @@ -36,17 +42,12 @@ struct SrcCodeLocationEntry { bool operator<(const SrcCodeLocationEntry &Other) const { return std::tie(Line, Column) < std::tie(Other.Line, Other.Column); } - -private: - bool UseLambdaFunc = false; - std::function LambdaFunc; }; static std::set> getGroundTruthInsts( const std::set> - &GroundTruth, - const llvm::Function *Func) { + &GroundTruth) { std::set> GroundTruthEntries; @@ -56,21 +57,32 @@ getGroundTruthInsts( const llvm::Instruction *CurrInst = nullptr; const llvm::Value *CurrVal = nullptr; - if (FirstEntry.shouldUseLambdaFunc()) { + if (std::holds_alternative( + FirstEntry.Context)) { + CurrInst = llvm::dyn_cast( + std::get(FirstEntry.Context)); + } else if (FirstEntry.LambdaFunc) { CurrInst = unittest::getInstAtOrNull( - Func, FirstEntry.Line, FirstEntry.Column, FirstEntry.getLambdaFunc()); + std::get(FirstEntry.Context), FirstEntry.Line, + FirstEntry.Column, FirstEntry.LambdaFunc); } else { - CurrInst = - unittest::getInstAtOrNull(Func, FirstEntry.Line, FirstEntry.Column); + CurrInst = unittest::getInstAtOrNull( + std::get(FirstEntry.Context), FirstEntry.Line, + FirstEntry.Column); } - if (SecondEntry.shouldUseLambdaFunc()) { - CurrVal = - unittest::getInstAtOrNull(Func, SecondEntry.Line, SecondEntry.Column, - SecondEntry.getLambdaFunc()); + if (std::holds_alternative( + FirstEntry.Context)) { + CurrVal = llvm::dyn_cast( + std::get(SecondEntry.Context)); + } else if (SecondEntry.LambdaFunc) { + CurrVal = unittest::getInstAtOrNull( + std::get(SecondEntry.Context), + SecondEntry.Line, SecondEntry.Column, SecondEntry.LambdaFunc); } else { - CurrVal = - unittest::getInstAtOrNull(Func, SecondEntry.Line, SecondEntry.Column); + CurrVal = unittest::getInstAtOrNull( + std::get(SecondEntry.Context), + SecondEntry.Line, SecondEntry.Column); } if (CurrInst) { @@ -83,18 +95,23 @@ getGroundTruthInsts( return GroundTruthEntries; }; -inline std::set -getGroundTruthInsts(const std::set &GroundTruth, - const llvm::Function *Func) { +static std::set +getGroundTruthInsts(const std::set &GroundTruth) { std::set GroundTruthEntries; for (const auto &Entry : GroundTruth) { const llvm::Instruction *CurrInst = nullptr; - if (Entry.shouldUseLambdaFunc()) { - CurrInst = unittest::getInstAtOrNull(Func, Entry.Line, Entry.Column, - Entry.getLambdaFunc()); + if (std::holds_alternative(Entry.Context)) { + CurrInst = llvm::dyn_cast( + std::get(Entry.Context)); + } else if (Entry.LambdaFunc) { + CurrInst = unittest::getInstAtOrNull( + std::get(Entry.Context), Entry.Line, + Entry.Column, Entry.LambdaFunc); } else { - CurrInst = unittest::getInstAtOrNull(Func, Entry.Line, Entry.Column); + CurrInst = unittest::getInstAtOrNull( + std::get(Entry.Context), Entry.Line, + Entry.Column); } if (CurrInst) { diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp index 06a090fb2a..2763767656 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp @@ -67,7 +67,7 @@ class IDETaintAnalysisTest : public ::testing::Test { const std::set> &GroundTruth, std::variant Config, - bool DumpResults = true, const llvm::StringRef FuncName = "main") { + bool DumpResults = true) { auto TC = std::visit(Overloaded{[&](std::monostate) { return LLVMTaintConfig(HA.getProjectIRDB()); @@ -98,8 +98,7 @@ class IDETaintAnalysisTest : public ::testing::Test { TaintProblem.emitTextReport(Solver.getSolverResults()); - compareResults(TaintProblem, Solver, GroundTruth, - HA.getProjectIRDB().getFunction(FuncName)); + compareResults(TaintProblem, Solver, GroundTruth); } void SetUp() override { ValueAnnotationPass::resetValueID(); } @@ -110,33 +109,8 @@ class IDETaintAnalysisTest : public ::testing::Test { IDEExtendedTaintAnalysis<> &TaintProblem, IDESolver_P> &Solver, const std::set> - &GroundTruth, - const llvm::Function *Func) { - auto GroundTruthEntries = getGroundTruthInsts(GroundTruth, Func); - - // Debug stuff - uint32_t Line = 12; - std::set TestSet; - for (uint32_t Col = 0; Col < 30; Col++) { - SrcCodeLocationEntry Curr = {Line, Col}; - TestSet.insert(Curr); - } - llvm::outs() << "TestSet Size: " << TestSet.size() << "\n"; - - int Counter = 0; - - auto TestInsts = getGroundTruthInsts(TestSet, Func); - llvm::outs() << "Line: " << Line << "\n"; - llvm::outs() << "TestInsts Size: " << TestInsts.size() << "\n"; - for (const auto *Elem : TestInsts) { - if (Elem) { - llvm::outs() << Counter << ": " << *Elem << " \n"; - } else { - llvm::outs() << Counter << ": Was nullptr \n"; - } - Counter++; - } - // Debug stuff + &GroundTruth) { + auto GroundTruthEntries = getGroundTruthInsts(GroundTruth); std::set> FoundLeaks; @@ -151,22 +125,6 @@ class IDETaintAnalysisTest : public ::testing::Test { } EXPECT_EQ(FoundLeaks, GroundTruthEntries); - - llvm::outs() << "-----------------GroundTruth----------------:\n"; - for (const auto &Leak : GroundTruthEntries) { - llvm::outs() << "std::get<0>:\n"; - llvm::outs() << *(std::get<0>(Leak)) << "\n"; - llvm::outs() << "std::get<1>:\n"; - llvm::outs() << *(std::get<1>(Leak)) << "\n"; - } - llvm::outs() << "------------------FoundLeaks----------------:\n"; - for (const auto &Leak : FoundLeaks) { - llvm::outs() << "std::get<0>:\n"; - llvm::outs() << *(std::get<0>(Leak)) << "\n"; - llvm::outs() << "std::get<1>:\n"; - llvm::outs() << *(std::get<1>(Leak)) << "\n"; - } - llvm::outs() << "--------------------------------------------:\n"; } }; // Test Fixture @@ -188,7 +146,8 @@ TEST_F(IDETaintAnalysisTest, XTaint01_Json) { Config.Functions.push_back(std::move(FuncDataMain)); Config.Functions.push_back(std::move(FuncDataPrint)); - GroundTruth.insert({{8, 3}, {8, 9}}); + // TODO: completely rework this test? + // GroundTruth.insert({{8, 3}, {8, 9}}); doAnalysis(HA, GroundTruth, &Config); } @@ -197,7 +156,8 @@ TEST_F(IDETaintAnalysisTest, XTaint01) { HelperAnalyses HA({PathToLLFiles + "xtaint01_cpp_dbg.ll"}, EntryPoints); std::set> GroundTruth; - GroundTruth.insert({{8, 3}, {8, 9}}); + GroundTruth.insert({{8, 3, HA.getProjectIRDB().getFunction("main")}, + {8, 9, HA.getProjectIRDB().getFunction("main")}}); doAnalysis(HA, GroundTruth, std::monostate{}); } @@ -206,11 +166,13 @@ TEST_F(IDETaintAnalysisTest, XTaint02) { HelperAnalyses HA({PathToLLFiles + "xtaint02_cpp_dbg.ll"}, EntryPoints); std::set> GroundTruth; - SrcCodeLocationEntry Call = SrcCodeLocationEntry(9, 3); + SrcCodeLocationEntry Call = + SrcCodeLocationEntry(9, 3, HA.getProjectIRDB().getFunction("main")); SrcCodeLocationEntry Leak = - SrcCodeLocationEntry(9, 9, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); + SrcCodeLocationEntry(9, 9, HA.getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); GroundTruth.insert({Call, Leak}); @@ -221,11 +183,13 @@ TEST_F(IDETaintAnalysisTest, XTaint03) { HelperAnalyses HA({PathToLLFiles + "xtaint03_cpp_dbg.ll"}, EntryPoints); std::set> GroundTruth; - SrcCodeLocationEntry Call = SrcCodeLocationEntry(10, 3); + SrcCodeLocationEntry Call = + SrcCodeLocationEntry(10, 3, HA.getProjectIRDB().getFunction("main")); SrcCodeLocationEntry Leak = - SrcCodeLocationEntry(10, 9, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); + SrcCodeLocationEntry(10, 9, HA.getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); GroundTruth.insert({Call, Leak}); @@ -236,21 +200,23 @@ TEST_F(IDETaintAnalysisTest, XTaint04) { HelperAnalyses HA({PathToLLFiles + "xtaint04_cpp_dbg.ll"}, EntryPoints); std::set> GroundTruth; - SrcCodeLocationEntry Call = SrcCodeLocationEntry(6, 3); + SrcCodeLocationEntry Call = + SrcCodeLocationEntry(6, 3, HA.getProjectIRDB().getFunction("main")); - // TODO: this counter stuff is not good, but I haven't found a better way to - // implement this yet + // TODO: the counter implementation isn't great, as it still relies on IR + // behaviour that might change based on operating system or other factors. A + // better implementation would be good here. int Counter = 0; - SrcCodeLocationEntry Leak = SrcCodeLocationEntry( - 6, 9, [Counter](const llvm::Instruction *Inst) mutable { - llvm::outs() << "Inst: " << *Inst << "\n"; - Counter++; - return Counter == 3; - }); + SrcCodeLocationEntry Leak = + SrcCodeLocationEntry(6, 9, HA.getProjectIRDB().getFunction("_Z3barPi"), + [Counter](const llvm::Instruction *Inst) mutable { + Counter++; + return Counter == 3; + }); GroundTruth.insert({Call, Leak}); - doAnalysis(HA, GroundTruth, std::monostate{}, true, "_Z3barPi"); + doAnalysis(HA, GroundTruth, std::monostate{}, true); } // XTaint05 is similar to 06, but even harder @@ -271,11 +237,13 @@ TEST_F(IDETaintAnalysisTest, DISABLED_XTaint07) { HelperAnalyses HA({PathToLLFiles + "xtaint07_cpp_dbg.ll"}, EntryPoints); std::set> GroundTruth; - SrcCodeLocationEntry Call = SrcCodeLocationEntry(10, 0); + SrcCodeLocationEntry Call = + SrcCodeLocationEntry(10, 0, HA.getProjectIRDB().getFunction("main")); SrcCodeLocationEntry Leak = - SrcCodeLocationEntry(10, 18, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); + SrcCodeLocationEntry(10, 18, HA.getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); GroundTruth.insert({Call, Leak}); doAnalysis(HA, GroundTruth, std::monostate{}, true); @@ -285,11 +253,13 @@ TEST_F(IDETaintAnalysisTest, DISABLED_XTaint08) { HelperAnalyses HA({PathToLLFiles + "xtaint08_cpp_dbg.ll"}, EntryPoints); std::set> GroundTruth; - SrcCodeLocationEntry Call = SrcCodeLocationEntry(20, 0); + SrcCodeLocationEntry Call = + SrcCodeLocationEntry(20, 0, HA.getProjectIRDB().getFunction("main")); SrcCodeLocationEntry Leak = - SrcCodeLocationEntry(20, 18, [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); + SrcCodeLocationEntry(20, 18, HA.getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); GroundTruth.insert({Call, Leak}); doAnalysis(HA, GroundTruth, std::monostate{}, true); @@ -299,8 +269,10 @@ TEST_F(IDETaintAnalysisTest, XTaint09_1) { HelperAnalyses HA({PathToLLFiles + "xtaint09_1_cpp_dbg.ll"}, EntryPoints); std::set> GroundTruth; - SrcCodeLocationEntry Call = SrcCodeLocationEntry(14, 3); - SrcCodeLocationEntry Leak = SrcCodeLocationEntry(14, 8); + SrcCodeLocationEntry Call = + SrcCodeLocationEntry(14, 3, HA.getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry Leak = + SrcCodeLocationEntry(14, 8, HA.getProjectIRDB().getFunction("main")); GroundTruth.insert({Call, Leak}); doAnalysis(HA, GroundTruth, std::monostate{}, true); @@ -310,16 +282,18 @@ TEST_F(IDETaintAnalysisTest, XTaint09) { HelperAnalyses HA({PathToLLFiles + "xtaint09_cpp_dbg.ll"}, EntryPoints); std::set> GroundTruth; - SrcCodeLocationEntry Call = SrcCodeLocationEntry(16, 3); - // TODO: this counter stuff is not good, but I haven't found a better way to - // implement this yet + SrcCodeLocationEntry Call = + SrcCodeLocationEntry(16, 3, HA.getProjectIRDB().getFunction("main")); + // TODO: the counter implementation isn't great, as it still relies on IR + // behaviour that might change based on operating system or other factors. A + // better implementation would be good here. int Counter = 0; - SrcCodeLocationEntry Leak = SrcCodeLocationEntry( - 16, 8, [Counter](const llvm::Instruction *Inst) mutable { - llvm::outs() << "Inst: " << *Inst << "\n"; - Counter++; - return Counter == 2; - }); + SrcCodeLocationEntry Leak = + SrcCodeLocationEntry(16, 8, HA.getProjectIRDB().getFunction("main"), + [Counter](const llvm::Instruction *Inst) mutable { + Counter++; + return Counter == 2; + }); GroundTruth.insert({Call, Leak}); doAnalysis(HA, GroundTruth, std::monostate{}, true); @@ -348,7 +322,8 @@ TEST_F(IDETaintAnalysisTest, XTaint12) { std::set> GroundTruth; GroundTruth.insert( - {SrcCodeLocationEntry(19, 3), SrcCodeLocationEntry(19, 8)}); + {SrcCodeLocationEntry(19, 3, HA.getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(19, 8, HA.getProjectIRDB().getFunction("main"))}); doAnalysis(HA, GroundTruth, std::monostate{}, true); } @@ -358,7 +333,8 @@ TEST_F(IDETaintAnalysisTest, XTaint13) { std::set> GroundTruth; GroundTruth.insert( - {SrcCodeLocationEntry(17, 3), SrcCodeLocationEntry(17, 8)}); + {SrcCodeLocationEntry(17, 3, HA.getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(17, 8, HA.getProjectIRDB().getFunction("main"))}); doAnalysis(HA, GroundTruth, std::monostate{}, true); } @@ -368,7 +344,8 @@ TEST_F(IDETaintAnalysisTest, XTaint14) { HelperAnalyses HA({PathToLLFiles + "xtaint14_cpp_dbg.ll"}, EntryPoints); GroundTruth.insert( - {SrcCodeLocationEntry(24, 3), SrcCodeLocationEntry(24, 8)}); + {SrcCodeLocationEntry(24, 3, HA.getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(24, 8, HA.getProjectIRDB().getFunction("main"))}); doAnalysis(HA, GroundTruth, std::monostate{}, true); } @@ -389,7 +366,8 @@ TEST_F(IDETaintAnalysisTest, XTaint16) { std::set> GroundTruth; GroundTruth.insert( - {SrcCodeLocationEntry(13, 3), SrcCodeLocationEntry(13, 8)}); + {SrcCodeLocationEntry(13, 3, HA.getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(13, 8, HA.getProjectIRDB().getFunction("main"))}); doAnalysis(HA, GroundTruth, std::monostate{}, true); } @@ -399,7 +377,8 @@ TEST_F(IDETaintAnalysisTest, XTaint17) { std::set> GroundTruth; GroundTruth.insert( - {SrcCodeLocationEntry(17, 3), SrcCodeLocationEntry(17, 8)}); + {SrcCodeLocationEntry(17, 3, HA.getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(17, 8, HA.getProjectIRDB().getFunction("main"))}); doAnalysis(HA, GroundTruth, std::monostate{}, true); } @@ -411,7 +390,8 @@ TEST_F(IDETaintAnalysisTest, XTaint18) { // TODO: ask Fabian why there are no leaks found for this test // I added a random GT, so that the test fails and it won't be overlooked. GroundTruth.insert( - {SrcCodeLocationEntry(8, 10), SrcCodeLocationEntry(8, 14)}); + {SrcCodeLocationEntry(8, 10, HA.getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(8, 14, HA.getProjectIRDB().getFunction("main"))}); doAnalysis(HA, GroundTruth, std::monostate{}, true); } @@ -424,7 +404,8 @@ PHASAR_SKIP_TEST(TEST_F(IDETaintAnalysisTest, XTaint19) { std::set> GroundTruth; GroundTruth.insert( - {SrcCodeLocationEntry(17, 3), SrcCodeLocationEntry(17, 8)}); + {SrcCodeLocationEntry(17, 3, HA.getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(17, 8, HA.getProjectIRDB().getFunction("main"))}); doAnalysis(HA, GroundTruth, std::monostate{}, true); }) @@ -433,9 +414,12 @@ TEST_F(IDETaintAnalysisTest, XTaint20) { HelperAnalyses HA({PathToLLFiles + "xtaint20_cpp_dbg.ll"}, EntryPoints); std::set> GroundTruth; - GroundTruth.insert({SrcCodeLocationEntry(12, 3), SrcCodeLocationEntry(6, 7)}); GroundTruth.insert( - {SrcCodeLocationEntry(13, 3), SrcCodeLocationEntry(13, 8)}); + {SrcCodeLocationEntry(12, 3, HA.getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(6, 7, HA.getProjectIRDB().getFunction("main"))}); + GroundTruth.insert( + {SrcCodeLocationEntry(13, 3, HA.getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(13, 8, HA.getProjectIRDB().getFunction("main"))}); doAnalysis(HA, GroundTruth, std::monostate{}, true); } @@ -445,9 +429,11 @@ TEST_F(IDETaintAnalysisTest, XTaint21) { std::set> GroundTruth; GroundTruth.insert( - {SrcCodeLocationEntry(17, 3), SrcCodeLocationEntry(11, 7)}); + {SrcCodeLocationEntry(17, 3, HA.getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(11, 7, HA.getProjectIRDB().getFunction("main"))}); GroundTruth.insert( - {SrcCodeLocationEntry(18, 3), SrcCodeLocationEntry(18, 8)}); + {SrcCodeLocationEntry(18, 3, HA.getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(18, 8, HA.getProjectIRDB().getFunction("main"))}); IDEExtendedTaintAnalysis<>::config_callback_t SourceCB = [](const llvm::Instruction *Inst) { diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp index 23522e9edb..4f30b2c339 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp @@ -21,6 +21,7 @@ #include "phasar/Utils/Logger.h" #include "phasar/Utils/SrcCodeLocationEntry.h" +#include "llvm/IR/Function.h" #include "llvm/Support/raw_ostream.h" #include "SourceMapping.h" @@ -69,19 +70,15 @@ class IDEGeneralizedLCATest : public ::testing::Test { // compare results /// \brief compares the computed results with every given tuple (value, /// alloca, inst) - void compareResults(const std::vector &Expected, - const std::vector &EVal, - const llvm::StringRef FuncName) { - const auto *Func = HA->getProjectIRDB().getFunction(FuncName); - - if (!Func) { - llvm::outs() << "Func is nullptr, wasn't found!!!\n"; - ASSERT_NE(nullptr, Func); - } - + void compareResults(const std::set &Expected, + const std::vector &EVal) { for (const auto &Entry : Expected) { - const auto *Vr = unittest::getInstAtOrNull(Func, 5, 3); - const auto *Inst = unittest::getInstAtOrNull(Func, 6, 3); + const auto *Vr = unittest::getInstAtOrNull( + std::get(Entry.Context), Entry.Line, + Entry.Column); + const auto *Inst = unittest::getInstAtOrNull( + std::get(Entry.Context), Entry.Line, + Entry.Column); bool Flag = false; @@ -130,21 +127,19 @@ class IDEGeneralizedLCATest : public ::testing::Test { TEST_F(IDEGeneralizedLCATest, SimpleTest) { initialize("SimpleTest_c.ll"); - std::vector GroundTruth; + std::set GroundTruth; // Old ground truth // GroundTruth.push_back({{EdgeValue(10)}, 3, 20}); // GroundTruth.push_back({{EdgeValue(15)}, 4, 20}); - /* - TODO: No column values work?! - */ - // New ground truth based on src file - GroundTruth.push_back(SrcCodeLocationEntry(5, {3})); - GroundTruth.push_back(SrcCodeLocationEntry(6, {3})); + GroundTruth.insert( + SrcCodeLocationEntry(5, 3, HA->getProjectIRDB().getFunction("main"))); + GroundTruth.insert( + SrcCodeLocationEntry(6, 3, HA->getProjectIRDB().getFunction("main"))); std::vector EVs = {EdgeValue(10), EdgeValue(15)}; - compareResults(GroundTruth, EVs, "main"); + compareResults(GroundTruth, EVs); } #if false diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp index 423dcae64d..ab29ecc820 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp @@ -65,26 +65,10 @@ class IFDSConstAnalysisTest : public ::testing::Test { } void compareResults(const std::set &GroundTruth, - IFDSSolver_P &Solver, - const llvm::Function *Func) { - /* --- Debug --- */ - std::set Test; - uint32_t Line = 3; - for (uint32_t Column = 0; Column < 30; Column++) { - Test.insert({Line, Column}); - } - llvm::outs() << "Line: " << Line << "\n"; - llvm::outs() << "Test size: " << Test.size() << "\n"; - auto TestInsts = getGroundTruthInsts(Test, Func); - for (const auto *Entry : TestInsts) { - llvm::outs() << "Test *Entry: " << *Entry << "\n"; - } - /* --- Debug --- */ - - auto GroundTruthEntriesAsInsts = getGroundTruthInsts(GroundTruth, Func); + IFDSSolver_P &Solver) { + auto GroundTruthEntriesAsInsts = getGroundTruthInsts(GroundTruth); std::set GroundTruthEntries; for (const auto *Entry : GroundTruthEntriesAsInsts) { - llvm::outs() << "GT *Entry: " << *Entry << "\n"; if (const auto *EntryVal = llvm::dyn_cast_or_null(Entry)) { GroundTruthEntries.insert(EntryVal); continue; @@ -104,7 +88,7 @@ class IFDSConstAnalysisTest : public ::testing::Test { if (isAllocaInstOrHeapAllocaFunction(Fact) || (llvm::isa(Fact) && !Constproblem->isZeroValue(Fact))) { - llvm::outs() << "Fact: " << *Fact << "\n"; + llvm::outs() << "Found *Fact: " << *Fact << "\n"; AllMutableAllocas.insert(Fact); } } @@ -120,41 +104,35 @@ TEST_F(IFDSConstAnalysisTest, HandleBasicTest_01) { IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); std::set GroundTruth; - compareResults(GroundTruth, Llvmconstsolver, - HA->getProjectIRDB().getFunction("main")); + HA->getProjectIRDB().getModule()->getGlobalList(); + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, HandleBasicTest_02) { initialize({PathToLlFiles + "basic/basic_02_cpp_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - SrcCodeLocationEntry Entry(3, 0); - std::set GroundTruth; - GroundTruth.insert(Entry); - compareResults(GroundTruth, Llvmconstsolver, - HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry Entry(3, 0, HA->getProjectIRDB().getFunction("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(); - SrcCodeLocationEntry Entry(3, 0); - std::set GroundTruth; - GroundTruth.insert(Entry); - compareResults(GroundTruth, Llvmconstsolver, - HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry Entry(3, 0, HA->getProjectIRDB().getFunction("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(); - SrcCodeLocationEntry Entry(3, 0); - std::set GroundTruth; - GroundTruth.insert(Entry); - compareResults(GroundTruth, Llvmconstsolver, - HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry Entry(3, 0, HA->getProjectIRDB().getFunction("main")); + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } /* ============== CONTROL FLOW TESTS ============== */ @@ -162,41 +140,44 @@ TEST_F(IFDSConstAnalysisTest, HandleCFForTest_01) { initialize({PathToLlFiles + "control_flow/cf_for_01_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - SrcCodeLocationEntry Entry(3, 12); - std::set GroundTruth; - GroundTruth.insert(Entry); - compareResults(GroundTruth, Llvmconstsolver, - HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry Entry(3, 12, HA->getProjectIRDB().getFunction("main")); + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } -#if false - 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); + SrcCodeLocationEntry Entry(4, 12, HA->getProjectIRDB().getFunction("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); + SrcCodeLocationEntry Entry(4, 12, HA->getProjectIRDB().getFunction("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); + SrcCodeLocationEntry Entry(5, 12, HA->getProjectIRDB().getFunction("main")); + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } /* ============== POINTER TESTS ============== */ @@ -204,14 +185,18 @@ TEST_F(IFDSConstAnalysisTest, HandlePointerTest_01) { initialize({PathToLlFiles + "pointer/pointer_01_cpp_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - compareResults({1}, Llvmconstsolver); + SrcCodeLocationEntry Entry(3, 0, HA->getProjectIRDB().getFunction("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); + SrcCodeLocationEntry Entry(3, 0, HA->getProjectIRDB().getFunction("main")); + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, DISABLED_HandlePointerTest_03) { @@ -220,14 +205,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); + SrcCodeLocationEntry Entry(4, 0, HA->getProjectIRDB().getFunction("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); + SrcCodeLocationEntry Entry(5, 7, HA->getProjectIRDB().getFunction("main")); + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } /* ============== GLOBAL TESTS ============== */ @@ -235,9 +224,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); + for (const auto &Global : HA->getProjectIRDB().getModule()->getGlobalList()) { + llvm::outs() << "Global.getName(): " << Global.getName() << "\n"; + } + SrcCodeLocationEntry Entry( + 1, 0, HA->getProjectIRDB().getGlobalVariableDefinition("g1")); + std::set GroundTruth{Entry}; + + compareResults(GroundTruth, Llvmconstsolver); } +#if false + + TEST_F(IFDSConstAnalysisTest, HandleGlobalTest_02) { initialize({PathToLlFiles + "global/global_02_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp index b6954283dd..620752c1eb 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp @@ -104,8 +104,7 @@ class IFDSTaintAnalysisTest : public ::testing::Test { TaintSolver.dumpResults(); - compare(TaintProblem.Leaks, GroundTruth, - HA.getProjectIRDB().getFunction(FuncName)); + compare(TaintProblem.Leaks, GroundTruth); } static void doAnalysis( @@ -120,9 +119,8 @@ class IFDSTaintAnalysisTest : public ::testing::Test { static void compare(const LeaksTy &Leaks, const std::set> - &GroundTruth, - const llvm::Function *Func) { - auto GroundTruthEntries = getGroundTruthInsts(GroundTruth, Func); + &GroundTruth) { + auto GroundTruthEntries = getGroundTruthInsts(GroundTruth); std::set> FoundLeaks; @@ -145,10 +143,8 @@ class IFDSTaintAnalysisTest : public ::testing::Test { void compareResults( const std::set> - &GroundTruth, - const llvm::StringRef FuncName) noexcept { - compare(TaintProblem->Leaks, GroundTruth, - HA->getProjectIRDB().getFunction(FuncName)); + &GroundTruth) noexcept { + compare(TaintProblem->Leaks, GroundTruth); } }; // Test Fixture @@ -156,74 +152,79 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_01) { initialize({PathToLlFiles + "dummy_source_sink/taint_01_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry = SrcCodeLocationEntry(6, 3); - SrcCodeLocationEntry EntryTwo = SrcCodeLocationEntry(6, 8); + SrcCodeLocationEntry Entry = + SrcCodeLocationEntry(6, 3, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo = + SrcCodeLocationEntry(6, 8, HA->getProjectIRDB().getFunction("main")); std::set> GroundTruth; GroundTruth.insert({Entry, EntryTwo}); - compareResults(GroundTruth, "main"); + compareResults(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(); - SrcCodeLocationEntry Entry(12, 3); - SrcCodeLocationEntry EntryTwo(12, 14); + SrcCodeLocationEntry Entry(12, 3, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(12, 14, + HA->getProjectIRDB().getFunction("main")); std::set> GroundTruth; GroundTruth.insert({Entry, EntryTwo}); - compareResults(GroundTruth, "main"); + compareResults(GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_02) { initialize({PathToLlFiles + "dummy_source_sink/taint_02_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(5, 3); - SrcCodeLocationEntry EntryTwo(5, 8); + SrcCodeLocationEntry Entry(5, 3, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(5, 8, HA->getProjectIRDB().getFunction("main")); std::set> GroundTruth; GroundTruth.insert({Entry, EntryTwo}); - compareResults(GroundTruth, "main"); + compareResults(GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_03) { initialize({PathToLlFiles + "dummy_source_sink/taint_03_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(6, 3); - SrcCodeLocationEntry EntryTwo(6, 8); + SrcCodeLocationEntry Entry(6, 3, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(6, 8, HA->getProjectIRDB().getFunction("main")); std::set> GroundTruth; GroundTruth.insert({Entry, EntryTwo}); - compareResults(GroundTruth, "main"); + compareResults(GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_04) { initialize({PathToLlFiles + "dummy_source_sink/taint_04_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(6, 3); - SrcCodeLocationEntry EntryTwo(6, 8); - SrcCodeLocationEntry EntryThree(8, 3); - SrcCodeLocationEntry EntryFour(8, 8); + SrcCodeLocationEntry Entry(6, 3, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(6, 8, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryThree(8, 3, + HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryFour(8, 8, + HA->getProjectIRDB().getFunction("main")); std::set> GroundTruth; GroundTruth.insert({{Entry, EntryTwo}, {EntryThree, EntryFour}}); - compareResults(GroundTruth, "main"); + compareResults(GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_05) { initialize({PathToLlFiles + "dummy_source_sink/taint_05_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(6, 3); - SrcCodeLocationEntry EntryTwo(6, 8); + SrcCodeLocationEntry Entry(6, 3, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(6, 8, HA->getProjectIRDB().getFunction("main")); std::set> GroundTruth; GroundTruth.insert({Entry, EntryTwo}); - compareResults(GroundTruth, "main"); + compareResults(GroundTruth); } // TODO: Fabian fragen, wie man mit Ground Truth von "main.0" hier umgehen soll. @@ -245,12 +246,13 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_01) { {PathToLlFiles + "dummy_source_sink/taint_exception_01_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(12, 3); - SrcCodeLocationEntry EntryTwo(12, 8); + SrcCodeLocationEntry Entry(12, 3, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(12, 8, + HA->getProjectIRDB().getFunction("main")); std::set> GroundTruth; GroundTruth.insert({Entry, EntryTwo}); - compareResults(GroundTruth, "main"); + compareResults(GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_01_m2r) { @@ -258,12 +260,13 @@ 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(); - SrcCodeLocationEntry Entry(12, 3); - SrcCodeLocationEntry EntryTwo(12, 14); + SrcCodeLocationEntry Entry(12, 3, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(12, 14, + HA->getProjectIRDB().getFunction("main")); std::set> GroundTruth; GroundTruth.insert({Entry, EntryTwo}); - compareResults(GroundTruth, "main"); + compareResults(GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_02) { @@ -271,12 +274,13 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_02) { {PathToLlFiles + "dummy_source_sink/taint_exception_02_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(11, 3); - SrcCodeLocationEntry EntryTwo(11, 8); + SrcCodeLocationEntry Entry(11, 3, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(11, 8, + HA->getProjectIRDB().getFunction("main")); std::set> GroundTruth; GroundTruth.insert({Entry, EntryTwo}); - compareResults(GroundTruth, "main"); + compareResults(GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_03) { @@ -284,12 +288,13 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_03) { {PathToLlFiles + "dummy_source_sink/taint_exception_03_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(14, 3); - SrcCodeLocationEntry EntryTwo(14, 8); + SrcCodeLocationEntry Entry(14, 3, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(14, 8, + HA->getProjectIRDB().getFunction("main")); std::set> GroundTruth; GroundTruth.insert({Entry, EntryTwo}); - compareResults(GroundTruth, "main"); + compareResults(GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_04) { @@ -297,12 +302,13 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_04) { {PathToLlFiles + "dummy_source_sink/taint_exception_04_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(16, 3); - SrcCodeLocationEntry EntryTwo(16, 8); + SrcCodeLocationEntry Entry(16, 3, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(16, 8, + HA->getProjectIRDB().getFunction("main")); std::set> GroundTruth; GroundTruth.insert({Entry, EntryTwo}); - compareResults(GroundTruth, "main"); + compareResults(GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_05) { @@ -310,12 +316,13 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_05) { {PathToLlFiles + "dummy_source_sink/taint_exception_05_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(16, 3); - SrcCodeLocationEntry EntryTwo(16, 8); + SrcCodeLocationEntry Entry(16, 3, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(16, 8, + HA->getProjectIRDB().getFunction("main")); std::set> GroundTruth; GroundTruth.insert({Entry, EntryTwo}); - compareResults(GroundTruth, "main"); + compareResults(GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_06) { @@ -323,12 +330,13 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_06) { {PathToLlFiles + "dummy_source_sink/taint_exception_06_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(13, 3); - SrcCodeLocationEntry EntryTwo(13, 8); + SrcCodeLocationEntry Entry(13, 3, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(13, 8, + HA->getProjectIRDB().getFunction("main")); std::set> GroundTruth; GroundTruth.insert({Entry, EntryTwo}); - compareResults(GroundTruth, "main"); + compareResults(GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_07) { @@ -336,12 +344,13 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_07) { {PathToLlFiles + "dummy_source_sink/taint_exception_07_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(14, 3); - SrcCodeLocationEntry EntryTwo(14, 8); + SrcCodeLocationEntry Entry(14, 3, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(14, 8, + HA->getProjectIRDB().getFunction("main")); std::set> GroundTruth; GroundTruth.insert({Entry, EntryTwo}); - compareResults(GroundTruth, "main"); + compareResults(GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_08) { @@ -349,12 +358,13 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_08) { {PathToLlFiles + "dummy_source_sink/taint_exception_08_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(19, 3); - SrcCodeLocationEntry EntryTwo(19, 8); + SrcCodeLocationEntry Entry(19, 3, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(19, 8, + HA->getProjectIRDB().getFunction("main")); std::set> GroundTruth; GroundTruth.insert({Entry, EntryTwo}); - compareResults(GroundTruth, "main"); + compareResults(GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_09) { @@ -362,12 +372,13 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_09) { {PathToLlFiles + "dummy_source_sink/taint_exception_09_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(20, 3); - SrcCodeLocationEntry EntryTwo(20, 8); + SrcCodeLocationEntry Entry(20, 3, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(20, 8, + HA->getProjectIRDB().getFunction("main")); std::set> GroundTruth; GroundTruth.insert({Entry, EntryTwo}); - compareResults(GroundTruth, "main"); + compareResults(GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_10) { @@ -375,12 +386,13 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_10) { {PathToLlFiles + "dummy_source_sink/taint_exception_10_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(19, 3); - SrcCodeLocationEntry EntryTwo(19, 8); + SrcCodeLocationEntry Entry(19, 3, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(19, 8, + HA->getProjectIRDB().getFunction("main")); std::set> GroundTruth; GroundTruth.insert({Entry, EntryTwo}); - compareResults(GroundTruth, "main"); + compareResults(GroundTruth); } // TODO: fix seg fault diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp index dd88c9fa14..839dbc7c11 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp @@ -54,9 +54,8 @@ class IFDSUninitializedVariablesTest : public ::testing::Test { void compareResults( const std::set> - &GroundTruth, - const llvm::Function *Func) { - auto GroundTruthEntries = getGroundTruthInsts(GroundTruth, Func); + &GroundTruth) { + auto GroundTruthEntries = getGroundTruthInsts(GroundTruth); std::set> FoundUninitUses; @@ -78,7 +77,7 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_01_SHOULD_NOT_LEAK) { Solver.solve(); // all_uninit.cpp does not contain undef-uses std::set> GroundTruth; - compareResults(GroundTruth, HA->getProjectIRDB().getFunction("main")); + compareResults(GroundTruth); } TEST_F(IFDSUninitializedVariablesTest, UninitTest_02_SHOULD_LEAK) { @@ -91,8 +90,11 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_02_SHOULD_LEAK) { // %4 = load i32, i32* %2, ID: 6 ; %2 is the uninitialized variable i // %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.insert({SrcCodeLocationEntry(2, 0), SrcCodeLocationEntry(3, 11)}); - compareResults(GroundTruth, HA->getICFG().getIRDB()->getFunction("main")); + GroundTruth.insert( + {SrcCodeLocationEntry(2, 0, HA->getICFG().getIRDB()->getFunction("main")), + SrcCodeLocationEntry(3, 11, + HA->getICFG().getIRDB()->getFunction("main"))}); + compareResults(GroundTruth); } #if false From b976e87e44f4e6d5df54ede46f34a8b36b098b2a Mon Sep 17 00:00:00 2001 From: mxHuber Date: Wed, 16 Jul 2025 20:43:45 +0200 Subject: [PATCH 10/35] bug fixed + ext taint test works --- include/phasar/Utils/SrcCodeLocationEntry.h | 132 +++++++++++++----- .../Problems/IDEExtendedTaintAnalysisTest.cpp | 24 +++- .../Problems/IFDSConstAnalysisTest.cpp | 83 +++++++---- 3 files changed, 172 insertions(+), 67 deletions(-) diff --git a/include/phasar/Utils/SrcCodeLocationEntry.h b/include/phasar/Utils/SrcCodeLocationEntry.h index 1b23700761..1eff7bf535 100644 --- a/include/phasar/Utils/SrcCodeLocationEntry.h +++ b/include/phasar/Utils/SrcCodeLocationEntry.h @@ -6,6 +6,7 @@ #include "llvm/IR/Instruction.h" #include "llvm/IR/Value.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" #include "SourceMapping.h" @@ -57,32 +58,43 @@ getGroundTruthInsts( const llvm::Instruction *CurrInst = nullptr; const llvm::Value *CurrVal = nullptr; - if (std::holds_alternative( - FirstEntry.Context)) { - CurrInst = llvm::dyn_cast( - std::get(FirstEntry.Context)); - } else if (FirstEntry.LambdaFunc) { - CurrInst = unittest::getInstAtOrNull( - std::get(FirstEntry.Context), FirstEntry.Line, - FirstEntry.Column, FirstEntry.LambdaFunc); + if (std::get_if(&FirstEntry.Context)) { + llvm::report_fatal_error("Cannot cast global variable to Instruction\n"); + } else if (const auto *Func = + std::get_if(&FirstEntry.Context)) { + if (FirstEntry.LambdaFunc) { + CurrInst = unittest::getInstAtOrNull( + *Func, FirstEntry.Line, FirstEntry.Column, FirstEntry.LambdaFunc); + } else { + CurrInst = unittest::getInstAtOrNull(*Func, FirstEntry.Line, + FirstEntry.Column); + } } else { - CurrInst = unittest::getInstAtOrNull( - std::get(FirstEntry.Context), FirstEntry.Line, - FirstEntry.Column); + llvm::report_fatal_error("Unknown variant type.\n"); } - if (std::holds_alternative( - FirstEntry.Context)) { - CurrVal = llvm::dyn_cast( - std::get(SecondEntry.Context)); - } else if (SecondEntry.LambdaFunc) { - CurrVal = unittest::getInstAtOrNull( - std::get(SecondEntry.Context), - SecondEntry.Line, SecondEntry.Column, SecondEntry.LambdaFunc); + if (const auto *GlobalVar = + std::get_if(&SecondEntry.Context)) { + CurrVal = llvm::cast(*GlobalVar); + } else if (const auto *Func = + std::get_if(&FirstEntry.Context)) { + const llvm::Instruction *AsInst = nullptr; + if (SecondEntry.LambdaFunc) { + AsInst = unittest::getInstAtOrNull(*Func, SecondEntry.Line, + SecondEntry.Column, + SecondEntry.LambdaFunc); + } else { + AsInst = unittest::getInstAtOrNull(*Func, SecondEntry.Line, + SecondEntry.Column); + } + if (const auto *CanBeCastToValue = + llvm::dyn_cast_or_null(AsInst)) { + CurrVal = CanBeCastToValue; + } else { + llvm::errs() << "AsInst Instruction couldn't be cast to value.\n"; + } } else { - CurrVal = unittest::getInstAtOrNull( - std::get(SecondEntry.Context), - SecondEntry.Line, SecondEntry.Column); + llvm::report_fatal_error("Unknown variant type.\n"); } if (CurrInst) { @@ -100,23 +112,73 @@ getGroundTruthInsts(const std::set &GroundTruth) { std::set GroundTruthEntries; for (const auto &Entry : GroundTruth) { - const llvm::Instruction *CurrInst = nullptr; - if (std::holds_alternative(Entry.Context)) { - CurrInst = llvm::dyn_cast( - std::get(Entry.Context)); - } else if (Entry.LambdaFunc) { - CurrInst = unittest::getInstAtOrNull( - std::get(Entry.Context), Entry.Line, - Entry.Column, Entry.LambdaFunc); + if (std::get_if(&Entry.Context)) { + llvm::report_fatal_error("Cannot cast global variable to Instruction\n"); + } else if (const auto *Func = + std::get_if(&Entry.Context)) { + if (Entry.LambdaFunc) { + GroundTruthEntries.insert(unittest::getInstAtOrNull( + *Func, Entry.Line, Entry.Column, Entry.LambdaFunc)); + } else { + GroundTruthEntries.insert( + unittest::getInstAtOrNull(*Func, Entry.Line, Entry.Column)); + } } else { - CurrInst = unittest::getInstAtOrNull( - std::get(Entry.Context), Entry.Line, - Entry.Column); + llvm::report_fatal_error("Unknown variant type.\n"); } + } - if (CurrInst) { - GroundTruthEntries.insert(CurrInst); + return GroundTruthEntries; +}; + +static std::set +getGroundTruthValues(const std::set &GroundTruth) { + std::set GroundTruthEntries; + + for (const auto &Entry : GroundTruth) { + if (const auto *Func = + std::get_if(&Entry.Context)) { + if (Entry.LambdaFunc) { + if (const auto *FuncVariantInst = unittest::getInstAtOrNull( + *Func, Entry.Line, Entry.Column, Entry.LambdaFunc)) { + if (const auto *CurrVal = + llvm::dyn_cast_or_null(FuncVariantInst)) { + GroundTruthEntries.insert(CurrVal); + continue; + } + llvm::errs() + << "FuncVariantInst Instruction couldn't be cast to value.\n"; + } + + continue; + } + + if (const auto *FuncVariantInst = + unittest::getInstAtOrNull(*Func, Entry.Line, Entry.Column)) { + llvm::outs() << "FuncVariantInst: " << FuncVariantInst << "\n"; + llvm::outs() << "*FuncVariantInst: " << *FuncVariantInst << "\n"; + if (const auto *CurrVal = + llvm::dyn_cast_or_null(FuncVariantInst)) { + GroundTruthEntries.insert(CurrVal); + continue; + } + + llvm::errs() + << "FuncVariantInst Instruction couldn't be cast to value.\n"; + } else { + llvm::errs() << "getInstAtOrNull returned null\n"; + } + + continue; + } + + if (const auto *GlobalVar = + std::get_if(&Entry.Context)) { + GroundTruthEntries.insert(llvm::cast(*GlobalVar)); + continue; } + + llvm::report_fatal_error("Unknown variant type.\n"); } return GroundTruthEntries; diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp index 2763767656..61c54d70b4 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp @@ -146,8 +146,15 @@ TEST_F(IDETaintAnalysisTest, XTaint01_Json) { Config.Functions.push_back(std::move(FuncDataMain)); Config.Functions.push_back(std::move(FuncDataPrint)); - // TODO: completely rework this test? - // GroundTruth.insert({{8, 3}, {8, 9}}); + SrcCodeLocationEntry Call = + SrcCodeLocationEntry(8, 3, HA.getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry Leak = + SrcCodeLocationEntry(8, 9, HA.getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + + GroundTruth.insert({Call, Leak}); doAnalysis(HA, GroundTruth, &Config); } @@ -156,8 +163,15 @@ TEST_F(IDETaintAnalysisTest, XTaint01) { HelperAnalyses HA({PathToLLFiles + "xtaint01_cpp_dbg.ll"}, EntryPoints); std::set> GroundTruth; - GroundTruth.insert({{8, 3, HA.getProjectIRDB().getFunction("main")}, - {8, 9, HA.getProjectIRDB().getFunction("main")}}); + SrcCodeLocationEntry Call = + SrcCodeLocationEntry(8, 3, HA.getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry Leak = + SrcCodeLocationEntry(8, 9, HA.getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + + GroundTruth.insert({Call, Leak}); doAnalysis(HA, GroundTruth, std::monostate{}); } @@ -201,7 +215,7 @@ TEST_F(IDETaintAnalysisTest, XTaint04) { std::set> GroundTruth; SrcCodeLocationEntry Call = - SrcCodeLocationEntry(6, 3, HA.getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry(6, 3, HA.getProjectIRDB().getFunction("_Z3barPi")); // TODO: the counter implementation isn't great, as it still relies on IR // behaviour that might change based on operating system or other factors. A diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp index ab29ecc820..140492030b 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp @@ -66,7 +66,7 @@ class IFDSConstAnalysisTest : public ::testing::Test { void compareResults(const std::set &GroundTruth, IFDSSolver_P &Solver) { - auto GroundTruthEntriesAsInsts = getGroundTruthInsts(GroundTruth); + auto GroundTruthEntriesAsInsts = getGroundTruthValues(GroundTruth); std::set GroundTruthEntries; for (const auto *Entry : GroundTruthEntriesAsInsts) { if (const auto *EntryVal = llvm::dyn_cast_or_null(Entry)) { @@ -74,7 +74,7 @@ class IFDSConstAnalysisTest : public ::testing::Test { continue; } - llvm::outs() + llvm::errs() << "Ground Truth Instruction was not a Value and can't be a " "correct entry here. Please double check the Ground Truth.\n"; ASSERT_TRUE(false); @@ -224,33 +224,33 @@ TEST_F(IFDSConstAnalysisTest, HandleGlobalTest_01) { initialize({PathToLlFiles + "global/global_01_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - for (const auto &Global : HA->getProjectIRDB().getModule()->getGlobalList()) { - llvm::outs() << "Global.getName(): " << Global.getName() << "\n"; - } SrcCodeLocationEntry Entry( 1, 0, HA->getProjectIRDB().getGlobalVariableDefinition("g1")); std::set GroundTruth{Entry}; - compareResults(GroundTruth, Llvmconstsolver); } -#if false - - 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); + SrcCodeLocationEntry Entry( + 1, 0, HA->getProjectIRDB().getGlobalVariableDefinition("g")); + SrcCodeLocationEntry EntryTwo(4, 7, HA->getProjectIRDB().getFunction("main")); + std::set GroundTruth{Entry, EntryTwo}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, HandleGlobalTest_03) { initialize({PathToLlFiles + "global/global_03_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - - /// The @llvm.global_ctors global variable is never immutable - compareResults({0, /*1,*/ 2}, Llvmconstsolver); + SrcCodeLocationEntry Entry( + 1, 0, HA->getProjectIRDB().getGlobalVariableDefinition("g")); + SrcCodeLocationEntry EntryTwo( + 0, 0, HA->getProjectIRDB().getFunction("__cxx_global_var_init")); + std::set GroundTruth{Entry, EntryTwo}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, DISABLED_HandleGlobalTest_04) { @@ -259,29 +259,40 @@ 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); + SrcCodeLocationEntry Entry( + 1, 0, HA->getProjectIRDB().getGlobalVariableDefinition("g1")); + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } +#if false + /* ============== CALL TESTS ============== */ 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); + SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("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); + SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("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); + SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, DISABLED_HandleCallParamTest_04) { @@ -299,7 +310,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) { @@ -313,14 +324,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); + SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("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); + SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, HandleCallReturnTest_01) { @@ -334,14 +349,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); + SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); + 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); + SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } /* ============== ARRAY TESTS ============== */ @@ -379,7 +398,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); + SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, HandleArrayTest_06) { @@ -387,7 +408,9 @@ TEST_F(IFDSConstAnalysisTest, HandleArrayTest_06) { IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); HA->getAliasInfo().print(llvm::errs()); - compareResults({1}, Llvmconstsolver); + SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } TEST_F(IFDSConstAnalysisTest, DISABLED_HandleArrayTest_07) { @@ -410,7 +433,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); + SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } /* ============== STL ARRAY TESTS ============== */ @@ -425,7 +450,9 @@ 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); + SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } PHASAR_SKIP_TEST(TEST_F(IFDSConstAnalysisTest, HandleSTLArrayTest_03) { @@ -435,7 +462,9 @@ 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); + SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); }) TEST_F(IFDSConstAnalysisTest, DISABLED_HandleSTLArrayTest_04) { From ed2708a2d7a8a34f8371e4b51362c2c659e9ec01 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Sun, 20 Jul 2025 23:58:18 +0200 Subject: [PATCH 11/35] compile tests as dbg + ground truths --- include/phasar/Utils/SrcCodeLocationEntry.h | 55 +++- .../general_linear_constant/CMakeLists.txt | 2 +- .../openssl/key_derivation/CMakeLists.txt | 2 +- .../openssl/secure_heap/CMakeLists.txt | 2 +- .../openssl/secure_memory/CMakeLists.txt | 2 +- .../typestate_analysis_fileio/CMakeLists.txt | 5 - .../DataFlow/IfdsIde/Problems/CMakeLists.txt | 2 +- .../Problems/IDEGeneralizedLCATest.cpp | 266 ++++++++++++------ .../Problems/IFDSConstAnalysisTest.cpp | 59 ++-- .../IFDSUninitializedVariablesTest.cpp | 16 +- 10 files changed, 286 insertions(+), 125 deletions(-) diff --git a/include/phasar/Utils/SrcCodeLocationEntry.h b/include/phasar/Utils/SrcCodeLocationEntry.h index 1eff7bf535..9b9ce5931b 100644 --- a/include/phasar/Utils/SrcCodeLocationEntry.h +++ b/include/phasar/Utils/SrcCodeLocationEntry.h @@ -20,14 +20,20 @@ namespace psr { struct SrcCodeLocationEntry { + // TODO: the const llvm::Instruction * variant is not good, as it basically + // completely ignores the line and column aspect of the source file. We want + // to tie the unittest to the source file, but for very specific cases, this + // variant was the only way I found to make the unittests run. SrcCodeLocationEntry( uint32_t Line, uint32_t Column, - std::variant + std::variant Context) : Line(Line), Column(Column), Context(Context) {} SrcCodeLocationEntry( uint32_t Line, uint32_t Column, - std::variant + std::variant Context, std::function LambdaFunc) : Line(Line), Column(Column), LambdaFunc(std::move(LambdaFunc)), @@ -35,7 +41,9 @@ struct SrcCodeLocationEntry { uint32_t Line = 0; uint32_t Column = 0; std::function LambdaFunc = nullptr; - std::variant Context; + std::variant + Context; bool operator==(const SrcCodeLocationEntry &Other) const { return Line == Other.Line && Column == Other.Column; @@ -60,6 +68,15 @@ getGroundTruthInsts( if (std::get_if(&FirstEntry.Context)) { llvm::report_fatal_error("Cannot cast global variable to Instruction\n"); + } + + if (const auto *Inst = + std::get_if(&FirstEntry.Context)) { + if (*Inst) { + CurrInst = *Inst; + } else { + llvm::report_fatal_error("Given Ground Truth Instruction was null.\n"); + } } else if (const auto *Func = std::get_if(&FirstEntry.Context)) { if (FirstEntry.LambdaFunc) { @@ -114,8 +131,20 @@ getGroundTruthInsts(const std::set &GroundTruth) { for (const auto &Entry : GroundTruth) { if (std::get_if(&Entry.Context)) { llvm::report_fatal_error("Cannot cast global variable to Instruction\n"); - } else if (const auto *Func = - std::get_if(&Entry.Context)) { + } + + if (const auto *Inst = + std::get_if(&Entry.Context)) { + if (*Inst) { + GroundTruthEntries.insert(*Inst); + continue; + } + + llvm::report_fatal_error("Given Ground Truth Instruction was null.\n"); + } + + if (const auto *Func = + std::get_if(&Entry.Context)) { if (Entry.LambdaFunc) { GroundTruthEntries.insert(unittest::getInstAtOrNull( *Func, Entry.Line, Entry.Column, Entry.LambdaFunc)); @@ -123,9 +152,9 @@ getGroundTruthInsts(const std::set &GroundTruth) { GroundTruthEntries.insert( unittest::getInstAtOrNull(*Func, Entry.Line, Entry.Column)); } - } else { - llvm::report_fatal_error("Unknown variant type.\n"); + continue; } + llvm::report_fatal_error("Unknown variant type.\n"); } return GroundTruthEntries; @@ -167,6 +196,9 @@ getGroundTruthValues(const std::set &GroundTruth) { << "FuncVariantInst Instruction couldn't be cast to value.\n"; } else { llvm::errs() << "getInstAtOrNull returned null\n"; + llvm::errs() << "Entry.Line: " << Entry.Line << "\n"; + llvm::errs() << "Entry.Column: " << Entry.Column << "\n"; + llvm::errs() << "*Func: " << *Func << "\n"; } continue; @@ -177,6 +209,15 @@ getGroundTruthValues(const std::set &GroundTruth) { GroundTruthEntries.insert(llvm::cast(*GlobalVar)); continue; } + if (const auto *Inst = + std::get_if(&Entry.Context)) { + if (*Inst) { + GroundTruthEntries.insert(llvm::cast(*Inst)); + continue; + } + + llvm::report_fatal_error("Given Ground Truth Instruction was null.\n"); + } llvm::report_fatal_error("Unknown variant type.\n"); } 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/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/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/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/CMakeLists.txt b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/CMakeLists.txt index 7d5a903495..c7842c38d7 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/CMakeLists.txt +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/CMakeLists.txt @@ -28,5 +28,5 @@ endif() test_require_config_file("DOTGraphConfig.json") foreach(TEST_SRC ${IfdsIdeProblemSources}) - add_phasar_unittest(${TEST_SRC}) + add_phasar_unittest(${TEST_SRC} DEBUG) endforeach(TEST_SRC) diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp index 4f30b2c339..6261016021 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp @@ -70,15 +70,17 @@ class IDEGeneralizedLCATest : public ::testing::Test { // compare results /// \brief compares the computed results with every given tuple (value, /// alloca, inst) - void compareResults(const std::set &Expected, - const std::vector &EVal) { + void compareResults( + std::vector> &Expected) { for (const auto &Entry : Expected) { + const auto &SCLEntry = std::get<0>(Entry); const auto *Vr = unittest::getInstAtOrNull( - std::get(Entry.Context), Entry.Line, - Entry.Column); + std::get(SCLEntry.Context), SCLEntry.Line, + SCLEntry.Column); const auto *Inst = unittest::getInstAtOrNull( - std::get(Entry.Context), Entry.Line, - Entry.Column); + std::get(SCLEntry.Context), SCLEntry.Line, + SCLEntry.Column); bool Flag = false; @@ -97,6 +99,7 @@ class IDEGeneralizedLCATest : public ::testing::Test { } if (Flag) { + EXPECT_TRUE(false); continue; } @@ -104,9 +107,10 @@ class IDEGeneralizedLCATest : public ::testing::Test { ASSERT_NE(nullptr, Inst); auto Result = LCASolver->resultAt(Inst, Vr); - // EXPECT_EQ(EVal, Result) - // << "vr:" << Vr->getValueID() << " inst:" << Inst->getValueID() - // << " Expected: " << EVal << " Got:" << Result; + auto EVal = std::get<1>(Entry); + EXPECT_EQ(EVal, Result) + << "vr:" << Vr->getValueID() << " inst:" << Inst->getValueID() + << " Expected: " << EVal << " Got:" << Result; } /*for (const auto &[EVal, VrId, InstId] : Expected) { @@ -126,128 +130,224 @@ class IDEGeneralizedLCATest : public ::testing::Test { }; // class Fixture TEST_F(IDEGeneralizedLCATest, SimpleTest) { - initialize("SimpleTest_c.ll"); - std::set GroundTruth; - // Old ground truth - // GroundTruth.push_back({{EdgeValue(10)}, 3, 20}); - // GroundTruth.push_back({{EdgeValue(15)}, 4, 20}); - - // New ground truth based on src file - GroundTruth.insert( - SrcCodeLocationEntry(5, 3, HA->getProjectIRDB().getFunction("main"))); - GroundTruth.insert( - SrcCodeLocationEntry(6, 3, HA->getProjectIRDB().getFunction("main"))); - std::vector EVs = {EdgeValue(10), EdgeValue(15)}; - - compareResults(GroundTruth, EVs); -} + initialize("SimpleTest_c_dbg.ll"); -#if false + std::vector> + GroundTruth; + + /* + TODO: ask Fabian why the edge values from the previous ground truths do not + work anymore. An example result: + vr:58 inst:58 Expected: {15} Got:{} + + Also, ask how to determine the correct EdgeValue. + */ + + GroundTruth.push_back( + {SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue(10)}}); + GroundTruth.push_back( + {SrcCodeLocationEntry(6, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue(15)}}); + + compareResults(GroundTruth); +} TEST_F(IDEGeneralizedLCATest, BranchTest) { - initialize("BranchTest_c.ll"); - std::vector GroundTruth; - GroundTruth.push_back({{EdgeValue(25), EdgeValue(43)}, 3, 22}); - GroundTruth.push_back({{EdgeValue(24)}, 4, 22}); + initialize("BranchTest_c_dbg.ll"); + // TODO: Test fails. An example result: + // vr:59 inst:59 Expected: {24} Got:{} + + std::vector> + GroundTruth; + GroundTruth.push_back( + {SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue(25)}}); + GroundTruth.push_back( + {SrcCodeLocationEntry(7, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue(24)}}); compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, FPtest) { - initialize("FPtest_c.ll"); + initialize("FPtest_c_dbg.ll"); + // TODO: Test fails. An example result: + // vr:59 inst:59 Expected: {2.000000e+00} Got:{} + + std::vector> + GroundTruth; + GroundTruth.push_back( + {SrcCodeLocationEntry(4, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue(4.5)}}); + GroundTruth.push_back( + {SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue(2.0)}}); - std::vector GroundTruth; - GroundTruth.push_back({{EdgeValue(4.5)}, 1, 16}); - GroundTruth.push_back({{EdgeValue(2.0)}, 2, 16}); compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, StringTest) { - initialize("StringTest_c.ll"); - std::vector GroundTruth; - GroundTruth.push_back({{EdgeValue("Hello, World")}, 2, 8}); - GroundTruth.push_back({{EdgeValue("Hello, World")}, 3, 8}); + initialize("StringTest_c_dbg.ll"); + // TODO: Test fails. An example result: + // vr:58 inst:58 Expected: {"Hello, World"} Got:{} + + std::vector> + GroundTruth; + GroundTruth.push_back( + {SrcCodeLocationEntry(4, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue("Hello, World")}}); + GroundTruth.push_back( + {SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue("Hello, World")}}); + compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, StringBranchTest) { - initialize("StringBranchTest_c.ll"); - std::vector GroundTruth; + initialize("StringBranchTest_c_dbg.ll"); + // TODO: Test fails. An example result: + // vr:59 inst:59 Expected: {"Hello, World"} Got:{} + + std::vector> + GroundTruth; + /* + TODO: check which version is correct here + */ +#if false GroundTruth.push_back( - {{EdgeValue("Hello, World"), EdgeValue("Hello Hello")}, 3, 15}); - GroundTruth.push_back({{EdgeValue("Hello Hello")}, 4, 15}); + {SrcCodeLocationEntry(4, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue("Hello, World"), EdgeValue("Hello, World")}}); + GroundTruth.push_back( + {SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue("Hello, World")}}); +#endif + + GroundTruth.push_back( + {SrcCodeLocationEntry(4, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue("Hello, World")}}); + GroundTruth.push_back( + {SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue("Hello, World")}}); + GroundTruth.push_back( + {SrcCodeLocationEntry(8, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue("Hello, World")}}); + compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, StringTestCpp) { - initialize("StringTest_cpp.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)))}); + initialize("StringTest_cpp_dbg.ll"); + // TODO: Test fails. An example result: + // vr:58 inst:58 Expected: {"Hello, World"} Got:{} + + std::vector> + GroundTruth; + GroundTruth.push_back( + {SrcCodeLocationEntry(4, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue("Hello, World")}}); + compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, FloatDivisionTest) { - initialize("FloatDivision_c.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 + initialize("FloatDivision_c_dbg.ll"); + // TODO: Test fails. An example result: + // vr:59 inst:59 Expected: {-7.000000e+00} Got:{} + + std::vector> + GroundTruth; + GroundTruth.push_back( + {SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue(nullptr)}}); + GroundTruth.push_back( + {SrcCodeLocationEntry(6, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue(1.0)}}); + GroundTruth.push_back( + {SrcCodeLocationEntry(7, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue(-7.0)}}); + compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, SimpleFunctionTest) { - initialize("SimpleFunctionTest_c.ll"); - std::vector GroundTruth; - GroundTruth.push_back({{EdgeValue(48)}, 10, 31}); // i - GroundTruth.push_back({{EdgeValue(nullptr)}, 11, 31}); // j + initialize("SimpleFunctionTest_c_dbg.ll"); + // TODO: Test fails. An example result: + // vr:59 inst:59 Expected: {48} Got:{} + + std::vector> + GroundTruth; + GroundTruth.push_back( + {SrcCodeLocationEntry(8, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue(48)}}); + GroundTruth.push_back( + {SrcCodeLocationEntry(9, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue(nullptr)}}); + compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, GlobalVariableTest) { - initialize("GlobalVariableTest_c.ll"); - std::vector GroundTruth; - GroundTruth.push_back({{EdgeValue(50)}, 7, 13}); // i - GroundTruth.push_back({{EdgeValue(8)}, 10, 13}); // j + initialize("GlobalVariableTest_c_dbg.ll"); + // TODO: Test fails. An example result: + // vr:58 inst:58 Expected: {8} Got:{} + + std::vector> + GroundTruth; + GroundTruth.push_back( + {SrcCodeLocationEntry(4, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue(50)}}); + GroundTruth.push_back( + {SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue(8)}}); + 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); - - // llvm::outs() << "foo.x = " << LCASolver->resultAt(barInst, xInst) << - // std::endl; llvm::outs() << "foo.y = " << LCASolver->resultAt(barInst, - // yInst) - // << std::endl; - - std::vector GroundTruth; - GroundTruth.push_back({{EdgeValue(1), EdgeValue(2)}, 0, 7}); // i - GroundTruth.push_back({{EdgeValue(2), EdgeValue(3)}, 1, 7}); // j + initialize("Imprecision_c_dbg.ll"); + // TODO: Test fails. An example result: + // vr:83 inst:83 Expected: {3, 2} Got:{} + + std::vector> + GroundTruth; + GroundTruth.push_back( + {SrcCodeLocationEntry(6, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue(1), EdgeValue(2)}}); + GroundTruth.push_back( + {SrcCodeLocationEntry(7, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue(2), EdgeValue(3)}}); + compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, ReturnConstTest) { - initialize("ReturnConstTest_c.ll"); - std::vector GroundTruth; - GroundTruth.push_back({{EdgeValue(43)}, 7, 8}); // i + initialize("ReturnConstTest_c_dbg.ll"); + // TODO: Test fails. An example result: + // vr:59 inst:59 Expected: {43} Got:{} + + std::vector> + GroundTruth; + GroundTruth.push_back( + {SrcCodeLocationEntry(6, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue(43)}}); + compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, NullTest) { - initialize("NullTest_c.ll"); - std::vector GroundTruth; - GroundTruth.push_back({{EdgeValue("")}, 4, 5}); // foo(null) + initialize("NullTest_c_dbg.ll"); + // TODO: Test fails. An example result: + // vr:83 inst:83 Expected: {""} Got:{} + + std::vector> + GroundTruth; + GroundTruth.push_back( + {SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), + {EdgeValue("")}}); + compareResults(GroundTruth); } -#endif - int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp index 140492030b..9956df235e 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp @@ -70,6 +70,7 @@ class IFDSConstAnalysisTest : public ::testing::Test { std::set GroundTruthEntries; for (const auto *Entry : GroundTruthEntriesAsInsts) { if (const auto *EntryVal = llvm::dyn_cast_or_null(Entry)) { + llvm::outs() << "*EntryVal: " << *EntryVal << "\n"; GroundTruthEntries.insert(EntryVal); continue; } @@ -245,10 +246,19 @@ TEST_F(IFDSConstAnalysisTest, HandleGlobalTest_03) { initialize({PathToLlFiles + "global/global_03_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); + + const llvm::Instruction *CorrectCall = + &(HA->getProjectIRDB() + .getFunction("__cxx_global_var_init") + ->getBasicBlockList() + .front() + .getInstList() + .front()); + SrcCodeLocationEntry Entry( 1, 0, HA->getProjectIRDB().getGlobalVariableDefinition("g")); - SrcCodeLocationEntry EntryTwo( - 0, 0, HA->getProjectIRDB().getFunction("__cxx_global_var_init")); + SrcCodeLocationEntry EntryTwo(0, 0, CorrectCall); + std::set GroundTruth{Entry, EntryTwo}; compareResults(GroundTruth, Llvmconstsolver); } @@ -265,14 +275,12 @@ TEST_F(IFDSConstAnalysisTest, DISABLED_HandleGlobalTest_04) { compareResults(GroundTruth, Llvmconstsolver); } -#if false - /* ============== CALL TESTS ============== */ TEST_F(IFDSConstAnalysisTest, HandleCallParamTest_01) { initialize({PathToLlFiles + "call/param/call_param_01_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry Entry(5, 0, HA->getProjectIRDB().getFunction("main")); std::set GroundTruth{Entry}; compareResults(GroundTruth, Llvmconstsolver); } @@ -281,7 +289,7 @@ TEST_F(IFDSConstAnalysisTest, HandleCallParamTest_02) { initialize({PathToLlFiles + "call/param/call_param_02_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry Entry(5, 0, HA->getProjectIRDB().getFunction("main")); std::set GroundTruth{Entry}; compareResults(GroundTruth, Llvmconstsolver); } @@ -290,8 +298,9 @@ TEST_F(IFDSConstAnalysisTest, HandleCallParamTest_03) { initialize({PathToLlFiles + "call/param/call_param_03_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); - std::set GroundTruth{Entry}; + // SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); + // std::set GroundTruth{Entry}; + std::set GroundTruth{}; compareResults(GroundTruth, Llvmconstsolver); } @@ -324,7 +333,7 @@ TEST_F(IFDSConstAnalysisTest, HandleCallParamTest_07) { initialize({PathToLlFiles + "call/param/call_param_07_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry Entry(0, 0, HA->getProjectIRDB().getFunction("main")); std::set GroundTruth{Entry}; compareResults(GroundTruth, Llvmconstsolver); } @@ -333,7 +342,7 @@ TEST_F(IFDSConstAnalysisTest, HandleCallParamTest_08) { initialize({PathToLlFiles + "call/param/call_param_08_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry Entry(9, 0, HA->getProjectIRDB().getFunction("main")); std::set GroundTruth{Entry}; compareResults(GroundTruth, Llvmconstsolver); } @@ -349,8 +358,9 @@ TEST_F(IFDSConstAnalysisTest, HandleCallReturnTest_02) { initialize({PathToLlFiles + "call/return/call_ret_02_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); - std::set GroundTruth{Entry}; + // SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); + // std::set GroundTruth{Entry}; + std::set GroundTruth{}; compareResults(GroundTruth, Llvmconstsolver); } @@ -358,8 +368,9 @@ TEST_F(IFDSConstAnalysisTest, HandleCallReturnTest_03) { initialize({PathToLlFiles + "call/return/call_ret_03_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); - std::set GroundTruth{Entry}; + // SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); + // std::set GroundTruth{Entry}; + std::set GroundTruth{}; compareResults(GroundTruth, Llvmconstsolver); } @@ -398,7 +409,7 @@ TEST_F(IFDSConstAnalysisTest, HandleArrayTest_05) { initialize({PathToLlFiles + "array/array_05_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry Entry(3, 0, HA->getProjectIRDB().getFunction("main")); std::set GroundTruth{Entry}; compareResults(GroundTruth, Llvmconstsolver); } @@ -408,7 +419,7 @@ TEST_F(IFDSConstAnalysisTest, HandleArrayTest_06) { IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); HA->getAliasInfo().print(llvm::errs()); - SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry Entry(3, 0, HA->getProjectIRDB().getFunction("main")); std::set GroundTruth{Entry}; compareResults(GroundTruth, Llvmconstsolver); } @@ -433,7 +444,7 @@ TEST_F(IFDSConstAnalysisTest, HandleArrayTest_09) { initialize({PathToLlFiles + "array/array_09_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry Entry(3, 0, HA->getProjectIRDB().getFunction("main")); std::set GroundTruth{Entry}; compareResults(GroundTruth, Llvmconstsolver); } @@ -450,7 +461,7 @@ TEST_F(IFDSConstAnalysisTest, HandleSTLArrayTest_02) { initialize({PathToLlFiles + "array/stl_array/stl_array_02_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry Entry(4, 0, HA->getProjectIRDB().getFunction("main")); std::set GroundTruth{Entry}; compareResults(GroundTruth, Llvmconstsolver); } @@ -462,7 +473,7 @@ 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(); - SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry Entry(4, 0, HA->getProjectIRDB().getFunction("main")); std::set GroundTruth{Entry}; compareResults(GroundTruth, Llvmconstsolver); }) @@ -487,7 +498,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); + SrcCodeLocationEntry Entry(4, 0, HA->getProjectIRDB().getFunction("main")); + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } /* ============== CSTRING TESTS ============== */ @@ -504,9 +517,13 @@ 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); + SrcCodeLocationEntry Entry(4, 0, HA->getProjectIRDB().getFunction("main")); + std::set GroundTruth{Entry}; + compareResults(GroundTruth, Llvmconstsolver); } +#if false + /* ============== STRUCTURE TESTS ============== */ // TEST_F(IFDSConstAnalysisTest, HandleStructureTest_01) { // Initialize({pathToLLFiles + "structs/structs_01_cpp_dbg.ll"}); diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp index 839dbc7c11..e85e69873f 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp @@ -61,8 +61,10 @@ class IFDSUninitializedVariablesTest : public ::testing::Test { FoundUninitUses; for (const auto &Kvp : UninitProblem->getAllUndefUses()) { const auto *SourceInst = Kvp.first; + llvm::outs() << "*SourceInst: " << *SourceInst << "\n"; for (const auto *UV : Kvp.second) { + llvm::outs() << "*UV: " << *UV << "\n"; FoundUninitUses.insert({SourceInst, UV}); } } @@ -90,10 +92,16 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_02_SHOULD_LEAK) { // %4 = load i32, i32* %2, ID: 6 ; %2 is the uninitialized variable i // %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.insert( - {SrcCodeLocationEntry(2, 0, HA->getICFG().getIRDB()->getFunction("main")), - SrcCodeLocationEntry(3, 11, - HA->getICFG().getIRDB()->getFunction("main"))}); +#if false + const auto Entry = + SrcCodeLocationEntry(2, 0, HA->getICFG().getIRDB()->getFunction("main")); + const auto EntryTwo = + SrcCodeLocationEntry(3, 11, HA->getICFG().getIRDB()->getFunction("main")); + const auto EntryThree = + SrcCodeLocationEntry(3, 13, HA->getICFG().getIRDB()->getFunction("main")); + GroundTruth.insert({Entry, EntryTwo}); + GroundTruth.insert({EntryTwo, }); +#endif compareResults(GroundTruth); } From 2cb26c1bcc283493f557059f418fb4715042f594 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Mon, 21 Jul 2025 09:11:06 +0200 Subject: [PATCH 12/35] Fix Gt for UninitTest_02_SHOULD_LEAK --- .../IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp index e85e69873f..6516023073 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp @@ -92,16 +92,16 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_02_SHOULD_LEAK) { // %4 = load i32, i32* %2, ID: 6 ; %2 is the uninitialized variable i // %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 -#if false + const auto Entry = SrcCodeLocationEntry(2, 0, HA->getICFG().getIRDB()->getFunction("main")); const auto EntryTwo = SrcCodeLocationEntry(3, 11, HA->getICFG().getIRDB()->getFunction("main")); const auto EntryThree = SrcCodeLocationEntry(3, 13, HA->getICFG().getIRDB()->getFunction("main")); - GroundTruth.insert({Entry, EntryTwo}); - GroundTruth.insert({EntryTwo, }); -#endif + GroundTruth.insert({EntryTwo, Entry}); + GroundTruth.insert({EntryThree, EntryTwo}); + compareResults(GroundTruth); } From 379444f26a437570ff3f3cded628e314d94beb59 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Mon, 21 Jul 2025 10:16:45 +0200 Subject: [PATCH 13/35] Add TestingSrcLocation --- .clang-tidy | 2 +- include/phasar/Utils/SrcCodeLocationEntry.h | 158 +++++++++++++++++- .../Problems/IFDSConstAnalysisTest.cpp | 78 ++++++--- unittests/TestUtils/SourceMapping.h | 1 + 4 files changed, 210 insertions(+), 29 deletions(-) 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/Utils/SrcCodeLocationEntry.h b/include/phasar/Utils/SrcCodeLocationEntry.h index 9b9ce5931b..ffbc889841 100644 --- a/include/phasar/Utils/SrcCodeLocationEntry.h +++ b/include/phasar/Utils/SrcCodeLocationEntry.h @@ -1,6 +1,11 @@ #ifndef PHASAR_UTILS_SRCCODELOCATIONENTRY_H #define PHASAR_UTILS_SRCCODELOCATIONENTRY_H +#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" +#include "phasar/Utils/Utilities.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" #include "llvm/IR/Function.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Instruction.h" @@ -13,12 +18,159 @@ #include #include +#include #include +#include #include #include namespace psr { +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; + } +}; +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); + } +}; +struct LineColFun { + uint32_t Line{}; + uint32_t Col{}; + llvm::StringRef InFunction{}; + + 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); + } + 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); + } +}; +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; + } +}; +struct ArgInFun { + uint32_t Idx; + llvm::StringRef InFunction{}; + + friend bool operator<(ArgInFun A1, ArgInFun A2) noexcept { + return std::tie(A1.Idx, A1.InFunction) < std::tie(A2.Idx, A2.InFunction); + } + friend bool operator==(ArgInFun A1, ArgInFun A2) noexcept { + return std::tie(A1.Idx, A1.InFunction) == std::tie(A2.Idx, A2.InFunction); + } +}; + +struct TestingSrcLocation + : public std::variant { + + using std::variant::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]] inline const llvm::Value * +testingLocInIR(TestingSrcLocation Loc, const LLVMProjectIRDB &IRDB, + const llvm::Function *InterestingFunction = nullptr) { + + return 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 unittest::getInstAtOrNull(InterestingFunction, LC.Line, + LC.Col); + }, + [&IRDB](LineColFun LC) -> llvm ::Value const * { + const auto *InFun = IRDB.getFunctionDefinition(LC.InFunction); + if (!InFun) { + llvm::report_fatal_error("Required function '" + LC.InFunction + + "' does not exist in the IR!"); + } + return unittest::getInstAtOrNull(InFun, LC.Line, LC.Col); + }, + [&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); + }, + [&IRDB](ArgInFun A) -> llvm ::Value const * { + const auto *InFun = IRDB.getFunctionDefinition(A.InFunction); + if (!InFun) { + llvm::report_fatal_error("Required function '" + A.InFunction + + "' does not exist in the IR!"); + } + 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); + }, + }, + Loc); +} + +template +[[nodiscard]] inline std::set +convertTestingLocationSetInIR( + const SetTy &Locs, const LLVMProjectIRDB &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; +} + struct SrcCodeLocationEntry { // TODO: the const llvm::Instruction * variant is not good, as it basically // completely ignores the line and column aspect of the source file. We want @@ -53,7 +205,7 @@ struct SrcCodeLocationEntry { } }; -static std::set> +inline std::set> getGroundTruthInsts( const std::set> &GroundTruth) { @@ -124,7 +276,7 @@ getGroundTruthInsts( return GroundTruthEntries; }; -static std::set +inline std::set getGroundTruthInsts(const std::set &GroundTruth) { std::set GroundTruthEntries; @@ -160,7 +312,7 @@ getGroundTruthInsts(const std::set &GroundTruth) { return GroundTruthEntries; }; -static std::set +inline std::set getGroundTruthValues(const std::set &GroundTruth) { std::set GroundTruthEntries; diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp index 9956df235e..be98776390 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp @@ -21,6 +21,7 @@ #include "gtest/gtest.h" #include +#include #include using namespace std; @@ -64,6 +65,25 @@ class IFDSConstAnalysisTest : public ::testing::Test { return RetOrResInstructions; } + 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); + } + } + } + + EXPECT_EQ(GroundTruth, AllMutableAllocas); + } + void compareResults(const std::set &GroundTruth, IFDSSolver_P &Solver) { auto GroundTruthEntriesAsInsts = getGroundTruthValues(GroundTruth); @@ -81,21 +101,22 @@ class IFDSConstAnalysisTest : public ::testing::Test { ASSERT_TRUE(false); } - std::set AllMutableAllocas; + compareResultsImpl(GroundTruthEntries, Solver); + } - 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); - } - } - } + void compareResults(const std::set &GroundTruth, + IFDSSolver_P &Solver) { + auto GroundTruthEntries = + convertTestingLocationSetInIR(GroundTruth, HA->getProjectIRDB()); - EXPECT_EQ(GroundTruthEntries, AllMutableAllocas); + compareResultsImpl(GroundTruthEntries, Solver); + } + void compareResults(std::initializer_list GroundTruth, + IFDSSolver_P &Solver) { + auto GroundTruthEntries = + convertTestingLocationSetInIR(GroundTruth, HA->getProjectIRDB()); + + compareResultsImpl(GroundTruthEntries, Solver); } }; @@ -333,7 +354,7 @@ TEST_F(IFDSConstAnalysisTest, HandleCallParamTest_07) { initialize({PathToLlFiles + "call/param/call_param_07_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - SrcCodeLocationEntry Entry(0, 0, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry Entry(6, 12, HA->getProjectIRDB().getFunction("main")); std::set GroundTruth{Entry}; compareResults(GroundTruth, Llvmconstsolver); } @@ -358,9 +379,9 @@ TEST_F(IFDSConstAnalysisTest, HandleCallReturnTest_02) { initialize({PathToLlFiles + "call/return/call_ret_02_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - // SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); - // std::set GroundTruth{Entry}; - std::set GroundTruth{}; + SrcCodeLocationEntry Entry(3, 12, + HA->getProjectIRDB().getFunction("_Z3foov")); + std::set GroundTruth{Entry}; compareResults(GroundTruth, Llvmconstsolver); } @@ -368,9 +389,9 @@ TEST_F(IFDSConstAnalysisTest, HandleCallReturnTest_03) { initialize({PathToLlFiles + "call/return/call_ret_03_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - // SrcCodeLocationEntry Entry(, , HA->getProjectIRDB().getFunction("main")); - // std::set GroundTruth{Entry}; - std::set GroundTruth{}; + SrcCodeLocationEntry Entry(3, 12, + HA->getProjectIRDB().getFunction("_Z3foov")); + std::set GroundTruth{Entry}; compareResults(GroundTruth, Llvmconstsolver); } @@ -461,8 +482,11 @@ TEST_F(IFDSConstAnalysisTest, HandleSTLArrayTest_02) { initialize({PathToLlFiles + "array/stl_array/stl_array_02_cpp_m2r_dbg.ll"}); IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - SrcCodeLocationEntry Entry(4, 0, HA->getProjectIRDB().getFunction("main")); - std::set GroundTruth{Entry}; + std::set GroundTruth = { + LineColFun{4, 0, "main"}, + GlobalVar{"__const.main.a"}, + }; + compareResults(GroundTruth, Llvmconstsolver); } @@ -473,9 +497,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(); - SrcCodeLocationEntry Entry(4, 0, HA->getProjectIRDB().getFunction("main")); - std::set GroundTruth{Entry}; - compareResults(GroundTruth, Llvmconstsolver); + compareResults( + { + GlobalVar{"__const.main.a"}, + GlobalVar{".str"}, + LineColFun{4, 0, "main"}, + }, + Llvmconstsolver); }) TEST_F(IFDSConstAnalysisTest, DISABLED_HandleSTLArrayTest_04) { diff --git a/unittests/TestUtils/SourceMapping.h b/unittests/TestUtils/SourceMapping.h index d69d864286..efb492e301 100644 --- a/unittests/TestUtils/SourceMapping.h +++ b/unittests/TestUtils/SourceMapping.h @@ -2,6 +2,7 @@ #define UNITTEST_TESTUTILS_SOURCEMAPPING_H #include "phasar/PhasarLLVM/Utils/LLVMIRToSrc.h" +#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "phasar/Utils/TypeTraits.h" #include "llvm/IR/InstIterator.h" From 73df79f0faefc89399e348b080f2e5d2d602da3e Mon Sep 17 00:00:00 2001 From: mxHuber Date: Tue, 22 Jul 2025 17:30:26 +0200 Subject: [PATCH 14/35] GLCA nearly done, questions for meeting --- .../Problems/IDEGeneralizedLCATest.cpp | 440 +++++++++++++----- 1 file changed, 311 insertions(+), 129 deletions(-) diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp index 6261016021..cbb3e59a6e 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp @@ -22,6 +22,9 @@ #include "phasar/Utils/SrcCodeLocationEntry.h" #include "llvm/IR/Function.h" +#include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Operator.h" #include "llvm/Support/raw_ostream.h" #include "SourceMapping.h" @@ -33,8 +36,8 @@ using namespace psr; using namespace psr::glca; -using groundTruth_t = - std::tuple; +using groundTruth_t = std::tuple; /* ============== TEST FIXTURE ============== */ @@ -70,17 +73,14 @@ class IDEGeneralizedLCATest : public ::testing::Test { // compare results /// \brief compares the computed results with every given tuple (value, /// alloca, inst) - void compareResults( - std::vector> &Expected) { + void compareResults(std::vector &Expected) { for (const auto &Entry : Expected) { - const auto &SCLEntry = std::get<0>(Entry); - const auto *Vr = unittest::getInstAtOrNull( - std::get(SCLEntry.Context), SCLEntry.Line, - SCLEntry.Column); - const auto *Inst = unittest::getInstAtOrNull( - std::get(SCLEntry.Context), SCLEntry.Line, - SCLEntry.Column); + const auto &EVal = std::get<0>(Entry); + const auto &SCLVr = std::get<1>(Entry); + const auto &SCLInst = std::get<2>(Entry); + + const auto *Vr = getInstLambdaOrNot(SCLVr); + const auto *Inst = getInstLambdaOrNot(SCLInst); bool Flag = false; @@ -103,11 +103,12 @@ class IDEGeneralizedLCATest : public ::testing::Test { continue; } + llvm::outs() << "Result: " << LCASolver->resultAt(Inst, Vr) << "\n"; + ASSERT_NE(nullptr, Vr); ASSERT_NE(nullptr, Inst); auto Result = LCASolver->resultAt(Inst, Vr); - auto EVal = std::get<1>(Entry); EXPECT_EQ(EVal, Result) << "vr:" << Vr->getValueID() << " inst:" << Inst->getValueID() << " Expected: " << EVal << " Got:" << Result; @@ -127,223 +128,404 @@ class IDEGeneralizedLCATest : public ::testing::Test { }*/ } +private: + const llvm::Instruction * + getInstLambdaOrNot(const SrcCodeLocationEntry &Entry) { + if (Entry.LambdaFunc) { + return unittest::getInstAtOrNull( + std::get(Entry.Context), Entry.Line, + Entry.Column, Entry.LambdaFunc); + } + + return unittest::getInstAtOrNull( + std::get(Entry.Context), Entry.Line, + Entry.Column); + } }; // class Fixture TEST_F(IDEGeneralizedLCATest, SimpleTest) { initialize("SimpleTest_c_dbg.ll"); - - std::vector> - GroundTruth; - - /* - TODO: ask Fabian why the edge values from the previous ground truths do not - work anymore. An example result: - vr:58 inst:58 Expected: {15} Got:{} - - Also, ask how to determine the correct EdgeValue. - */ + std::vector GroundTruth; GroundTruth.push_back( - {SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue(10)}}); + {{EdgeValue(10)}, + SrcCodeLocationEntry(4, 0, HA->getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(7, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + })}); GroundTruth.push_back( - {SrcCodeLocationEntry(6, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue(15)}}); + {{EdgeValue(15)}, + SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(7, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + })}); compareResults(GroundTruth); } - TEST_F(IDEGeneralizedLCATest, BranchTest) { initialize("BranchTest_c_dbg.ll"); - // TODO: Test fails. An example result: - // vr:59 inst:59 Expected: {24} Got:{} + std::vector GroundTruth; - std::vector> - GroundTruth; GroundTruth.push_back( - {SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue(25)}}); + {{EdgeValue(25)}, + SrcCodeLocationEntry(7, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }), + SrcCodeLocationEntry(8, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + })}); GroundTruth.push_back( - {SrcCodeLocationEntry(7, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue(24)}}); + {{EdgeValue(24)}, + SrcCodeLocationEntry(3, 0, HA->getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(8, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + })}); + compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, FPtest) { initialize("FPtest_c_dbg.ll"); - // TODO: Test fails. An example result: - // vr:59 inst:59 Expected: {2.000000e+00} Got:{} + std::vector GroundTruth; - std::vector> - GroundTruth; GroundTruth.push_back( - {SrcCodeLocationEntry(4, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue(4.5)}}); + {{EdgeValue(4.5)}, + SrcCodeLocationEntry(4, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + llvm::outs() + << "4.5: In lambda *Inst: " << *Inst << "\n"; + llvm::outs() << "4.5: In lambda *Inst.getType(): " + << *Inst->getType() << "\n"; + llvm::outs() + << "4.5: In lambda *Inst.getOpcode(): " + << Inst->getOpcode() << "\n"; + /* Floating-point types are handled by FAdd, FSub + and FMul, instead of Add, Sub and Mul, which + are used by Integer types. + Opcode 18 is operator FMul */ + // TODO: ask Fabian if the opcode is a valid + // approach to this issue. + return Inst->getOpcode() == 18; + }), + SrcCodeLocationEntry(6, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + })}); GroundTruth.push_back( - {SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue(2.0)}}); + {{EdgeValue(2.0)}, + SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + llvm::outs() + << "2.0: In lambda *Inst: " << *Inst << "\n"; + llvm::outs() << "2.0: In lambda *Inst.getType(): " + << *Inst->getType() << "\n"; + llvm::outs() + << "2.0: In lambda *Inst.getOpcode(): " + << Inst->getOpcode() << "\n"; + /* Floating-point types are handled by FAdd, FSub + and FMul, instead of Add, Sub and Mul, which + are used by Integer types. + Opcode 16 is operator FSub */ + // TODO: ask Fabian if the opcode is a valid + // approach to this issue. + return Inst->getOpcode() == 16; + }), + SrcCodeLocationEntry(6, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + })}); compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, StringTest) { initialize("StringTest_c_dbg.ll"); - // TODO: Test fails. An example result: - // vr:58 inst:58 Expected: {"Hello, World"} Got:{} + std::vector GroundTruth; - std::vector> - GroundTruth; GroundTruth.push_back( - {SrcCodeLocationEntry(4, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue("Hello, World")}}); + {{EdgeValue("Hello, World")}, + SrcCodeLocationEntry(4, 0, HA->getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(7, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + })}); GroundTruth.push_back( - {SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue("Hello, World")}}); + {{EdgeValue("Hello, World")}, + SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(7, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + })}); compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, StringBranchTest) { initialize("StringBranchTest_c_dbg.ll"); - // TODO: Test fails. An example result: - // vr:59 inst:59 Expected: {"Hello, World"} Got:{} + std::vector GroundTruth; - std::vector> - GroundTruth; - /* - TODO: check which version is correct here - */ -#if false GroundTruth.push_back( - {SrcCodeLocationEntry(4, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue("Hello, World"), EdgeValue("Hello, World")}}); + {{EdgeValue("Hello Hello"), EdgeValue("Hello, World")}, + SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(11, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + })}); + // TODO: ask Fabian how to reach: + // %1 = load ptr, ptr %str1, align 8, !dbg !40 + // in the if.end branch GroundTruth.push_back( - {SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue("Hello, World")}}); -#endif - - GroundTruth.push_back( - {SrcCodeLocationEntry(4, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue("Hello, World")}}); - GroundTruth.push_back( - {SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue("Hello, World")}}); - GroundTruth.push_back( - {SrcCodeLocationEntry(8, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue("Hello, World")}}); + {{EdgeValue("Hello, World")}, + SrcCodeLocationEntry(8, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) mutable { + return llvm::isa(Inst); + }), + SrcCodeLocationEntry(11, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + })}); compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, StringTestCpp) { initialize("StringTest_cpp_dbg.ll"); - // TODO: Test fails. An example result: - // vr:58 inst:58 Expected: {"Hello, World"} Got:{} + std::vector GroundTruth; - std::vector> - GroundTruth; + // TODO: ask Fabian, why ReturnInst doesn't work here and how to fix that + // test. GroundTruth.push_back( - {SrcCodeLocationEntry(4, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue("Hello, World")}}); + {{EdgeValue("Hello, World")}, + SrcCodeLocationEntry(4, 0, HA->getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + llvm::outs() << "*Inst" << *Inst << "\n"; + return llvm::isa(Inst); + })}); compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, FloatDivisionTest) { initialize("FloatDivision_c_dbg.ll"); - // TODO: Test fails. An example result: - // vr:59 inst:59 Expected: {-7.000000e+00} Got:{} + std::vector GroundTruth; - std::vector> - GroundTruth; GroundTruth.push_back( - {SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue(nullptr)}}); + {{EdgeValue(1.0)}, + SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + llvm::outs() + << "In lambda *Inst: " << *Inst << "\n"; + llvm::outs() << "2.0: In lambda *Inst.getType(): " + << *Inst->getType() << "\n"; + llvm::outs() << "n lambda *Inst.getOpcode(): " + << Inst->getOpcode() << "\n"; + /* Floating-point types are handled by FAdd, FSub + and FMul, instead of Add, Sub and Mul, which + are used by Integer types. + Opcode 18 is operator fptosi */ + // TODO: ask Fabian if the opcode is a valid + // approach to this issue. + return Inst->getOpcode() == 45; + }), + SrcCodeLocationEntry(8, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + llvm::outs() << "*Inst" << *Inst << "\n"; + return llvm::isa(Inst); + })}); GroundTruth.push_back( - {SrcCodeLocationEntry(6, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue(1.0)}}); + {{EdgeValue(nullptr)}, + SrcCodeLocationEntry(6, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + llvm::outs() + << "In lambda *Inst: " << *Inst << "\n"; + llvm::outs() << "In lambda *Inst.getType(): " + << *Inst->getType() << "\n"; + llvm::outs() << "In lambda *Inst.getOpcode(): " + << Inst->getOpcode() << "\n"; + /* Floating-point types are handled by FAdd, FSub + and FMul, instead of Add, Sub and Mul, which + are used by Integer types. + Opcode 18 is operator FMul */ + // TODO: ask Fabian if the opcode is a valid + // approach to this issue. + return Inst->getOpcode() == 18; + }), + SrcCodeLocationEntry(8, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + })}); GroundTruth.push_back( - {SrcCodeLocationEntry(7, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue(-7.0)}}); + {{EdgeValue(-7.0)}, + SrcCodeLocationEntry(7, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + llvm::outs() + << "2.0: In lambda *Inst: " << *Inst << "\n"; + llvm::outs() << "2.0: In lambda *Inst.getType(): " + << *Inst->getType() << "\n"; + llvm::outs() + << "2.0: In lambda *Inst.getOpcode(): " + << Inst->getOpcode() << "\n"; + /* Floating-point types are handled by FAdd, FSub + and FMul, instead of Add, Sub and Mul, which + are used by Integer types. + Opcode 16 is operator FSub */ + // TODO: ask Fabian if the opcode is a valid + // approach to this issue. + return Inst->getOpcode() == 16; + }), + SrcCodeLocationEntry(8, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + llvm::outs() << "*Inst" << *Inst << "\n"; + return llvm::isa(Inst); + })}); compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, SimpleFunctionTest) { initialize("SimpleFunctionTest_c_dbg.ll"); - // TODO: Test fails. An example result: - // vr:59 inst:59 Expected: {48} Got:{} - - std::vector> - GroundTruth; + std::vector GroundTruth; + + // TODO: ask Fabian if this impl is fine, or if there is a better way to do + // it. + /* We want the second call inst here: + not this -> %call2 = call i32 @foo(i32 noundef %2), !dbg !42, !psr.id !43 + this -----> %call3 = call i32 @bar(i32 noundef %call2), !dbg !44, !psr.id + !45 + */ + bool FoundFirstCall = false; GroundTruth.push_back( - {SrcCodeLocationEntry(8, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue(48)}}); + {{EdgeValue(48)}, + SrcCodeLocationEntry( + 8, 0, HA->getProjectIRDB().getFunction("main"), + [&FoundFirstCall](const llvm::Instruction *Inst) mutable { + llvm::outs() << "*Inst: " << *Inst << "\n"; + if (llvm::isa(Inst) && !FoundFirstCall) { + FoundFirstCall = true; + return false; + } + return llvm::isa(Inst); + }), + SrcCodeLocationEntry(10, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + })}); GroundTruth.push_back( - {SrcCodeLocationEntry(9, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue(nullptr)}}); + {{EdgeValue(nullptr)}, + SrcCodeLocationEntry(9, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + llvm::outs() << "*Inst: " << *Inst << "\n"; + return llvm::isa(Inst); + }), + SrcCodeLocationEntry(10, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + })}); compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, GlobalVariableTest) { initialize("GlobalVariableTest_c_dbg.ll"); - // TODO: Test fails. An example result: - // vr:58 inst:58 Expected: {8} Got:{} + std::vector GroundTruth; - std::vector> - GroundTruth; GroundTruth.push_back( - {SrcCodeLocationEntry(4, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue(50)}}); + {{EdgeValue(50)}, + SrcCodeLocationEntry(4, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + llvm::outs() << "*Inst: " << *Inst << "\n"; + return llvm::isa(Inst); + }), + SrcCodeLocationEntry(6, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + })}); GroundTruth.push_back( - {SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue(8)}}); + {{EdgeValue(8)}, + SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + llvm::outs() << "*Inst: " << *Inst << "\n"; + return llvm::isa(Inst); + }), + SrcCodeLocationEntry(6, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + })}); compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, Imprecision) { initialize("Imprecision_c_dbg.ll"); - // TODO: Test fails. An example result: - // vr:83 inst:83 Expected: {3, 2} Got:{} + std::vector GroundTruth; + + // TODO: ask Fabian how to handle this test. I do not know how to handle that + // source file. I tried the calls in main, line 3 with function foo and line 1 + // with function bar. - std::vector> - GroundTruth; GroundTruth.push_back( - {SrcCodeLocationEntry(6, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue(1), EdgeValue(2)}}); + {{EdgeValue(1), EdgeValue(2)}, + SrcCodeLocationEntry(3, 0, HA->getProjectIRDB().getFunction("foo"), + [](const llvm::Instruction *Inst) { + llvm::outs() << "*Inst: " << *Inst << "\n"; + // return false; + return llvm::isa(Inst); + }), + SrcCodeLocationEntry(8, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + })}); GroundTruth.push_back( - {SrcCodeLocationEntry(7, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue(2), EdgeValue(3)}}); + {{EdgeValue(2), EdgeValue(3)}, + SrcCodeLocationEntry(3, 0, HA->getProjectIRDB().getFunction("foo"), + [](const llvm::Instruction *Inst) { + llvm::outs() << "*Inst: " << *Inst << "\n"; + return false; + // return llvm::isa(Inst); + }), + SrcCodeLocationEntry(8, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + })}); compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, ReturnConstTest) { initialize("ReturnConstTest_c_dbg.ll"); - // TODO: Test fails. An example result: - // vr:59 inst:59 Expected: {43} Got:{} + std::vector GroundTruth; - std::vector> - GroundTruth; GroundTruth.push_back( - {SrcCodeLocationEntry(6, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue(43)}}); + {{EdgeValue(43)}, + SrcCodeLocationEntry(6, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }), + SrcCodeLocationEntry(6, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + })}); compareResults(GroundTruth); } TEST_F(IDEGeneralizedLCATest, NullTest) { initialize("NullTest_c_dbg.ll"); - // TODO: Test fails. An example result: - // vr:83 inst:83 Expected: {""} Got:{} + std::vector GroundTruth; - std::vector> - GroundTruth; GroundTruth.push_back( - {SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), - {EdgeValue("")}}); + {{EdgeValue("")}, + SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + })}); compareResults(GroundTruth); } From 17bb913796efe33eb931747c7dfdd273860499dc Mon Sep 17 00:00:00 2001 From: mxHuber Date: Thu, 24 Jul 2025 22:39:39 +0200 Subject: [PATCH 15/35] taint double free tests fail --- include/phasar/Utils/SrcCodeLocationEntry.h | 40 +-- .../general_linear_constant/NullTest.c | 5 +- .../taint_analysis/CMakeLists.txt | 2 +- .../Problems/IDEGeneralizedLCATest.cpp | 299 +++--------------- .../Problems/IDETSAnalysisFileIOTest.cpp | 38 +-- .../Problems/IFDSConstAnalysisTest.cpp | 16 +- .../Problems/IFDSTaintAnalysisTest.cpp | 185 ++++++----- unittests/Utils/AnalysisPrinterTest.cpp | 4 +- 8 files changed, 177 insertions(+), 412 deletions(-) diff --git a/include/phasar/Utils/SrcCodeLocationEntry.h b/include/phasar/Utils/SrcCodeLocationEntry.h index ffbc889841..17b22a6ae7 100644 --- a/include/phasar/Utils/SrcCodeLocationEntry.h +++ b/include/phasar/Utils/SrcCodeLocationEntry.h @@ -178,14 +178,12 @@ struct SrcCodeLocationEntry { // variant was the only way I found to make the unittests run. SrcCodeLocationEntry( uint32_t Line, uint32_t Column, - std::variant + std::variant Context) : Line(Line), Column(Column), Context(Context) {} SrcCodeLocationEntry( uint32_t Line, uint32_t Column, - std::variant + std::variant Context, std::function LambdaFunc) : Line(Line), Column(Column), LambdaFunc(std::move(LambdaFunc)), @@ -193,9 +191,7 @@ struct SrcCodeLocationEntry { uint32_t Line = 0; uint32_t Column = 0; std::function LambdaFunc = nullptr; - std::variant - Context; + std::variant Context; bool operator==(const SrcCodeLocationEntry &Other) const { return Line == Other.Line && Column == Other.Column; @@ -222,15 +218,8 @@ getGroundTruthInsts( llvm::report_fatal_error("Cannot cast global variable to Instruction\n"); } - if (const auto *Inst = - std::get_if(&FirstEntry.Context)) { - if (*Inst) { - CurrInst = *Inst; - } else { - llvm::report_fatal_error("Given Ground Truth Instruction was null.\n"); - } - } else if (const auto *Func = - std::get_if(&FirstEntry.Context)) { + if (const auto *Func = + std::get_if(&FirstEntry.Context)) { if (FirstEntry.LambdaFunc) { CurrInst = unittest::getInstAtOrNull( *Func, FirstEntry.Line, FirstEntry.Column, FirstEntry.LambdaFunc); @@ -285,16 +274,6 @@ getGroundTruthInsts(const std::set &GroundTruth) { llvm::report_fatal_error("Cannot cast global variable to Instruction\n"); } - if (const auto *Inst = - std::get_if(&Entry.Context)) { - if (*Inst) { - GroundTruthEntries.insert(*Inst); - continue; - } - - llvm::report_fatal_error("Given Ground Truth Instruction was null.\n"); - } - if (const auto *Func = std::get_if(&Entry.Context)) { if (Entry.LambdaFunc) { @@ -361,15 +340,6 @@ getGroundTruthValues(const std::set &GroundTruth) { GroundTruthEntries.insert(llvm::cast(*GlobalVar)); continue; } - if (const auto *Inst = - std::get_if(&Entry.Context)) { - if (*Inst) { - GroundTruthEntries.insert(llvm::cast(*Inst)); - continue; - } - - llvm::report_fatal_error("Given Ground Truth Instruction was null.\n"); - } llvm::report_fatal_error("Unknown variant type.\n"); } 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/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/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp index cbb3e59a6e..a5e64ef1d4 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp @@ -113,19 +113,6 @@ class IDEGeneralizedLCATest : public ::testing::Test { << "vr:" << Vr->getValueID() << " inst:" << Inst->getValueID() << " Expected: " << EVal << " Got:" << Result; } - - /*for (const auto &[EVal, VrId, InstId] : Expected) { - const auto *Vr = HA->getProjectIRDB().getInstruction(VrId); - const auto *Inst = HA->getProjectIRDB().getInstruction(InstId); - llvm::outs() << "VrId Inst: " << *Vr << "\n"; - llvm::outs() << "InstID Inst: " << *Inst << "\n"; - 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; - }*/ } private: @@ -150,17 +137,11 @@ TEST_F(IDEGeneralizedLCATest, SimpleTest) { GroundTruth.push_back( {{EdgeValue(10)}, SrcCodeLocationEntry(4, 0, HA->getProjectIRDB().getFunction("main")), - SrcCodeLocationEntry(7, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - })}); + SrcCodeLocationEntry(7, 3, HA->getProjectIRDB().getFunction("main"))}); GroundTruth.push_back( {{EdgeValue(15)}, SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), - SrcCodeLocationEntry(7, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - })}); + SrcCodeLocationEntry(7, 3, HA->getProjectIRDB().getFunction("main"))}); compareResults(GroundTruth); } @@ -170,21 +151,12 @@ TEST_F(IDEGeneralizedLCATest, BranchTest) { GroundTruth.push_back( {{EdgeValue(25)}, - SrcCodeLocationEntry(7, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }), - SrcCodeLocationEntry(8, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - })}); + SrcCodeLocationEntry(7, 11, HA->getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(8, 3, HA->getProjectIRDB().getFunction("main"))}); GroundTruth.push_back( {{EdgeValue(24)}, - SrcCodeLocationEntry(3, 0, HA->getProjectIRDB().getFunction("main")), - SrcCodeLocationEntry(8, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - })}); + SrcCodeLocationEntry(7, 9, HA->getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(8, 3, HA->getProjectIRDB().getFunction("main"))}); compareResults(GroundTruth); } @@ -195,50 +167,12 @@ TEST_F(IDEGeneralizedLCATest, FPtest) { GroundTruth.push_back( {{EdgeValue(4.5)}, - SrcCodeLocationEntry(4, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - llvm::outs() - << "4.5: In lambda *Inst: " << *Inst << "\n"; - llvm::outs() << "4.5: In lambda *Inst.getType(): " - << *Inst->getType() << "\n"; - llvm::outs() - << "4.5: In lambda *Inst.getOpcode(): " - << Inst->getOpcode() << "\n"; - /* Floating-point types are handled by FAdd, FSub - and FMul, instead of Add, Sub and Mul, which - are used by Integer types. - Opcode 18 is operator FMul */ - // TODO: ask Fabian if the opcode is a valid - // approach to this issue. - return Inst->getOpcode() == 18; - }), - SrcCodeLocationEntry(6, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - })}); + SrcCodeLocationEntry(4, 9, HA->getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(6, 3, HA->getProjectIRDB().getFunction("main"))}); GroundTruth.push_back( {{EdgeValue(2.0)}, - SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - llvm::outs() - << "2.0: In lambda *Inst: " << *Inst << "\n"; - llvm::outs() << "2.0: In lambda *Inst.getType(): " - << *Inst->getType() << "\n"; - llvm::outs() - << "2.0: In lambda *Inst.getOpcode(): " - << Inst->getOpcode() << "\n"; - /* Floating-point types are handled by FAdd, FSub - and FMul, instead of Add, Sub and Mul, which - are used by Integer types. - Opcode 16 is operator FSub */ - // TODO: ask Fabian if the opcode is a valid - // approach to this issue. - return Inst->getOpcode() == 16; - }), - SrcCodeLocationEntry(6, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - })}); + SrcCodeLocationEntry(5, 9, HA->getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(6, 3, HA->getProjectIRDB().getFunction("main"))}); compareResults(GroundTruth); } @@ -250,17 +184,11 @@ TEST_F(IDEGeneralizedLCATest, StringTest) { GroundTruth.push_back( {{EdgeValue("Hello, World")}, SrcCodeLocationEntry(4, 0, HA->getProjectIRDB().getFunction("main")), - SrcCodeLocationEntry(7, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - })}); + SrcCodeLocationEntry(7, 3, HA->getProjectIRDB().getFunction("main"))}); GroundTruth.push_back( {{EdgeValue("Hello, World")}, SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), - SrcCodeLocationEntry(7, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - })}); + SrcCodeLocationEntry(7, 3, HA->getProjectIRDB().getFunction("main"))}); compareResults(GroundTruth); } @@ -271,24 +199,12 @@ TEST_F(IDEGeneralizedLCATest, StringBranchTest) { GroundTruth.push_back( {{EdgeValue("Hello Hello"), EdgeValue("Hello, World")}, - SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), - SrcCodeLocationEntry(11, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - })}); - // TODO: ask Fabian how to reach: - // %1 = load ptr, ptr %str1, align 8, !dbg !40 - // in the if.end branch + SrcCodeLocationEntry(5, 15, HA->getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(10, 3, HA->getProjectIRDB().getFunction("main"))}); GroundTruth.push_back( - {{EdgeValue("Hello, World")}, - SrcCodeLocationEntry(8, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) mutable { - return llvm::isa(Inst); - }), - SrcCodeLocationEntry(11, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - })}); + {{EdgeValue("Hello Hello")}, + SrcCodeLocationEntry(6, 15, HA->getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(10, 3, HA->getProjectIRDB().getFunction("main"))}); compareResults(GroundTruth); } @@ -297,16 +213,10 @@ TEST_F(IDEGeneralizedLCATest, StringTestCpp) { initialize("StringTest_cpp_dbg.ll"); std::vector GroundTruth; - // TODO: ask Fabian, why ReturnInst doesn't work here and how to fix that - // test. GroundTruth.push_back( {{EdgeValue("Hello, World")}, - SrcCodeLocationEntry(4, 0, HA->getProjectIRDB().getFunction("main")), - SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - llvm::outs() << "*Inst" << *Inst << "\n"; - return llvm::isa(Inst); - })}); + SrcCodeLocationEntry(4, 15, HA->getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(6, 1, HA->getProjectIRDB().getFunction("main"))}); compareResults(GroundTruth); } @@ -317,73 +227,16 @@ TEST_F(IDEGeneralizedLCATest, FloatDivisionTest) { GroundTruth.push_back( {{EdgeValue(1.0)}, - SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - llvm::outs() - << "In lambda *Inst: " << *Inst << "\n"; - llvm::outs() << "2.0: In lambda *Inst.getType(): " - << *Inst->getType() << "\n"; - llvm::outs() << "n lambda *Inst.getOpcode(): " - << Inst->getOpcode() << "\n"; - /* Floating-point types are handled by FAdd, FSub - and FMul, instead of Add, Sub and Mul, which - are used by Integer types. - Opcode 18 is operator fptosi */ - // TODO: ask Fabian if the opcode is a valid - // approach to this issue. - return Inst->getOpcode() == 45; - }), - SrcCodeLocationEntry(8, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - llvm::outs() << "*Inst" << *Inst << "\n"; - return llvm::isa(Inst); - })}); + SrcCodeLocationEntry(5, 9, HA->getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(8, 3, HA->getProjectIRDB().getFunction("main"))}); GroundTruth.push_back( {{EdgeValue(nullptr)}, - SrcCodeLocationEntry(6, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - llvm::outs() - << "In lambda *Inst: " << *Inst << "\n"; - llvm::outs() << "In lambda *Inst.getType(): " - << *Inst->getType() << "\n"; - llvm::outs() << "In lambda *Inst.getOpcode(): " - << Inst->getOpcode() << "\n"; - /* Floating-point types are handled by FAdd, FSub - and FMul, instead of Add, Sub and Mul, which - are used by Integer types. - Opcode 18 is operator FMul */ - // TODO: ask Fabian if the opcode is a valid - // approach to this issue. - return Inst->getOpcode() == 18; - }), - SrcCodeLocationEntry(8, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - })}); + SrcCodeLocationEntry(6, 9, HA->getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(8, 3, HA->getProjectIRDB().getFunction("main"))}); GroundTruth.push_back( {{EdgeValue(-7.0)}, - SrcCodeLocationEntry(7, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - llvm::outs() - << "2.0: In lambda *Inst: " << *Inst << "\n"; - llvm::outs() << "2.0: In lambda *Inst.getType(): " - << *Inst->getType() << "\n"; - llvm::outs() - << "2.0: In lambda *Inst.getOpcode(): " - << Inst->getOpcode() << "\n"; - /* Floating-point types are handled by FAdd, FSub - and FMul, instead of Add, Sub and Mul, which - are used by Integer types. - Opcode 16 is operator FSub */ - // TODO: ask Fabian if the opcode is a valid - // approach to this issue. - return Inst->getOpcode() == 16; - }), - SrcCodeLocationEntry(8, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - llvm::outs() << "*Inst" << *Inst << "\n"; - return llvm::isa(Inst); - })}); + SrcCodeLocationEntry(7, 9, HA->getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(8, 3, HA->getProjectIRDB().getFunction("main"))}); compareResults(GroundTruth); } @@ -392,41 +245,14 @@ TEST_F(IDEGeneralizedLCATest, SimpleFunctionTest) { initialize("SimpleFunctionTest_c_dbg.ll"); std::vector GroundTruth; - // TODO: ask Fabian if this impl is fine, or if there is a better way to do - // it. - /* We want the second call inst here: - not this -> %call2 = call i32 @foo(i32 noundef %2), !dbg !42, !psr.id !43 - this -----> %call3 = call i32 @bar(i32 noundef %call2), !dbg !44, !psr.id - !45 - */ - bool FoundFirstCall = false; GroundTruth.push_back( {{EdgeValue(48)}, - SrcCodeLocationEntry( - 8, 0, HA->getProjectIRDB().getFunction("main"), - [&FoundFirstCall](const llvm::Instruction *Inst) mutable { - llvm::outs() << "*Inst: " << *Inst << "\n"; - if (llvm::isa(Inst) && !FoundFirstCall) { - FoundFirstCall = true; - return false; - } - return llvm::isa(Inst); - }), - SrcCodeLocationEntry(10, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - })}); + SrcCodeLocationEntry(8, 7, HA->getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(10, 3, HA->getProjectIRDB().getFunction("main"))}); GroundTruth.push_back( {{EdgeValue(nullptr)}, - SrcCodeLocationEntry(9, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - llvm::outs() << "*Inst: " << *Inst << "\n"; - return llvm::isa(Inst); - }), - SrcCodeLocationEntry(10, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - })}); + SrcCodeLocationEntry(9, 7, HA->getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(10, 3, HA->getProjectIRDB().getFunction("main"))}); compareResults(GroundTruth); } @@ -437,26 +263,12 @@ TEST_F(IDEGeneralizedLCATest, GlobalVariableTest) { GroundTruth.push_back( {{EdgeValue(50)}, - SrcCodeLocationEntry(4, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - llvm::outs() << "*Inst: " << *Inst << "\n"; - return llvm::isa(Inst); - }), - SrcCodeLocationEntry(6, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - })}); + SrcCodeLocationEntry(4, 13, HA->getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(6, 3, HA->getProjectIRDB().getFunction("main"))}); GroundTruth.push_back( {{EdgeValue(8)}, - SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - llvm::outs() << "*Inst: " << *Inst << "\n"; - return llvm::isa(Inst); - }), - SrcCodeLocationEntry(6, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - })}); + SrcCodeLocationEntry(5, 13, HA->getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(6, 3, HA->getProjectIRDB().getFunction("main"))}); compareResults(GroundTruth); } @@ -465,34 +277,14 @@ TEST_F(IDEGeneralizedLCATest, Imprecision) { initialize("Imprecision_c_dbg.ll"); std::vector GroundTruth; - // TODO: ask Fabian how to handle this test. I do not know how to handle that - // source file. I tried the calls in main, line 3 with function foo and line 1 - // with function bar. - GroundTruth.push_back( {{EdgeValue(1), EdgeValue(2)}, - SrcCodeLocationEntry(3, 0, HA->getProjectIRDB().getFunction("foo"), - [](const llvm::Instruction *Inst) { - llvm::outs() << "*Inst: " << *Inst << "\n"; - // return false; - return llvm::isa(Inst); - }), - SrcCodeLocationEntry(8, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - })}); + SrcCodeLocationEntry(3, 14, HA->getProjectIRDB().getFunction("foo")), + SrcCodeLocationEntry(3, 26, HA->getProjectIRDB().getFunction("foo"))}); GroundTruth.push_back( {{EdgeValue(2), EdgeValue(3)}, - SrcCodeLocationEntry(3, 0, HA->getProjectIRDB().getFunction("foo"), - [](const llvm::Instruction *Inst) { - llvm::outs() << "*Inst: " << *Inst << "\n"; - return false; - // return llvm::isa(Inst); - }), - SrcCodeLocationEntry(8, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - })}); + SrcCodeLocationEntry(3, 21, HA->getProjectIRDB().getFunction("foo")), + SrcCodeLocationEntry(3, 26, HA->getProjectIRDB().getFunction("foo"))}); compareResults(GroundTruth); } @@ -503,14 +295,8 @@ TEST_F(IDEGeneralizedLCATest, ReturnConstTest) { GroundTruth.push_back( {{EdgeValue(43)}, - SrcCodeLocationEntry(6, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }), - SrcCodeLocationEntry(6, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - })}); + SrcCodeLocationEntry(6, 12, HA->getProjectIRDB().getFunction("main")), + SrcCodeLocationEntry(6, 3, HA->getProjectIRDB().getFunction("main"))}); compareResults(GroundTruth); } @@ -521,11 +307,8 @@ TEST_F(IDEGeneralizedLCATest, NullTest) { GroundTruth.push_back( {{EdgeValue("")}, - SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main")), - SrcCodeLocationEntry(5, 0, HA->getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - })}); + SrcCodeLocationEntry(1, 31, HA->getProjectIRDB().getFunction("foo")), + SrcCodeLocationEntry(1, 24, HA->getProjectIRDB().getFunction("foo"))}); compareResults(GroundTruth); } diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp index 0b2d4fa52e..e5c80d4d3f 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp @@ -91,7 +91,7 @@ class IDETSAnalysisFileIOTest : public ::testing::Test { }; // 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 = { @@ -102,7 +102,7 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_01) { } 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(); @@ -112,7 +112,7 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_02) { } 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(); @@ -138,7 +138,7 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_03) { } 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(); @@ -160,7 +160,7 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_04) { } 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(); @@ -179,7 +179,7 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_05) { 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(); @@ -214,7 +214,7 @@ TEST_F(IDETSAnalysisFileIOTest, DISABLED_HandleTypeState_06) { } 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(); @@ -246,7 +246,7 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_07) { } 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(); @@ -259,7 +259,7 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_08) { } 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(); @@ -277,7 +277,7 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_09) { } 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(); @@ -299,7 +299,7 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_10) { } 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(); @@ -326,7 +326,7 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_11) { } 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(); @@ -346,7 +346,7 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_12) { } 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(); @@ -361,7 +361,7 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_13) { } 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(); @@ -384,7 +384,7 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_14) { } 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(); @@ -446,7 +446,7 @@ 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(); @@ -483,7 +483,7 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_16) { // 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(); @@ -514,7 +514,7 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_17) { 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(); @@ -536,7 +536,7 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_18) { // 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(); diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp index be98776390..49a0407661 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp @@ -268,19 +268,11 @@ TEST_F(IFDSConstAnalysisTest, HandleGlobalTest_03) { IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - const llvm::Instruction *CorrectCall = - &(HA->getProjectIRDB() - .getFunction("__cxx_global_var_init") - ->getBasicBlockList() - .front() - .getInstList() - .front()); + // SrcCodeLocationEntry Entry( + // 1, 0, HA->getProjectIRDB().getGlobalVariableDefinition("g")); + // SrcCodeLocationEntry EntryTwo(0, 0, ); - SrcCodeLocationEntry Entry( - 1, 0, HA->getProjectIRDB().getGlobalVariableDefinition("g")); - SrcCodeLocationEntry EntryTwo(0, 0, CorrectCall); - - std::set GroundTruth{Entry, EntryTwo}; + std::set GroundTruth{}; //{Entry, EntryTwo}; compareResults(GroundTruth, Llvmconstsolver); } diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp index 620752c1eb..0181f6cd9d 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp @@ -92,8 +92,7 @@ class IFDSTaintAnalysisTest : public ::testing::Test { static void doAnalysis( const llvm::Twine &IRFile, const LLVMTaintConfig &Config, const std::set> - &GroundTruth, - const llvm::StringRef FuncName) { + &GroundTruth) { HelperAnalyses HA(PathToLlFiles + IRFile, EntryPoints); auto TaintProblem = @@ -107,14 +106,6 @@ class IFDSTaintAnalysisTest : public ::testing::Test { compare(TaintProblem.Leaks, GroundTruth); } - static void doAnalysis( - const llvm::Twine &IRFile, - const std::set> - &GroundTruth, - const llvm::StringRef FuncName) { - doAnalysis(IRFile, getDefaultConfig(), GroundTruth, FuncName); - } - template static void compare(const LeaksTy &Leaks, @@ -152,12 +143,14 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_01) { initialize({PathToLlFiles + "dummy_source_sink/taint_01_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); + SrcCodeLocationEntry Entry = SrcCodeLocationEntry(6, 3, HA->getProjectIRDB().getFunction("main")); SrcCodeLocationEntry EntryTwo = SrcCodeLocationEntry(6, 8, HA->getProjectIRDB().getFunction("main")); - std::set> GroundTruth; - GroundTruth.insert({Entry, EntryTwo}); + std::set> GroundTruth{ + {Entry, EntryTwo}}; + compareResults(GroundTruth); } @@ -165,12 +158,12 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_01_m2r) { initialize({PathToLlFiles + "dummy_source_sink/taint_01_cpp_m2r_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(12, 3, HA->getProjectIRDB().getFunction("main")); - SrcCodeLocationEntry EntryTwo(12, 14, - HA->getProjectIRDB().getFunction("main")); - std::set> GroundTruth; - GroundTruth.insert({Entry, EntryTwo}); + SrcCodeLocationEntry Entry(6, 3, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(5, 11, + HA->getProjectIRDB().getFunction("main")); + std::set> GroundTruth{ + {Entry, EntryTwo}}; compareResults(GroundTruth); } @@ -179,11 +172,12 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_02) { initialize({PathToLlFiles + "dummy_source_sink/taint_02_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); + SrcCodeLocationEntry Entry(5, 3, HA->getProjectIRDB().getFunction("main")); SrcCodeLocationEntry EntryTwo(5, 8, HA->getProjectIRDB().getFunction("main")); + std::set> GroundTruth{ + {Entry, EntryTwo}}; - std::set> GroundTruth; - GroundTruth.insert({Entry, EntryTwo}); compareResults(GroundTruth); } @@ -191,11 +185,12 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_03) { initialize({PathToLlFiles + "dummy_source_sink/taint_03_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); + SrcCodeLocationEntry Entry(6, 3, HA->getProjectIRDB().getFunction("main")); SrcCodeLocationEntry EntryTwo(6, 8, HA->getProjectIRDB().getFunction("main")); + std::set> GroundTruth{ + {Entry, EntryTwo}}; - std::set> GroundTruth; - GroundTruth.insert({Entry, EntryTwo}); compareResults(GroundTruth); } @@ -203,15 +198,16 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_04) { initialize({PathToLlFiles + "dummy_source_sink/taint_04_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); + SrcCodeLocationEntry Entry(6, 3, HA->getProjectIRDB().getFunction("main")); SrcCodeLocationEntry EntryTwo(6, 8, HA->getProjectIRDB().getFunction("main")); SrcCodeLocationEntry EntryThree(8, 3, HA->getProjectIRDB().getFunction("main")); SrcCodeLocationEntry EntryFour(8, 8, HA->getProjectIRDB().getFunction("main")); + std::set> GroundTruth{ + {Entry, EntryTwo}, {EntryThree, EntryFour}}; - std::set> GroundTruth; - GroundTruth.insert({{Entry, EntryTwo}, {EntryThree, EntryFour}}); compareResults(GroundTruth); } @@ -219,39 +215,42 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_05) { initialize({PathToLlFiles + "dummy_source_sink/taint_05_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); + SrcCodeLocationEntry Entry(6, 3, HA->getProjectIRDB().getFunction("main")); SrcCodeLocationEntry EntryTwo(6, 8, HA->getProjectIRDB().getFunction("main")); + std::set> GroundTruth{ + {Entry, EntryTwo}}; - std::set> GroundTruth; - GroundTruth.insert({Entry, EntryTwo}); compareResults(GroundTruth); } -// TODO: Fabian fragen, wie man mit Ground Truth von "main.0" hier umgehen soll. -#if false - 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"}; + // map> GroundTruth; + // GroundTruth[5] = set{"main.0"}; + + SrcCodeLocationEntry Entry(13, 5, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(0, 0, HA->getProjectIRDB().getFunction("main")); + std::set> GroundTruth{ + {Entry, EntryTwo}}; + compareResults(GroundTruth); } -#endif - TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_01) { initialize( {PathToLlFiles + "dummy_source_sink/taint_exception_01_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); + SrcCodeLocationEntry Entry(12, 3, HA->getProjectIRDB().getFunction("main")); SrcCodeLocationEntry EntryTwo(12, 8, HA->getProjectIRDB().getFunction("main")); + std::set> GroundTruth{ + {Entry, EntryTwo}}; - std::set> GroundTruth; - GroundTruth.insert({Entry, EntryTwo}); compareResults(GroundTruth); } @@ -260,12 +259,13 @@ 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(); + SrcCodeLocationEntry Entry(12, 3, HA->getProjectIRDB().getFunction("main")); - SrcCodeLocationEntry EntryTwo(12, 14, + SrcCodeLocationEntry EntryTwo(10, 14, HA->getProjectIRDB().getFunction("main")); + std::set> GroundTruth{ + {Entry, EntryTwo}}; - std::set> GroundTruth; - GroundTruth.insert({Entry, EntryTwo}); compareResults(GroundTruth); } @@ -274,12 +274,13 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_02) { {PathToLlFiles + "dummy_source_sink/taint_exception_02_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); + SrcCodeLocationEntry Entry(11, 3, HA->getProjectIRDB().getFunction("main")); SrcCodeLocationEntry EntryTwo(11, 8, HA->getProjectIRDB().getFunction("main")); + std::set> GroundTruth{ + {Entry, EntryTwo}}; - std::set> GroundTruth; - GroundTruth.insert({Entry, EntryTwo}); compareResults(GroundTruth); } @@ -288,12 +289,17 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_03) { {PathToLlFiles + "dummy_source_sink/taint_exception_03_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(14, 3, HA->getProjectIRDB().getFunction("main")); - SrcCodeLocationEntry EntryTwo(14, 8, + + SrcCodeLocationEntry Entry(11, 3, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(11, 8, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryThree(14, 3, + HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryFour(14, 8, + HA->getProjectIRDB().getFunction("main")); + std::set> GroundTruth{ + {Entry, EntryTwo}, {EntryThree, EntryFour}}; - std::set> GroundTruth; - GroundTruth.insert({Entry, EntryTwo}); compareResults(GroundTruth); } @@ -302,12 +308,13 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_04) { {PathToLlFiles + "dummy_source_sink/taint_exception_04_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); + SrcCodeLocationEntry Entry(16, 3, HA->getProjectIRDB().getFunction("main")); SrcCodeLocationEntry EntryTwo(16, 8, HA->getProjectIRDB().getFunction("main")); + std::set> GroundTruth{ + {Entry, EntryTwo}}; - std::set> GroundTruth; - GroundTruth.insert({Entry, EntryTwo}); compareResults(GroundTruth); } @@ -316,12 +323,13 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_05) { {PathToLlFiles + "dummy_source_sink/taint_exception_05_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); + SrcCodeLocationEntry Entry(16, 3, HA->getProjectIRDB().getFunction("main")); SrcCodeLocationEntry EntryTwo(16, 8, HA->getProjectIRDB().getFunction("main")); + std::set> GroundTruth{ + {Entry, EntryTwo}}; - std::set> GroundTruth; - GroundTruth.insert({Entry, EntryTwo}); compareResults(GroundTruth); } @@ -330,12 +338,13 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_06) { {PathToLlFiles + "dummy_source_sink/taint_exception_06_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(13, 3, HA->getProjectIRDB().getFunction("main")); - SrcCodeLocationEntry EntryTwo(13, 8, + + SrcCodeLocationEntry Entry(13, 5, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(13, 10, HA->getProjectIRDB().getFunction("main")); + std::set> GroundTruth{ + {Entry, EntryTwo}}; - std::set> GroundTruth; - GroundTruth.insert({Entry, EntryTwo}); compareResults(GroundTruth); } @@ -344,12 +353,13 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_07) { {PathToLlFiles + "dummy_source_sink/taint_exception_07_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(14, 3, HA->getProjectIRDB().getFunction("main")); - SrcCodeLocationEntry EntryTwo(14, 8, + + SrcCodeLocationEntry Entry(14, 5, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(14, 10, HA->getProjectIRDB().getFunction("main")); + std::set> GroundTruth{ + {Entry, EntryTwo}}; - std::set> GroundTruth; - GroundTruth.insert({Entry, EntryTwo}); compareResults(GroundTruth); } @@ -358,12 +368,13 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_08) { {PathToLlFiles + "dummy_source_sink/taint_exception_08_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); + SrcCodeLocationEntry Entry(19, 3, HA->getProjectIRDB().getFunction("main")); SrcCodeLocationEntry EntryTwo(19, 8, HA->getProjectIRDB().getFunction("main")); + std::set> GroundTruth{ + {Entry, EntryTwo}}; - std::set> GroundTruth; - GroundTruth.insert({Entry, EntryTwo}); compareResults(GroundTruth); } @@ -372,12 +383,13 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_09) { {PathToLlFiles + "dummy_source_sink/taint_exception_09_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); + SrcCodeLocationEntry Entry(20, 3, HA->getProjectIRDB().getFunction("main")); SrcCodeLocationEntry EntryTwo(20, 8, HA->getProjectIRDB().getFunction("main")); + std::set> GroundTruth{ + {Entry, EntryTwo}}; - std::set> GroundTruth; - GroundTruth.insert({Entry, EntryTwo}); compareResults(GroundTruth); } @@ -386,43 +398,48 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_10) { {PathToLlFiles + "dummy_source_sink/taint_exception_10_cpp_dbg.ll"}); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); - SrcCodeLocationEntry Entry(19, 3, HA->getProjectIRDB().getFunction("main")); - SrcCodeLocationEntry EntryTwo(19, 8, + + SrcCodeLocationEntry Entry(19, 5, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(19, 10, HA->getProjectIRDB().getFunction("main")); + std::set> GroundTruth{ + {Entry, EntryTwo}}; - std::set> GroundTruth; - GroundTruth.insert({Entry, EntryTwo}); compareResults(GroundTruth); } -// TODO: fix seg fault -#if false - -TEST_F(IFDSTaintAnalysisTest, TaintTest_DoubleFree_01) { - doAnalysis("double_free_01_c.ll", getDoubleFreeConfig(), - { - {6, {5}}, - }); -} - - -TEST_F(IFDSTaintAnalysisTest, TaintTest_DoubleFree_02) { - doAnalysis("double_free_02_c.ll", getDoubleFreeConfig(), - { - {11, {"10"}}, - }); -} - 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"}; + + SrcCodeLocationEntry Entry(8, 3, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(8, 8, HA->getProjectIRDB().getFunction("main"), + [](const llvm::Instruction *Inst) { + return Inst->getOpcode() == + llvm::Instruction::FPToSI; + }); + std::set> GroundTruth{ + {Entry, EntryTwo}}; + compareResults(GroundTruth); } -#endif +TEST_F(IFDSTaintAnalysisTest, TaintTest_DoubleFree_01) { + SrcCodeLocationEntry Entry(5, 3, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(6, 3, HA->getProjectIRDB().getFunction("main")); + std::set> GroundTruth{ + {Entry, EntryTwo}}; + doAnalysis("double_free_01_c_dbg.ll", getDoubleFreeConfig(), GroundTruth); +} + +TEST_F(IFDSTaintAnalysisTest, TaintTest_DoubleFree_02) { + SrcCodeLocationEntry Entry(5, 3, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(8, 3, HA->getProjectIRDB().getFunction("main")); + std::set> GroundTruth{ + {Entry, EntryTwo}}; + doAnalysis("double_free_02_c_dbg.ll", getDoubleFreeConfig(), GroundTruth); +} int main(int Argc, char **Argv) { ::testing::InitGoogleTest(&Argc, Argv); diff --git a/unittests/Utils/AnalysisPrinterTest.cpp b/unittests/Utils/AnalysisPrinterTest.cpp index 546c9d3049..197cdc5334 100644 --- a/unittests/Utils/AnalysisPrinterTest.cpp +++ b/unittests/Utils/AnalysisPrinterTest.cpp @@ -30,7 +30,7 @@ class GroundTruthCollector public: // constructor init Groundtruth in each fixture GroundTruthCollector(llvm::DenseMap> &GroundTruth) - : GroundTruth(GroundTruth){}; + : GroundTruth(GroundTruth) {}; void findAndRemove(llvm::DenseMap> &Map1, llvm::DenseMap> &Map2) { @@ -122,7 +122,7 @@ TEST_F(AnalysisPrinterTest, XTaint01) { GroundTruth[13] = {"7"}; GroundTruthCollector GroundTruthPrinter = {GroundTruth}; - doAnalysisTest("xtaint01_cpp.ll", GroundTruthPrinter, std::monostate{}); + doAnalysisTest("xtaint01_cpp_dbg.ll", GroundTruthPrinter, std::monostate{}); } // main function for the test case From 99b582b2b90521a54a56ee3fcabf3eded0af25a2 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Fri, 25 Jul 2025 12:23:33 +0200 Subject: [PATCH 16/35] Fixed IFDSConstAnalysisTest --- include/phasar/Utils/SrcCodeLocationEntry.h | 2 +- .../Problems/IFDSConstAnalysisTest.cpp | 13 ++--- .../Problems/IFDSTaintAnalysisTest.cpp | 50 +++++++++++-------- 3 files changed, 35 insertions(+), 30 deletions(-) diff --git a/include/phasar/Utils/SrcCodeLocationEntry.h b/include/phasar/Utils/SrcCodeLocationEntry.h index 17b22a6ae7..8035c1296d 100644 --- a/include/phasar/Utils/SrcCodeLocationEntry.h +++ b/include/phasar/Utils/SrcCodeLocationEntry.h @@ -329,7 +329,7 @@ getGroundTruthValues(const std::set &GroundTruth) { llvm::errs() << "getInstAtOrNull returned null\n"; llvm::errs() << "Entry.Line: " << Entry.Line << "\n"; llvm::errs() << "Entry.Column: " << Entry.Column << "\n"; - llvm::errs() << "*Func: " << *Func << "\n"; + llvm::errs() << "*Func: " << **Func << "\n"; } continue; diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp index 49a0407661..573f5eb0fc 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp @@ -268,11 +268,12 @@ TEST_F(IFDSConstAnalysisTest, HandleGlobalTest_03) { IFDSSolver Llvmconstsolver(*Constproblem, &HA->getICFG()); Llvmconstsolver.solve(); - // SrcCodeLocationEntry Entry( - // 1, 0, HA->getProjectIRDB().getGlobalVariableDefinition("g")); - // SrcCodeLocationEntry EntryTwo(0, 0, ); + SrcCodeLocationEntry Entry( + 6, 10, HA->getProjectIRDB().getFunction("__cxx_global_var_init")); + SrcCodeLocationEntry EntryTwo( + 0, 0, HA->getProjectIRDB().getGlobalVariableDefinition("g")); - std::set GroundTruth{}; //{Entry, EntryTwo}; + std::set GroundTruth{Entry, EntryTwo}; compareResults(GroundTruth, Llvmconstsolver); } @@ -542,8 +543,6 @@ TEST_F(IFDSConstAnalysisTest, DISABLED_HandleCStringTest_02) { compareResults(GroundTruth, Llvmconstsolver); } -#if false - /* ============== STRUCTURE TESTS ============== */ // TEST_F(IFDSConstAnalysisTest, HandleStructureTest_01) { // Initialize({pathToLLFiles + "structs/structs_01_cpp_dbg.ll"}); @@ -653,8 +652,6 @@ TEST_F(IFDSConstAnalysisTest, DISABLED_HandleCStringTest_02) { // compareResults({0}, llvmconstsolver); //} -#endif - // main function for the test case int main(int Argc, char **Argv) { ::testing::InitGoogleTest(&Argc, Argv); diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp index 0181f6cd9d..0884ad50c8 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp @@ -86,24 +86,15 @@ 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 std::set> - &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); } template @@ -113,6 +104,11 @@ class IFDSTaintAnalysisTest : public ::testing::Test { &GroundTruth) { auto GroundTruthEntries = getGroundTruthInsts(GroundTruth); + for (const auto &Entry : GroundTruthEntries) { + llvm::outs() << "First Entry: " << *(std::get<0>(Entry)) << "\n"; + llvm::outs() << "Second Entry: " << *(std::get<1>(Entry)) << "\n"; + } + std::set> FoundLeaks; for (const auto &Leak : Leaks) { @@ -232,7 +228,7 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_06) { // GroundTruth[5] = set{"main.0"}; SrcCodeLocationEntry Entry(13, 5, HA->getProjectIRDB().getFunction("main")); - SrcCodeLocationEntry EntryTwo(0, 0, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(0, 1, HA->getProjectIRDB().getFunction("main")); std::set> GroundTruth{ {Entry, EntryTwo}}; @@ -426,19 +422,31 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_LibSummary_01) { } TEST_F(IFDSTaintAnalysisTest, TaintTest_DoubleFree_01) { - SrcCodeLocationEntry Entry(5, 3, HA->getProjectIRDB().getFunction("main")); - SrcCodeLocationEntry EntryTwo(6, 3, HA->getProjectIRDB().getFunction("main")); + initialize({PathToLlFiles + "double_free_01_c_dbg.ll"}, + getDoubleFreeConfig()); + IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); + TaintSolver.solve(); + + SrcCodeLocationEntry Entry(6, 3, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(6, 8, HA->getProjectIRDB().getFunction("main")); std::set> GroundTruth{ {Entry, EntryTwo}}; - doAnalysis("double_free_01_c_dbg.ll", getDoubleFreeConfig(), GroundTruth); + + compareResults(GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_DoubleFree_02) { - SrcCodeLocationEntry Entry(5, 3, HA->getProjectIRDB().getFunction("main")); - SrcCodeLocationEntry EntryTwo(8, 3, HA->getProjectIRDB().getFunction("main")); + initialize({PathToLlFiles + "double_free_02_c_dbg.ll"}, + getDoubleFreeConfig()); + IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); + TaintSolver.solve(); + + SrcCodeLocationEntry Entry(8, 3, HA->getProjectIRDB().getFunction("main")); + SrcCodeLocationEntry EntryTwo(8, 8, HA->getProjectIRDB().getFunction("main")); std::set> GroundTruth{ {Entry, EntryTwo}}; - doAnalysis("double_free_02_c_dbg.ll", getDoubleFreeConfig(), GroundTruth); + + compareResults(GroundTruth); } int main(int Argc, char **Argv) { From 5c6d82c0768c7d20ee099ac4bb3b998158fa5d0d Mon Sep 17 00:00:00 2001 From: mxHuber Date: Fri, 25 Jul 2025 22:37:39 +0200 Subject: [PATCH 17/35] fixed tainttest and segfaults + refactoring --- include/phasar/Utils/SrcCodeLocationEntry.h | 115 ++++++++++-------- .../Problems/IDEExtendedTaintAnalysisTest.cpp | 8 +- .../Problems/IFDSTaintAnalysisTest.cpp | 97 +++++++++------ .../DataFlow/IfdsIde/SparseIDESolverTest.cpp | 4 +- .../Pointer/FilteredLLVMAliasSetTest.cpp | 4 +- 5 files changed, 131 insertions(+), 97 deletions(-) diff --git a/include/phasar/Utils/SrcCodeLocationEntry.h b/include/phasar/Utils/SrcCodeLocationEntry.h index 8035c1296d..98d3fa15b2 100644 --- a/include/phasar/Utils/SrcCodeLocationEntry.h +++ b/include/phasar/Utils/SrcCodeLocationEntry.h @@ -172,10 +172,6 @@ convertTestingLocationSetInIR( } struct SrcCodeLocationEntry { - // TODO: the const llvm::Instruction * variant is not good, as it basically - // completely ignores the line and column aspect of the source file. We want - // to tie the unittest to the source file, but for very specific cases, this - // variant was the only way I found to make the unittests run. SrcCodeLocationEntry( uint32_t Line, uint32_t Column, std::variant @@ -201,6 +197,66 @@ struct SrcCodeLocationEntry { } }; +inline const llvm::Instruction * +getGroundTruthInst(const SrcCodeLocationEntry &Entry) { + if (const auto *GlobalVar = + std::get_if(&Entry.Context)) { + return llvm::dyn_cast_or_null(*GlobalVar); + } + + if (const auto *Func = std::get_if(&Entry.Context)) { + if (Entry.LambdaFunc) { + return unittest::getInstAtOrNull(*Func, Entry.Line, Entry.Column, + Entry.LambdaFunc); + } + + return unittest::getInstAtOrNull(*Func, Entry.Line, Entry.Column); + } + + llvm::report_fatal_error("Unknown variant type.\n"); +} + +inline const llvm::Instruction * +getInstFromEntryOrNull(const SrcCodeLocationEntry &Entry) { + if (const auto *GlobalVar = + std::get_if(&Entry.Context)) { + return llvm::dyn_cast_or_null(*GlobalVar); + } + + if (const auto *Func = std::get_if(&Entry.Context)) { + if (Entry.LambdaFunc) { + return unittest::getInstAtOrNull(*Func, Entry.Line, Entry.Column, + Entry.LambdaFunc); + } + return unittest::getInstAtOrNull(*Func, Entry.Line, Entry.Column); + } + + llvm::report_fatal_error("Unknown variant type.\n"); +} + +inline const llvm::Value * +getValueFromEntryOrNull(const SrcCodeLocationEntry &Entry) { + if (const auto *GlobalVar = + std::get_if(&Entry.Context)) { + return llvm::dyn_cast_or_null(*GlobalVar); + } + + if (const auto *Func = std::get_if(&Entry.Context)) { + if (Entry.LambdaFunc) { + if (const auto *Inst = unittest::getInstAtOrNull( + *Func, Entry.Line, Entry.Column, Entry.LambdaFunc)) { + return llvm::dyn_cast_or_null(Inst); + } + } + if (const auto *Inst = + unittest::getInstAtOrNull(*Func, Entry.Line, Entry.Column)) { + return llvm::dyn_cast_or_null(Inst); + } + } + + llvm::report_fatal_error("Unknown variant type.\n"); +} + inline std::set> getGroundTruthInsts( const std::set> @@ -211,55 +267,18 @@ getGroundTruthInsts( for (const auto &Entry : GroundTruth) { const auto &FirstEntry = std::get<0>(Entry); const auto &SecondEntry = std::get<1>(Entry); - const llvm::Instruction *CurrInst = nullptr; - const llvm::Value *CurrVal = nullptr; - - if (std::get_if(&FirstEntry.Context)) { - llvm::report_fatal_error("Cannot cast global variable to Instruction\n"); - } + const llvm::Instruction *CurrInst = getInstFromEntryOrNull(FirstEntry); + const llvm::Value *CurrVal = getValueFromEntryOrNull(SecondEntry); - if (const auto *Func = - std::get_if(&FirstEntry.Context)) { - if (FirstEntry.LambdaFunc) { - CurrInst = unittest::getInstAtOrNull( - *Func, FirstEntry.Line, FirstEntry.Column, FirstEntry.LambdaFunc); - } else { - CurrInst = unittest::getInstAtOrNull(*Func, FirstEntry.Line, - FirstEntry.Column); - } - } else { - llvm::report_fatal_error("Unknown variant type.\n"); + if (!CurrInst) { + continue; } - if (const auto *GlobalVar = - std::get_if(&SecondEntry.Context)) { - CurrVal = llvm::cast(*GlobalVar); - } else if (const auto *Func = - std::get_if(&FirstEntry.Context)) { - const llvm::Instruction *AsInst = nullptr; - if (SecondEntry.LambdaFunc) { - AsInst = unittest::getInstAtOrNull(*Func, SecondEntry.Line, - SecondEntry.Column, - SecondEntry.LambdaFunc); - } else { - AsInst = unittest::getInstAtOrNull(*Func, SecondEntry.Line, - SecondEntry.Column); - } - if (const auto *CanBeCastToValue = - llvm::dyn_cast_or_null(AsInst)) { - CurrVal = CanBeCastToValue; - } else { - llvm::errs() << "AsInst Instruction couldn't be cast to value.\n"; - } - } else { - llvm::report_fatal_error("Unknown variant type.\n"); + if (!CurrVal) { + continue; } - if (CurrInst) { - if (CurrVal) { - GroundTruthEntries.insert({CurrInst, CurrVal}); - } - } + GroundTruthEntries.insert({CurrInst, CurrVal}); } return GroundTruthEntries; diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp index 61c54d70b4..0ec383c0af 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp @@ -401,13 +401,7 @@ TEST_F(IDETaintAnalysisTest, XTaint18) { HelperAnalyses HA({PathToLLFiles + "xtaint18_cpp_dbg.ll"}, EntryPoints); std::set> GroundTruth; - // TODO: ask Fabian why there are no leaks found for this test - // I added a random GT, so that the test fails and it won't be overlooked. - GroundTruth.insert( - {SrcCodeLocationEntry(8, 10, HA.getProjectIRDB().getFunction("main")), - SrcCodeLocationEntry(8, 14, HA.getProjectIRDB().getFunction("main"))}); - - doAnalysis(HA, GroundTruth, std::monostate{}, true); + doAnalysis(HA, {}, std::monostate{}, true); } PHASAR_SKIP_TEST(TEST_F(IDETaintAnalysisTest, XTaint19) { diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp index 0884ad50c8..60b1b28d74 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp @@ -16,6 +16,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instruction.h" +#include "llvm/IR/Value.h" #include "SourceMapping.h" #include "TestConfig.h" @@ -103,35 +104,55 @@ class IFDSTaintAnalysisTest : public ::testing::Test { const std::set> &GroundTruth) { auto GroundTruthEntries = getGroundTruthInsts(GroundTruth); + std::set> + FoundLeaks; - for (const auto &Entry : GroundTruthEntries) { - llvm::outs() << "First Entry: " << *(std::get<0>(Entry)) << "\n"; - llvm::outs() << "Second Entry: " << *(std::get<1>(Entry)) << "\n"; + for (const auto &Leak : Leaks) { + if (const auto *SinkInst = + llvm::dyn_cast_or_null(Leak.first)) { + for (const auto *LV : Leak.second) { + if (LV) { + if (const auto *LVValue = llvm::dyn_cast_or_null(LV)) { + FoundLeaks.insert({SinkInst, {LVValue}}); + } + } + } + } + } + + EXPECT_EQ(FoundLeaks, GroundTruthEntries); + } + + template + static void + compare(const LeaksTy &Leaks, + const std::set> + &GroundTruth) { + std::set> + GroundTruthEntries; + + for (const auto &Entry : GroundTruth) { + GroundTruthEntries.insert( + {getGroundTruthInst(std::get<0>(Entry)), std::get<1>(Entry)}); } std::set> FoundLeaks; + for (const auto &Leak : Leaks) { if (const auto *SinkInst = llvm::dyn_cast_or_null(Leak.first)) { - llvm::outs() << "*SinkInst: " << *SinkInst << "\n"; for (const auto *LV : Leak.second) { if (LV) { if (const auto *LVValue = llvm::dyn_cast_or_null(LV)) { - llvm::outs() << "*LVValue: " << *LVValue << "\n"; FoundLeaks.insert({SinkInst, {LVValue}}); } } } } } - EXPECT_EQ(FoundLeaks, GroundTruthEntries); - } - void compareResults( - const std::set> - &GroundTruth) noexcept { - compare(TaintProblem->Leaks, GroundTruth); + EXPECT_EQ(FoundLeaks, GroundTruthEntries); } }; // Test Fixture @@ -147,7 +168,7 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_01) { std::set> GroundTruth{ {Entry, EntryTwo}}; - compareResults(GroundTruth); + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_01_m2r) { @@ -161,7 +182,7 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_01_m2r) { std::set> GroundTruth{ {Entry, EntryTwo}}; - compareResults(GroundTruth); + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_02) { @@ -174,7 +195,7 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_02) { std::set> GroundTruth{ {Entry, EntryTwo}}; - compareResults(GroundTruth); + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_03) { @@ -187,7 +208,7 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_03) { std::set> GroundTruth{ {Entry, EntryTwo}}; - compareResults(GroundTruth); + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_04) { @@ -204,7 +225,7 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_04) { std::set> GroundTruth{ {Entry, EntryTwo}, {EntryThree, EntryFour}}; - compareResults(GroundTruth); + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_05) { @@ -217,22 +238,22 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_05) { std::set> GroundTruth{ {Entry, EntryTwo}}; - compareResults(GroundTruth); + 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"}; - SrcCodeLocationEntry Entry(13, 5, HA->getProjectIRDB().getFunction("main")); - SrcCodeLocationEntry EntryTwo(0, 1, HA->getProjectIRDB().getFunction("main")); - std::set> GroundTruth{ - {Entry, EntryTwo}}; + const auto &IRDB = HA->getProjectIRDB(); + SrcCodeLocationEntry Entry(5, 3, IRDB.getFunction("main")); + const auto *ArgValue = + testingLocInIR({ArgNo{0}}, IRDB, IRDB.getFunction("main")); + std::set> GroundTruth{ + {Entry, ArgValue}}; - compareResults(GroundTruth); + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_01) { @@ -247,7 +268,7 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_01) { std::set> GroundTruth{ {Entry, EntryTwo}}; - compareResults(GroundTruth); + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_01_m2r) { @@ -262,7 +283,7 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_01_m2r) { std::set> GroundTruth{ {Entry, EntryTwo}}; - compareResults(GroundTruth); + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_02) { @@ -277,7 +298,7 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_02) { std::set> GroundTruth{ {Entry, EntryTwo}}; - compareResults(GroundTruth); + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_03) { @@ -296,7 +317,7 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_03) { std::set> GroundTruth{ {Entry, EntryTwo}, {EntryThree, EntryFour}}; - compareResults(GroundTruth); + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_04) { @@ -311,7 +332,7 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_04) { std::set> GroundTruth{ {Entry, EntryTwo}}; - compareResults(GroundTruth); + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_05) { @@ -326,7 +347,7 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_05) { std::set> GroundTruth{ {Entry, EntryTwo}}; - compareResults(GroundTruth); + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_06) { @@ -341,7 +362,7 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_06) { std::set> GroundTruth{ {Entry, EntryTwo}}; - compareResults(GroundTruth); + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_07) { @@ -356,7 +377,7 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_07) { std::set> GroundTruth{ {Entry, EntryTwo}}; - compareResults(GroundTruth); + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_08) { @@ -371,7 +392,7 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_08) { std::set> GroundTruth{ {Entry, EntryTwo}}; - compareResults(GroundTruth); + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_09) { @@ -386,7 +407,7 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_09) { std::set> GroundTruth{ {Entry, EntryTwo}}; - compareResults(GroundTruth); + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_10) { @@ -401,7 +422,7 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_ExceptionHandling_10) { std::set> GroundTruth{ {Entry, EntryTwo}}; - compareResults(GroundTruth); + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_LibSummary_01) { @@ -418,7 +439,7 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_LibSummary_01) { std::set> GroundTruth{ {Entry, EntryTwo}}; - compareResults(GroundTruth); + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_DoubleFree_01) { @@ -432,7 +453,7 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_DoubleFree_01) { std::set> GroundTruth{ {Entry, EntryTwo}}; - compareResults(GroundTruth); + compare(TaintProblem->Leaks, GroundTruth); } TEST_F(IFDSTaintAnalysisTest, TaintTest_DoubleFree_02) { @@ -446,7 +467,7 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_DoubleFree_02) { std::set> GroundTruth{ {Entry, EntryTwo}}; - compareResults(GroundTruth); + compare(TaintProblem->Leaks, GroundTruth); } int main(int Argc, char **Argv) { 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, From a66046839eacfe05179672cd0a3c78942087ae7e Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Mon, 4 Aug 2025 18:21:17 +0200 Subject: [PATCH 18/35] Fix AnalysisPrinterTest --- unittests/Utils/AnalysisPrinterTest.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/unittests/Utils/AnalysisPrinterTest.cpp b/unittests/Utils/AnalysisPrinterTest.cpp index 197cdc5334..a267d8dd81 100644 --- a/unittests/Utils/AnalysisPrinterTest.cpp +++ b/unittests/Utils/AnalysisPrinterTest.cpp @@ -12,6 +12,8 @@ #include "phasar/Utils/DefaultAnalysisPrinter.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/raw_ostream.h" #include "TestConfig.h" #include "gtest/gtest.h" @@ -54,7 +56,24 @@ class GroundTruthCollector findAndRemove(FoundLeak, GroundTruth); } - void doOnFinalize() override { EXPECT_TRUE(GroundTruth.empty()); } + std::string printGroundTruth() { + std::string Ret; + llvm::raw_string_ostream OS(Ret); + OS << "{\n"; + for (const auto &[Inst, Facts] : GroundTruth) { + OS << " " << Inst << ": { "; + llvm::interleaveComma(Facts, OS); + OS << " },\n"; + } + OS << "}\n"; + + return Ret; + } + + void doOnFinalize() override { + EXPECT_TRUE(GroundTruth.empty()) + << "Elements of GroundTruth not found: " << printGroundTruth(); + } llvm::DenseMap> GroundTruth{}; }; @@ -120,7 +139,7 @@ TEST_F(AnalysisPrinterTest, HandleBasicTest_01) { TEST_F(AnalysisPrinterTest, XTaint01) { llvm::DenseMap> GroundTruth; - GroundTruth[13] = {"7"}; + GroundTruth[16] = {"8"}; GroundTruthCollector GroundTruthPrinter = {GroundTruth}; doAnalysisTest("xtaint01_cpp_dbg.ll", GroundTruthPrinter, std::monostate{}); } From 66fbc0220a07fb25a67eff9800911492c1441e32 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Mon, 4 Aug 2025 18:53:50 +0200 Subject: [PATCH 19/35] Convert AnalysisPrinterTest to src-code-based ground-truth --- .../Problems/IDEExtendedTaintAnalysisTest.cpp | 2 +- .../Problems/IDEGeneralizedLCATest.cpp | 2 +- .../Problems/IFDSConstAnalysisTest.cpp | 2 +- .../Problems/IFDSTaintAnalysisTest.cpp | 2 +- .../IFDSUninitializedVariablesTest.cpp | 2 +- .../TestUtils}/SrcCodeLocationEntry.h | 17 +++++ unittests/Utils/AnalysisPrinterTest.cpp | 71 ++++++++++--------- 7 files changed, 58 insertions(+), 40 deletions(-) rename {include/phasar/Utils => unittests/TestUtils}/SrcCodeLocationEntry.h (94%) diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp index 0ec383c0af..3348fb62b5 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp @@ -20,7 +20,6 @@ #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "phasar/Utils/DebugOutput.h" -#include "phasar/Utils/SrcCodeLocationEntry.h" #include "phasar/Utils/Utilities.h" #include "llvm/ADT/DenseSet.h" @@ -35,6 +34,7 @@ #include "llvm/Support/Casting.h" #include "SourceMapping.h" +#include "SrcCodeLocationEntry.h" #include "TestConfig.h" #include "gtest/gtest.h" #include "nlohmann/json.hpp" diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp index a5e64ef1d4..96ecafe30e 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEGeneralizedLCATest.cpp @@ -19,7 +19,6 @@ #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "phasar/Utils/Logger.h" -#include "phasar/Utils/SrcCodeLocationEntry.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instruction.h" @@ -28,6 +27,7 @@ #include "llvm/Support/raw_ostream.h" #include "SourceMapping.h" +#include "SrcCodeLocationEntry.h" #include "TestConfig.h" #include "gtest/gtest.h" diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp index 573f5eb0fc..0760511c32 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSConstAnalysisTest.cpp @@ -10,13 +10,13 @@ #include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" -#include "phasar/Utils/SrcCodeLocationEntry.h" #include "llvm/ADT/StringRef.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" diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp index 60b1b28d74..6348e8c58a 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp @@ -11,7 +11,6 @@ #include "phasar/PhasarLLVM/TaintConfig/LLVMTaintConfig.h" #include "phasar/PhasarLLVM/TaintConfig/TaintConfigBase.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" -#include "phasar/Utils/SrcCodeLocationEntry.h" #include "llvm/ADT/StringRef.h" #include "llvm/IR/Function.h" @@ -19,6 +18,7 @@ #include "llvm/IR/Value.h" #include "SourceMapping.h" +#include "SrcCodeLocationEntry.h" #include "TestConfig.h" #include "gtest/gtest.h" diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp index 6516023073..42aec92ada 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp @@ -10,7 +10,6 @@ #include "phasar/PhasarLLVM/Pointer/LLVMAliasSet.h" #include "phasar/PhasarLLVM/SimpleAnalysisConstructor.h" #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" -#include "phasar/Utils/SrcCodeLocationEntry.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instruction.h" @@ -18,6 +17,7 @@ #include "llvm/IR/Value.h" #include "SourceMapping.h" +#include "SrcCodeLocationEntry.h" #include "TestConfig.h" #include "gtest/gtest.h" diff --git a/include/phasar/Utils/SrcCodeLocationEntry.h b/unittests/TestUtils/SrcCodeLocationEntry.h similarity index 94% rename from include/phasar/Utils/SrcCodeLocationEntry.h rename to unittests/TestUtils/SrcCodeLocationEntry.h index 98d3fa15b2..d7c34bb63f 100644 --- a/include/phasar/Utils/SrcCodeLocationEntry.h +++ b/unittests/TestUtils/SrcCodeLocationEntry.h @@ -171,6 +171,23 @@ convertTestingLocationSetInIR( return Ret; } +template +[[nodiscard]] inline auto convertTestingLocationSetMapInIR( + const MapTy &Locs, const LLVMProjectIRDB &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 = llvm::dyn_cast_if_present( + testingLocInIR(InstLoc, IRDB, InterestingFunction)); + auto ConvSet = + convertTestingLocationSetInIR(Set, IRDB, InterestingFunction); + return std::make_pair(LocVal, std::move(ConvSet)); + }); + return Ret; +} + struct SrcCodeLocationEntry { SrcCodeLocationEntry( uint32_t Line, uint32_t Column, diff --git a/unittests/Utils/AnalysisPrinterTest.cpp b/unittests/Utils/AnalysisPrinterTest.cpp index a267d8dd81..3744c9f47d 100644 --- a/unittests/Utils/AnalysisPrinterTest.cpp +++ b/unittests/Utils/AnalysisPrinterTest.cpp @@ -11,12 +11,13 @@ #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "phasar/Utils/DefaultAnalysisPrinter.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/STLExtras.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 CallBackPairTy = std::pair::config_callback_t, IDEExtendedTaintAnalysis<>::config_callback_t>; @@ -31,29 +32,23 @@ 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() { @@ -61,9 +56,10 @@ class GroundTruthCollector llvm::raw_string_ostream OS(Ret); OS << "{\n"; for (const auto &[Inst, Facts] : GroundTruth) { - OS << " " << Inst << ": { "; - llvm::interleaveComma(Facts, OS); - OS << " },\n"; + OS << " " << llvmIRToString(Inst) << ": {\n"; + for (const auto *Val : Facts) { + OS << " " << llvmIRToString(Val) << '\n'; + } } OS << "}\n"; @@ -75,7 +71,8 @@ class GroundTruthCollector << "Elements of GroundTruth not found: " << printGroundTruth(); } - llvm::DenseMap> GroundTruth{}; + std::map> + GroundTruth{}; }; class AnalysisPrinterTest : public ::testing::Test { @@ -84,7 +81,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); @@ -105,7 +103,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(); @@ -116,8 +115,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; @@ -132,16 +133,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[16] = {"8"}; - GroundTruthCollector GroundTruthPrinter = {GroundTruth}; - doAnalysisTest("xtaint01_cpp_dbg.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 From 37d65f9d57bde999ac7ed0c0d095aae4b0d4754f Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Mon, 4 Aug 2025 20:07:59 +0200 Subject: [PATCH 20/35] Start converting InstInterationAnalysis tests --- .../inst_interaction/CMakeLists.txt | 2 + .../IDEInstInteractionAnalysisTest.cpp | 1062 ++++++++++------- unittests/TestUtils/SrcCodeLocationEntry.h | 122 +- 3 files changed, 722 insertions(+), 464 deletions(-) diff --git a/test/llvm_test_code/inst_interaction/CMakeLists.txt b/test/llvm_test_code/inst_interaction/CMakeLists.txt index 6fdfa88e8b..1015243951 100644 --- a/test/llvm_test_code/inst_interaction/CMakeLists.txt +++ b/test/llvm_test_code/inst_interaction/CMakeLists.txt @@ -42,8 +42,10 @@ 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/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp index 59a474013b..43f3930de7 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp @@ -18,14 +18,19 @@ #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/IR/GlobalVariable.h" #include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" #include "llvm/Support/raw_ostream.h" +#include "SrcCodeLocationEntry.h" #include "TestConfig.h" #include "gtest/gtest.h" @@ -37,6 +42,8 @@ using namespace psr; +using TaintSetT = BitVectorSet; + /* ============== TEST FIXTURE ============== */ class IDEInstInteractionAnalysisTest : public ::testing::Test { protected: @@ -45,8 +52,8 @@ class IDEInstInteractionAnalysisTest : public ::testing::Test { // Function - Line Nr - Variable - Values using IIACompactResult_t = - std::tuple::l_t>; + std::tuple::l_t>; std::optional HA; LLVMProjectIRDB *IRDB{}; @@ -75,26 +82,37 @@ class IDEInstInteractionAnalysisTest : public ::testing::Test { // 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,30 +123,30 @@ 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, LatticeVal] : 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); + if (!llvm::isa(Fact.getBase())) { + continue; + } + auto FactName = psr::getVarNameFromIR(Fact.getBase()); + if (FactName == VarName) { + EXPECT_EQ(LatticeVal, Value) + << "Unexpected taint-set at " << InstLoc << " for variable '" + << 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 '" << VarName << "' missing at '" << IRLoc << "'."; } } @@ -426,472 +444,594 @@ 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); -} - -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); + 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); } -PHASAR_SKIP_TEST(TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_04) { - // If we use libcxx this won't work since internal implementation is different - LIBCPP_GTEST_SKIP; +// 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); +// } - 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); -}) - -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); -} +// PHASAR_SKIP_TEST(TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_04) { +// // If we use libcxx this won't work since internal implementation is +// different LIBCPP_GTEST_SKIP; -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); -} +// 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); +// }) -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); -} +// 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); +// } -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); -} +// 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); +// } -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); -} +// 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); +// } -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); -} +// 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); +// } -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); -} +// 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); +// } -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); -} +// 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); +// } -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); -} +// 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); +// } -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); -} +// 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); +// } -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); -} +// 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); +// } -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); -} +// 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); +// } -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); -} +// 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); +// } -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); -} +// 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); +// } -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); -} +// 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); +// } -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); -} +// 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); +// } -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); -} +// 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); +// } -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, 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); +// } -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, - 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); +// } -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, - 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, 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); -} +// 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, +// 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); -} +// 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, +// 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"; +// 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); +// } - 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) { +// TEST_F(IDEInstInteractionAnalysisTest, HandleHeapTest_01) { // std::set GroundTruth; // GroundTruth.emplace( // std::tuple>( -// "main", 10, "retval", {"3"})); +// "main", 17, "retval", {"3"})); // GroundTruth.emplace( // std::tuple>( -// "main", 10, "a", {"1", "4", "5", "6", "7", "8", "13"})); +// "main", 17, "i", {"5", "6"})); // GroundTruth.emplace( // std::tuple>( -// "main", 10, "x", {"1", "4", "5", "13"})); -// doAnalysisAndCompareResults("struct_01_cpp.ll", GroundTruth, false); +// "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); +// }) + +// // TEST_F(IDEInstInteractionAnalysisTest, HandleStruct_01) { +// // std::set GroundTruth; +// // GroundTruth.emplace( +// // std::tuple>( +// // "main", 10, "retval", {"3"})); +// // GroundTruth.emplace( +// // std::tuple>( +// // "main", 10, "a", {"1", "4", "5", "6", "7", "8", "13"})); +// // GroundTruth.emplace( +// // std::tuple>( +// // "main", 10, "x", {"1", "4", "5", "13"})); +// // doAnalysisAndCompareResults("struct_01_cpp.ll", GroundTruth, false); +// // } + // main function for the test case/* */ int main(int Argc, char **Argv) { ::testing::InitGoogleTest(&Argc, Argv); diff --git a/unittests/TestUtils/SrcCodeLocationEntry.h b/unittests/TestUtils/SrcCodeLocationEntry.h index d7c34bb63f..0738e08965 100644 --- a/unittests/TestUtils/SrcCodeLocationEntry.h +++ b/unittests/TestUtils/SrcCodeLocationEntry.h @@ -4,6 +4,7 @@ #include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.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" @@ -19,7 +20,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -35,6 +38,10 @@ struct GlobalVar { 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{}; @@ -46,6 +53,10 @@ struct LineCol { 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 LineColFun { uint32_t Line{}; @@ -60,6 +71,33 @@ struct LineColFun { 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() + " }"; + } +}; + +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.Line, LC1.Col, LC1.InFunction, LC1.OpCode) < + std::tie(LC2.Line, LC2.Col, LC2.InFunction, 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 ArgNo { uint32_t Idx{}; @@ -68,6 +106,9 @@ struct ArgNo { 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; @@ -79,12 +120,18 @@ struct ArgInFun { 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 TestingSrcLocation - : public std::variant { - - using std::variant::variant; + : public std::variant { + using VarT = std::variant; + using VarT::variant; template [[nodiscard]] constexpr bool isa() const noexcept { return std::holds_alternative(*this); @@ -96,8 +143,66 @@ struct TestingSrcLocation 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 + +namespace std { +template <> struct hash { + size_t operator()(psr::LineCol LC) const noexcept { + return llvm::hash_value(std::make_pair(LC.Line, LC.Col)); + } +}; +template <> struct hash { + size_t operator()(psr::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::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::GlobalVar GV) const noexcept { + return llvm::hash_value(GV.Name); + } +}; +template <> struct hash { + size_t operator()(psr::ArgNo Arg) const noexcept { + return llvm::hash_value(Arg.Idx); + } +}; +template <> struct hash { + size_t operator()(psr::ArgInFun Arg) const noexcept { + return llvm::hash_combine(Arg.Idx, Arg.InFunction); + } }; +template <> struct hash { + size_t operator()(const psr::TestingSrcLocation &Loc) const noexcept { + return std::hash{}(Loc); + } +}; +} // namespace std + +namespace psr { + [[nodiscard]] inline const llvm::Value * testingLocInIR(TestingSrcLocation Loc, const LLVMProjectIRDB &IRDB, const llvm::Function *InterestingFunction = nullptr) { @@ -123,6 +228,17 @@ testingLocInIR(TestingSrcLocation Loc, const LLVMProjectIRDB &IRDB, } return unittest::getInstAtOrNull(InFun, LC.Line, LC.Col); }, + [&IRDB](LineColFunOp LC) -> llvm ::Value const * { + const auto *InFun = IRDB.getFunctionDefinition(LC.InFunction); + if (!InFun) { + llvm::report_fatal_error("Required function '" + LC.InFunction + + "' does not exist in the IR!"); + } + return unittest::getInstAtOrNull( + InFun, LC.Line, LC.Col, [Op = LC.OpCode](const auto *Inst) { + return Inst->getOpcode() == Op; + }); + }, [&IRDB](GlobalVar GV) -> llvm ::Value const * { return IRDB.getModule()->getGlobalVariable(GV.Name, true); }, From 6aa8ab9766ff4ba5e11b8aab4b2e698fe4a92f30 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Tue, 5 Aug 2025 20:03:45 +0200 Subject: [PATCH 21/35] Convert some more IIA test cases --- .../IDEInstInteractionAnalysisTest.cpp | 406 ++++++++++-------- unittests/TestUtils/SrcCodeLocationEntry.h | 99 ++++- 2 files changed, 309 insertions(+), 196 deletions(-) diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp index 43f3930de7..522cdb89d0 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp @@ -25,9 +25,11 @@ #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" @@ -50,9 +52,10 @@ 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::optional HA; @@ -67,6 +70,34 @@ class IDEInstInteractionAnalysisTest : public ::testing::Test { IRDB = &HA->getProjectIRDB(); } + [[nodiscard]] bool matchesVar(const llvm::Value *Fact, + const VarNameT &VarName) { + return std::visit( + psr::Overloaded{ + [&](const std::string &Name) { + if (!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); + } + void doAnalysisAndCompareResults(const std::string &LlvmFilePath, const std::vector &EntryPoints, @@ -133,20 +164,18 @@ class IDEInstInteractionAnalysisTest : public ::testing::Test { IIASolver.resultsAt(llvm::cast(IRLoc)); bool FactFound = false; for (auto &[Fact, Value] : ResultMap) { - if (!llvm::isa(Fact.getBase())) { - continue; - } - auto FactName = psr::getVarNameFromIR(Fact.getBase()); - if (FactName == VarName) { + if (matchesVar(Fact.getBase(), VarName)) { EXPECT_EQ(LatticeVal, Value) << "Unexpected taint-set at " << InstLoc << " for variable '" - << VarName << "' (" << llvmIRToString(Fact.getBase()) << ")"; + << printVar(VarName) << "' (" << llvmIRToString(Fact.getBase()) + << ")"; FactFound = true; } } EXPECT_TRUE(FactFound) - << "Variable '" << VarName << "' missing at '" << IRLoc << "'."; + << "Variable '" << printVar(VarName) << "' missing at '" + << llvmIRToString(IRLoc) << "'."; } } @@ -488,182 +517,209 @@ TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_02) { 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); -// } +TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_03) { + std::set GroundTruth; -// PHASAR_SKIP_TEST(TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_04) { -// // If we use libcxx this won't work since internal implementation is -// different LIBCPP_GTEST_SKIP; + auto Main20 = LineColFun{6, 3, "main"}; -// 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); -// }) + 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"}, + }); -// 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); -// } + doAnalysisAndCompareResults("basic_03_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); -// } +PHASAR_SKIP_TEST(TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_04) { + // If we use libcxx this won't work since internal implementation is different + // TODO: Test this out, now that we have a src-code based definition of the + // ground-truth! + LIBCPP_GTEST_SKIP; -// 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); -// } + std::set GroundTruth; + auto Main23 = LineColFun{11, 3, "main"}; -// 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); -// } + 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"}, + }); -// 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); -// } + doAnalysisAndCompareResults("basic_04_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); -// } +TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_05) { + std::set GroundTruth; + auto Main11 = LineColFun{10, 3, "main"}; + GroundTruth.emplace(Main11, "i", + TaintSetT{ + LineColFun{6, 7, "main"}, + LineColFun{8, 7, "main"}, + }); -// 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); -// } + doAnalysisAndCompareResults("basic_05_cpp_dbg.ll", {"main"}, GroundTruth, + false); +} + +TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_06) { + std::set GroundTruth; + 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; + 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; + 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; + 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; + 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; + 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; diff --git a/unittests/TestUtils/SrcCodeLocationEntry.h b/unittests/TestUtils/SrcCodeLocationEntry.h index 0738e08965..66acd84402 100644 --- a/unittests/TestUtils/SrcCodeLocationEntry.h +++ b/unittests/TestUtils/SrcCodeLocationEntry.h @@ -10,6 +10,7 @@ #include "llvm/IR/Function.h" #include "llvm/IR/GlobalVariable.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" @@ -126,11 +127,38 @@ struct ArgInFun { } }; +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 TestingSrcLocation : public std::variant { + ArgInFun, RetVal, RetStmt> { using VarT = std::variant; + ArgInFun, RetVal, RetStmt>; using VarT::variant; template [[nodiscard]] constexpr bool isa() const noexcept { @@ -194,6 +222,18 @@ template <> struct hash { } }; +template <> struct hash { + size_t operator()(psr::RetVal Ret) const noexcept { + return llvm::hash_value(Ret.InFunction); + } +}; + +template <> struct hash { + size_t operator()(psr::RetStmt Ret) const noexcept { + return llvm::hash_value(Ret.InFunction); + } +}; + template <> struct hash { size_t operator()(const psr::TestingSrcLocation &Loc) const noexcept { return std::hash{}(Loc); @@ -206,7 +246,14 @@ namespace psr { [[nodiscard]] inline const llvm::Value * testingLocInIR(TestingSrcLocation Loc, const LLVMProjectIRDB &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; + }; return std::visit( psr::Overloaded{ [=](LineCol LC) -> llvm ::Value const * { @@ -220,20 +267,12 @@ testingLocInIR(TestingSrcLocation Loc, const LLVMProjectIRDB &IRDB, return unittest::getInstAtOrNull(InterestingFunction, LC.Line, LC.Col); }, - [&IRDB](LineColFun LC) -> llvm ::Value const * { - const auto *InFun = IRDB.getFunctionDefinition(LC.InFunction); - if (!InFun) { - llvm::report_fatal_error("Required function '" + LC.InFunction + - "' does not exist in the IR!"); - } + [&](LineColFun LC) -> llvm ::Value const * { + const auto *InFun = GetFunction(LC.InFunction); return unittest::getInstAtOrNull(InFun, LC.Line, LC.Col); }, - [&IRDB](LineColFunOp LC) -> llvm ::Value const * { - const auto *InFun = IRDB.getFunctionDefinition(LC.InFunction); - if (!InFun) { - llvm::report_fatal_error("Required function '" + LC.InFunction + - "' does not exist in the IR!"); - } + [&](LineColFunOp LC) -> llvm ::Value const * { + const auto *InFun = GetFunction(LC.InFunction); return unittest::getInstAtOrNull( InFun, LC.Line, LC.Col, [Op = LC.OpCode](const auto *Inst) { return Inst->getOpcode() == Op; @@ -257,12 +296,8 @@ testingLocInIR(TestingSrcLocation Loc, const LLVMProjectIRDB &IRDB, } return InterestingFunction->getArg(A.Idx); }, - [&IRDB](ArgInFun A) -> llvm ::Value const * { - const auto *InFun = IRDB.getFunctionDefinition(A.InFunction); - if (!InFun) { - llvm::report_fatal_error("Required function '" + A.InFunction + - "' does not exist in the IR!"); - } + [&](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 (" + @@ -270,6 +305,28 @@ testingLocInIR(TestingSrcLocation Loc, const LLVMProjectIRDB &IRDB, } 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); + }, }, Loc); } From 792c0f75e9498ad746e27c056c04131f64147236 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Wed, 6 Aug 2025 20:19:19 +0200 Subject: [PATCH 22/35] Add more IIA tests --- include/phasar/Domain/LatticeDomain.h | 11 +- .../IDEInstInteractionAnalysisTest.cpp | 763 ++++++++++-------- unittests/TestUtils/SrcCodeLocationEntry.h | 10 +- 3 files changed, 441 insertions(+), 343 deletions(-) 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/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp index 522cdb89d0..e61093cc61 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp @@ -10,6 +10,7 @@ #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" @@ -75,7 +76,8 @@ class IDEInstInteractionAnalysisTest : public ::testing::Test { return std::visit( psr::Overloaded{ [&](const std::string &Name) { - if (!llvm::isa(Fact)) { + if (!llvm::isa(Fact) && + !llvm::isa(Fact)) { return false; } auto FactName = psr::getVarNameFromIR(Fact); @@ -97,6 +99,17 @@ class IDEInstInteractionAnalysisTest : public ::testing::Test { }, 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, @@ -154,7 +167,7 @@ class IDEInstInteractionAnalysisTest : public ::testing::Test { IIASolver.dumpResults(); } // do the comparison - for (const auto &[InstLoc, VarName, LatticeVal] : GroundTruth) { + 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); @@ -163,9 +176,9 @@ class IDEInstInteractionAnalysisTest : public ::testing::Test { auto ResultMap = IIASolver.resultsAt(llvm::cast(IRLoc)); bool FactFound = false; - for (auto &[Fact, Value] : ResultMap) { + for (auto &[Fact, ComputedVal] : ResultMap) { if (matchesVar(Fact.getBase(), VarName)) { - EXPECT_EQ(LatticeVal, Value) + EXPECT_EQ(sorted(ExpectedVal), sorted(ComputedVal)) << "Unexpected taint-set at " << InstLoc << " for variable '" << printVar(VarName) << "' (" << llvmIRToString(Fact.getBase()) << ")"; @@ -721,334 +734,416 @@ TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_11) { 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); -// } +TEST_F(IDEInstInteractionAnalysisTest, HandleCallTest_01) { + std::set GroundTruth; + auto Main14 = RetStmt{"main"}; -// 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); -// } + 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"}, + }); -// 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); -// } + doAnalysisAndCompareResults("call_01_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); -// } +TEST_F(IDEInstInteractionAnalysisTest, HandleCallTest_02) { + std::set GroundTruth; + auto Main13 = RetStmt{"main"}; -// 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); -// } + 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"}, + }); -// 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); -// } + doAnalysisAndCompareResults("call_02_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); -// } +TEST_F(IDEInstInteractionAnalysisTest, HandleCallTest_03) { + std::set GroundTruth; + auto Main10 = RetStmt{"main"}; -// 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); -// } + 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"}, + }); -// 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); -// } + doAnalysisAndCompareResults("call_03_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); -// } +TEST_F(IDEInstInteractionAnalysisTest, HandleCallTest_04) { + std::set GroundTruth; + auto Main10 = RetStmt{"main"}; -// 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, false); -// } + 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"}, + }); -// 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, -// false); -// } + doAnalysisAndCompareResults("call_04_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, -// false); -// } +TEST_F(IDEInstInteractionAnalysisTest, HandleCallTest_05) { + std::set GroundTruth; + auto Main10 = RetStmt{"main"}; -// 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); -// } + 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"}, + }); -// 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); -// } + doAnalysisAndCompareResults("call_05_cpp_dbg.ll", {"main"}, GroundTruth, + false); +} + +TEST_F(IDEInstInteractionAnalysisTest, HandleCallTest_06) { + // NOTE: Here we are suffering from IntraProceduralAliasesOnly + std::set GroundTruth; + 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; + 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; + 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; + + 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(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(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; + 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; + 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; + 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; + + 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. @@ -1071,22 +1166,22 @@ TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_11) { // doAnalysisAndCompareResults("rvo_01_cpp.ll", {"main"}, GroundTruth, false); // }) -// // TEST_F(IDEInstInteractionAnalysisTest, HandleStruct_01) { -// // std::set GroundTruth; -// // GroundTruth.emplace( -// // std::tuple>( -// // "main", 10, "retval", {"3"})); -// // GroundTruth.emplace( -// // std::tuple>( -// // "main", 10, "a", {"1", "4", "5", "6", "7", "8", "13"})); -// // GroundTruth.emplace( -// // std::tuple>( -// // "main", 10, "x", {"1", "4", "5", "13"})); -// // doAnalysisAndCompareResults("struct_01_cpp.ll", GroundTruth, false); -// // } +// TEST_F(IDEInstInteractionAnalysisTest, HandleStruct_01) { +// std::set GroundTruth; +// GroundTruth.emplace( +// std::tuple>( +// "main", 10, "retval", {"3"})); +// GroundTruth.emplace( +// std::tuple>( +// "main", 10, "a", {"1", "4", "5", "6", "7", "8", "13"})); +// GroundTruth.emplace( +// std::tuple>( +// "main", 10, "x", {"1", "4", "5", "13"})); +// doAnalysisAndCompareResults("struct_01_cpp.ll", GroundTruth, false); +// } // main function for the test case/* */ int main(int Argc, char **Argv) { diff --git a/unittests/TestUtils/SrcCodeLocationEntry.h b/unittests/TestUtils/SrcCodeLocationEntry.h index 66acd84402..4cce34bcf4 100644 --- a/unittests/TestUtils/SrcCodeLocationEntry.h +++ b/unittests/TestUtils/SrcCodeLocationEntry.h @@ -65,8 +65,8 @@ struct LineColFun { llvm::StringRef InFunction{}; 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); + 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) == @@ -86,8 +86,8 @@ struct LineColFunOp { uint32_t 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); + 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) == @@ -116,7 +116,7 @@ struct ArgInFun { llvm::StringRef InFunction{}; friend bool operator<(ArgInFun A1, ArgInFun A2) noexcept { - return std::tie(A1.Idx, A1.InFunction) < std::tie(A2.Idx, A2.InFunction); + 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); From 0e8d8f620245e86f15195c2c935878847170a27a Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Fri, 8 Aug 2025 20:02:45 +0200 Subject: [PATCH 23/35] Convert FIIA-test + fix use-after-free in IIA test --- include/phasar/Utils/BitVectorSet.h | 11 +- .../Problems/IDEFeatureTaintAnalysisTest.cpp | 1075 ++++++++++++----- .../IDEInstInteractionAnalysisTest.cpp | 4 +- 3 files changed, 758 insertions(+), 332 deletions(-) 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/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEFeatureTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEFeatureTaintAnalysisTest.cpp index 243cb2d6a7..da689fb881 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEFeatureTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEFeatureTaintAnalysisTest.cpp @@ -17,20 +17,25 @@ #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; -static std::string printSet(const std::set &EdgeFact) { - std::string Ret; - llvm::raw_string_ostream ROS(Ret); - llvm::interleaveComma(EdgeFact, ROS << '<'); - ROS << '>'; - return Ret; -} +using TaintSetT = std::set; + +// static std::string printSet(const std::set &EdgeFact) { +// std::string Ret; +// llvm::raw_string_ostream ROS(Ret); +// llvm::interleaveComma(EdgeFact, ROS << '<'); +// ROS << '>'; +// return Ret; +// } /* ============== TEST FIXTURE ============== */ class IDEFeatureTaintAnalysisTest : public ::testing::Test { @@ -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,35 @@ 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)); - } - - // Initialze IDs - for (const auto *Inst : IRDB->getAllInstructions()) { - BitVectorSet BV; - BV.insert(getMetaDataID(Inst)); - } + [[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); } void @@ -77,21 +101,32 @@ class IDEFeatureTaintAnalysisTest : public ::testing::Test { // 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); }; assert(HA); @@ -112,438 +147,822 @@ class IDEFeatureTaintAnalysisTest : public ::testing::Test { // 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()) { IIASolver.dumpResults(llvm::errs()); - llvm::errs() - << "\n======================================================\n"; - printDump(HA->getProjectIRDB(), IIASolver.getSolverResults()); + // llvm::errs() + // << "\n======================================================\n"; + // printDump(HA->getProjectIRDB(), IIASolver.getSolverResults()); } } - void TearDown() override {} - - // See vara::PhasarTaintAnalysis::taintsForInst - [[nodiscard]] inline std::set - taintsForInst(const llvm::Instruction *Inst, - SolverResults SR) { - - if (const auto *Ret = llvm::dyn_cast(Inst)) { - if (Ret->getNumOperands() == 0) { - return {}; - } - } else if (llvm::isa(Inst)) { - return {}; - } - - std::set AggregatedTaints; - - 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(); - - } else { - auto Results = SR.resultsAtInLLVMSSA(Inst); - auto SearchPosTaints = Results.find(Inst); - if (SearchPosTaints != Results.end()) { - AggregatedTaints = SearchPosTaints->second.toSet(); - } - } - - // additionalStaticTaints - AggregatedTaints.insert(getMetaDataID(Inst)); - - return AggregatedTaints; + void TearDown() override { + BitVectorSet::clearPosition(); } - void printDump(const LLVMProjectIRDB &IRDB, - SolverResults - SR) { - const llvm::Function *CurrFun = nullptr; - for (const auto *Inst : IRDB.getAllInstructions()) { - if (CurrFun != Inst->getFunction()) { - CurrFun = Inst->getFunction(); - llvm::errs() << "\n=================== '" << CurrFun->getName() - << "' ===================\n"; - } - llvm::errs() << " N: " << llvmIRToString(Inst) << '\n'; - llvm::errs() << " D: " << printSet(taintsForInst(Inst, SR)) << "\n\n"; - } - } + // // See vara::PhasarTaintAnalysis::taintsForInst + // [[nodiscard]] inline std::set + // taintsForInst(const llvm::Instruction *Inst, + // SolverResults SR) { + + // if (const auto *Ret = llvm::dyn_cast(Inst)) { + // if (Ret->getNumOperands() == 0) { + // return {}; + // } + // } else if (llvm::isa(Inst)) { + // return {}; + // } + + // std::set AggregatedTaints; + + // 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(); + + // } else { + // auto Results = SR.resultsAtInLLVMSSA(Inst); + // auto SearchPosTaints = Results.find(Inst); + // if (SearchPosTaints != Results.end()) { + // AggregatedTaints = SearchPosTaints->second.toSet(); + // } + // } + + // // additionalStaticTaints + // AggregatedTaints.insert(getMetaDataID(Inst)); + + // return AggregatedTaints; + // } + + // void printDump(const LLVMProjectIRDB &IRDB, + // SolverResults + // SR) { + // const llvm::Function *CurrFun = nullptr; + // for (const auto *Inst : IRDB.getAllInstructions()) { + // if (CurrFun != Inst->getFunction()) { + // CurrFun = Inst->getFunction(); + // llvm::errs() << "\n=================== '" << CurrFun->getName() + // << "' ===================\n"; + // } + // llvm::errs() << " N: " << llvmIRToString(Inst) << '\n'; + // llvm::errs() << " D: " << printSet(taintsForInst(Inst, SR)) << "\n\n"; + // } + // } }; // Test Fixture 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 + // TODO: Test this out, now that we have a src-code based definition of the + // ground-truth! 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"; - - 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); -}) + 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(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/IDEInstInteractionAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp index e61093cc61..06e6ce0944 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp @@ -192,7 +192,9 @@ class IDEInstInteractionAnalysisTest : public ::testing::Test { } } - void TearDown() override {} + void TearDown() override { + BitVectorSet::clearPosition(); + } }; // Test Fixture From 14c119a1eca3dea9e12c34a59a50364ba0a5c530 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Mon, 11 Aug 2025 22:51:47 +0200 Subject: [PATCH 24/35] HandleTypeState_03 not working --- .../Problems/IDETSAnalysisFileIOTest.cpp | 134 ++++++++++++++++-- .../IFDSUninitializedVariablesTest.cpp | 8 +- 2 files changed, 127 insertions(+), 15 deletions(-) diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp index e5c80d4d3f..a33f03d881 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp @@ -19,6 +19,10 @@ #include "phasar/PhasarLLVM/TypeHierarchy/LLVMTypeHierarchy.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" +#include "llvm/IR/Instruction.h" +#include "llvm/Support/Casting.h" + +#include "SrcCodeLocationEntry.h" #include "TestConfig.h" #include "gtest/gtest.h" @@ -62,6 +66,46 @@ class IDETSAnalysisFileIOTest : public ::testing::Test { void TearDown() override {} + std::map> + srcCodeLocsToInsts( + const std::map> + &GroundTruth) { + std::map> + Converted; + + for (const auto &OuterEntry : GroundTruth) { + const auto *FirstInst = getInstFromEntryOrNull(std::get<0>(OuterEntry)); + if (FirstInst) { + for (const auto &InnerEntry : std::get<1>(OuterEntry)) { + const auto *SecondInst = + getInstFromEntryOrNull(std::get<0>(InnerEntry)); + + if (SecondInst) { + std::map InnerMap = { + {SecondInst, std::get<1>(InnerEntry)}}; + + Converted.insert( + std::pair>(FirstInst, + InnerMap)); + continue; + } + + llvm::errs() + << "Second SrcCodeLocationEntry couldn't be converted to an " + "Instruction."; + } + continue; + } + + llvm::errs() << "First SrcCodeLocationEntry couldn't be converted to an " + "Instruction."; + } + + return Converted; + } + /** * 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 argc). @@ -69,9 +113,35 @@ class IDETSAnalysisFileIOTest : public ::testing::Test { * @param solver provides the results */ void compareResults( - const std::map> &GroundTruth, + const std::map> + &GroundTruth, IDESolver_P> &Solver) { + auto GroundTruthEntries = srcCodeLocsToInsts(GroundTruth); + + int Counter = 0; + for (const auto &Entry : GroundTruthEntries) { + std::map Results; + auto GT = std::get<1>(Entry); + llvm::outs() << "Counter: " << Counter++ << "\n"; + const auto *CurrInst = std::get<0>(Entry); + for (auto Result : Solver.resultsAt(CurrInst, true)) { + const auto &FirstResult = std::get<0>(Result); + const auto &SecondResult = std::get<1>(Result); + + llvm::outs() << "FirstResult: " << *(FirstResult) << "\n"; + llvm::outs() << "SecondResult: " << SecondResult << "\n"; + + if (GT.find(llvm::cast(FirstResult)) != GT.end()) { + Results.insert(std::pair( + llvm::cast(FirstResult), int(SecondResult))); + } + } + EXPECT_EQ(Results, GT) << "At " << llvmIRToShortString(CurrInst); + } + +#if false + for (const auto &InstToGroundTruth : GroundTruth) { const auto *Inst = HA->getProjectIRDB().getInstruction(InstToGroundTruth.first); @@ -87,6 +157,8 @@ class IDETSAnalysisFileIOTest : public ::testing::Test { } EXPECT_EQ(Results, GT) << "At " << llvmIRToShortString(Inst); } + +#endif } }; // Test Fixture @@ -94,28 +166,63 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_01) { 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); + // const std::map> Gt = { + // {5, {{"3", IOSTATE::UNINIT}}}, + // {9, {{"3", IOSTATE::CLOSED}}}, + // {7, {{"3", IOSTATE::OPENED}}}}; + + std::map> + GroundTruth; + const auto File = + SrcCodeLocationEntry(4, 9, HA->getICFG().getIRDB()->getFunction("main")); + const auto Entry = + SrcCodeLocationEntry(5, 7, HA->getICFG().getIRDB()->getFunction("main")); + const auto EntryTwo = + SrcCodeLocationEntry(6, 3, HA->getICFG().getIRDB()->getFunction("main")); + const auto EntryThree = + SrcCodeLocationEntry(7, 3, HA->getICFG().getIRDB()->getFunction("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_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); - const std::map> Gt = { - {7, {{"3", IOSTATE::OPENED}, {"5", IOSTATE::OPENED}}}}; - compareResults(Gt, Llvmtssolver); + + std::map> + GroundTruth; + const auto File = + SrcCodeLocationEntry(4, 9, HA->getICFG().getIRDB()->getFunction("main")); + const auto Entry = + SrcCodeLocationEntry(6, 3, HA->getICFG().getIRDB()->getFunction("main")); + GroundTruth.insert({Entry, {{File, IOSTATE::OPENED}}}); + compareResults(GroundTruth, Llvmtssolver); } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_03) { initialize({PathToLlFiles + "typestate_03_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); + + std::map> + GroundTruth; + const auto File = + SrcCodeLocationEntry(6, 9, HA->getICFG().getIRDB()->getFunction("main")); + const auto FooArg = + SrcCodeLocationEntry(3, 16, HA->getICFG().getIRDB()->getFunction("foo")); + const auto FooRet = + SrcCodeLocationEntry(3, 32, HA->getICFG().getIRDB()->getFunction("foo")); + const auto Return = + SrcCodeLocationEntry(11, 3, HA->getICFG().getIRDB()->getFunction("main")); + GroundTruth.insert({FooArg, {{File, IOSTATE::OPENED}}}); + GroundTruth.insert({FooRet, {{File, IOSTATE::CLOSED}}}); + GroundTruth.insert({Return, {{File, IOSTATE::CLOSED}}}); + compareResults(GroundTruth, Llvmtssolver); + +#if false // llvmtssolver.printReport(); const std::map> Gt = { // Entry in foo() @@ -135,8 +242,11 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_03) { {"8", IOSTATE::CLOSED}, {"12", IOSTATE::CLOSED}}}}; compareResults(Gt, Llvmtssolver); +#endif } +#if false + TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_04) { initialize({PathToLlFiles + "typestate_04_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); @@ -548,6 +658,8 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_19) { compareResults(Gt, Llvmtssolver); } +#endif + // main function for the test case int main(int Argc, char **Argv) { ::testing::InitGoogleTest(&Argc, Argv); diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp index 42aec92ada..a0a466bb23 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp @@ -105,16 +105,14 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_02_SHOULD_LEAK) { compareResults(GroundTruth); } -#if false - 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; - + std::set> GroundTruth; +#if false // %4 = load i32, i32* %2 ; %2 is the parameter a of addTen(int) containing // undef GroundTruth[5] = {"0"}; @@ -125,9 +123,11 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_03_SHOULD_LEAK) { // The same as in test2: is it necessary to report again? (the analysis does // not) // GroundTruth[17] = {"16"}; +#endif compareResults(GroundTruth); } +#if false TEST_F(IFDSUninitializedVariablesTest, UninitTest_04_SHOULD_NOT_LEAK) { initialize({PathToLlFiles + "ctor_default_cpp_dbg.ll"}); From 785b4467095eb4c21cf1fa0ca962482e6e353318 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Fri, 15 Aug 2025 23:59:05 +0200 Subject: [PATCH 25/35] All but three fileio tests work --- .../Problems/IDETSAnalysisFileIOTest.cpp | 471 +++++++++++++++--- 1 file changed, 410 insertions(+), 61 deletions(-) diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp index a33f03d881..f62961e4f0 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp @@ -21,6 +21,7 @@ #include "llvm/IR/Instruction.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" #include "SrcCodeLocationEntry.h" #include "TestConfig.h" @@ -92,15 +93,27 @@ class IDETSAnalysisFileIOTest : public ::testing::Test { continue; } - llvm::errs() - << "Second SrcCodeLocationEntry couldn't be converted to an " - "Instruction."; + llvm::outs() << "Line: " << std::get<0>(InnerEntry).Line + << "\nColumn: " << std::get<0>(InnerEntry).Column + << "\n"; + llvm::report_fatal_error( + "Second SrcCodeLocationEntry couldn't be converted to an " + "Instruction.\n"); + // llvm::errs() + // << "Second SrcCodeLocationEntry couldn't be converted to an " + // "Instruction.\n"; } continue; } - llvm::errs() << "First SrcCodeLocationEntry couldn't be converted to an " - "Instruction."; + llvm::outs() << "Line: " << std::get<0>(OuterEntry).Line + << "\nColumn: " << std::get<0>(OuterEntry).Column << "\n"; + llvm::report_fatal_error( + "First SrcCodeLocationEntry couldn't be converted to an " + "Instruction.\n"); + // llvm::errs() << "First SrcCodeLocationEntry couldn't be converted to an + // " + // "Instruction.\n"; } return Converted; @@ -129,19 +142,23 @@ class IDETSAnalysisFileIOTest : public ::testing::Test { const auto &FirstResult = std::get<0>(Result); const auto &SecondResult = std::get<1>(Result); - llvm::outs() << "FirstResult: " << *(FirstResult) << "\n"; + llvm::outs() << "FirstResult: " << llvmIRToString(FirstResult) << "\n"; llvm::outs() << "SecondResult: " << SecondResult << "\n"; - - if (GT.find(llvm::cast(FirstResult)) != GT.end()) { - Results.insert(std::pair( - llvm::cast(FirstResult), int(SecondResult))); + if (const auto *CastInst = + llvm::dyn_cast_or_null(FirstResult)) { + if (GT.find(CastInst) != GT.end()) { + Results.insert(std::pair( + CastInst, int(SecondResult))); + } + } else { + llvm::errs() + << "[Error]: Couldn't cast FirstResult to Instruction.\n"; } } EXPECT_EQ(Results, GT) << "At " << llvmIRToShortString(CurrInst); } #if false - for (const auto &InstToGroundTruth : GroundTruth) { const auto *Inst = HA->getProjectIRDB().getInstruction(InstToGroundTruth.first); @@ -157,7 +174,6 @@ class IDETSAnalysisFileIOTest : public ::testing::Test { } EXPECT_EQ(Results, GT) << "At " << llvmIRToShortString(Inst); } - #endif } }; // Test Fixture @@ -174,13 +190,13 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_01) { std::map> GroundTruth; const auto File = - SrcCodeLocationEntry(4, 9, HA->getICFG().getIRDB()->getFunction("main")); + SrcCodeLocationEntry(4, 9, HA->getICFG().getFunction("main")); const auto Entry = - SrcCodeLocationEntry(5, 7, HA->getICFG().getIRDB()->getFunction("main")); + SrcCodeLocationEntry(5, 7, HA->getICFG().getFunction("main")); const auto EntryTwo = - SrcCodeLocationEntry(6, 3, HA->getICFG().getIRDB()->getFunction("main")); + SrcCodeLocationEntry(6, 3, HA->getICFG().getFunction("main")); const auto EntryThree = - SrcCodeLocationEntry(7, 3, HA->getICFG().getIRDB()->getFunction("main")); + SrcCodeLocationEntry(7, 3, HA->getICFG().getFunction("main")); GroundTruth.insert({Entry, {{File, IOSTATE::UNINIT}}}); GroundTruth.insert({EntryTwo, {{File, IOSTATE::OPENED}}}); GroundTruth.insert({EntryThree, {{File, IOSTATE::CLOSED}}}); @@ -195,9 +211,9 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_02) { std::map> GroundTruth; const auto File = - SrcCodeLocationEntry(4, 9, HA->getICFG().getIRDB()->getFunction("main")); + SrcCodeLocationEntry(4, 9, HA->getICFG().getFunction("main")); const auto Entry = - SrcCodeLocationEntry(6, 3, HA->getICFG().getIRDB()->getFunction("main")); + SrcCodeLocationEntry(6, 3, HA->getICFG().getFunction("main")); GroundTruth.insert({Entry, {{File, IOSTATE::OPENED}}}); compareResults(GroundTruth, Llvmtssolver); } @@ -209,17 +225,19 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_03) { std::map> GroundTruth; - const auto File = - SrcCodeLocationEntry(6, 9, HA->getICFG().getIRDB()->getFunction("main")); - const auto FooArg = - SrcCodeLocationEntry(3, 16, HA->getICFG().getIRDB()->getFunction("foo")); + const auto MainFile = + SrcCodeLocationEntry(6, 9, HA->getICFG().getFunction("main")); + const auto FooFile = + SrcCodeLocationEntry(3, 16, HA->getICFG().getFunction("foo")); + const auto FooBegin = + SrcCodeLocationEntry(3, 21, HA->getICFG().getFunction("foo")); const auto FooRet = - SrcCodeLocationEntry(3, 32, HA->getICFG().getIRDB()->getFunction("foo")); + SrcCodeLocationEntry(3, 32, HA->getICFG().getFunction("foo")); const auto Return = - SrcCodeLocationEntry(11, 3, HA->getICFG().getIRDB()->getFunction("main")); - GroundTruth.insert({FooArg, {{File, IOSTATE::OPENED}}}); - GroundTruth.insert({FooRet, {{File, IOSTATE::CLOSED}}}); - GroundTruth.insert({Return, {{File, IOSTATE::CLOSED}}}); + SrcCodeLocationEntry(11, 3, HA->getICFG().getFunction("main")); + GroundTruth.insert({FooBegin, {{FooFile, IOSTATE::OPENED}}}); + GroundTruth.insert({FooRet, {{FooFile, IOSTATE::CLOSED}}}); + GroundTruth.insert({Return, {{MainFile, IOSTATE::CLOSED}}}); compareResults(GroundTruth, Llvmtssolver); #if false @@ -245,35 +263,49 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_03) { #endif } -#if false - TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_04) { 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); + std::map> + GroundTruth; + const auto FooArg = + SrcCodeLocationEntry(4, 16, HA->getICFG().getFunction("foo")); + const auto FooRet = + SrcCodeLocationEntry(4, 49, HA->getICFG().getFunction("foo")); + const auto File = + SrcCodeLocationEntry(7, 9, HA->getICFG().getFunction("main")); + const auto FClose = + SrcCodeLocationEntry(9, 3, HA->getICFG().getFunction("main")); + const auto Return = + SrcCodeLocationEntry(10, 3, HA->getICFG().getFunction("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_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); + + std::map> + GroundTruth; + const auto File = + SrcCodeLocationEntry(6, 9, HA->getICFG().getFunction("main")); + const auto AfterFOpen = + SrcCodeLocationEntry(8, 7, HA->getICFG().getFunction("main")); + const auto AfterFClose = + SrcCodeLocationEntry(10, 3, HA->getICFG().getFunction("main")); + const auto Return = + SrcCodeLocationEntry(11, 3, HA->getICFG().getFunction("main")); + GroundTruth.insert({AfterFOpen, {{File, IOSTATE::OPENED}}}); + GroundTruth.insert({AfterFClose, {{File, IOSTATE::CLOSED}}}); + GroundTruth.insert({Return, {{File, IOSTATE::BOT}}}); + compareResults(GroundTruth, Llvmtssolver); +#if false const std::map> Gt = { // Before if statement {10, {{"4", IOSTATE::OPENED}, {"6", IOSTATE::OPENED}}}, @@ -285,14 +317,24 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_05) { // After if statement {14, {{"4", IOSTATE::BOT}, {"6", IOSTATE::BOT}}}}; compareResults(Gt, Llvmtssolver); +#endif } +// TODO: fix +#if false + TEST_F(IDETSAnalysisFileIOTest, DISABLED_HandleTypeState_06) { // This test fails due to imprecise points-to information initialize({PathToLlFiles + "typestate_06_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); + + std::map> + GroundTruth; + const auto File = + SrcCodeLocationEntry(6, 9, HA->getICFG().getFunction("main")); + GroundTruth.insert({Opened, {{File, IOSTATE::UNINIT}}}); + compareResults(GroundTruth, Llvmtssolver); const std::map> Gt = { // Before first fopen() {8, {{"5", IOSTATE::UNINIT}, {"6", IOSTATE::UNINIT}}}, @@ -323,11 +365,44 @@ TEST_F(IDETSAnalysisFileIOTest, DISABLED_HandleTypeState_06) { compareResults(Gt, Llvmtssolver); } +#endif + TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_07) { initialize({PathToLlFiles + "typestate_07_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); + + std::map> + GroundTruth; + const auto FooFile = + SrcCodeLocationEntry(3, 16, HA->getICFG().getFunction("foo")); + const auto FooExit = + SrcCodeLocationEntry(3, 32, HA->getICFG().getFunction("foo")); + const auto File = + SrcCodeLocationEntry(6, 9, HA->getICFG().getFunction("main")); + const auto FClose = + SrcCodeLocationEntry(7, 3, HA->getICFG().getFunction("main")); + const auto AfterFClose = + SrcCodeLocationEntry(8, 5, HA->getICFG().getFunction("main")); + const auto AfterFOpen = + SrcCodeLocationEntry(10, 3, HA->getICFG().getFunction("main")); + const auto FForFoo = + SrcCodeLocationEntry(10, 7, HA->getICFG().getFunction("main")); + GroundTruth.insert({FooExit, {{FooFile, IOSTATE::CLOSED}}}); + GroundTruth.insert({FClose, {{File, IOSTATE::UNINIT}}}); + GroundTruth.insert({AfterFClose, {{File, IOSTATE::ERROR}}}); + // TODO: fix IOSTATE::OPENED part below failing + GroundTruth.insert({AfterFOpen, + {{File, IOSTATE::ERROR}, + {AfterFClose, IOSTATE::ERROR}, + {FForFoo, IOSTATE::OPENED}}}); +#if false + // GroundTruth.insert({, {{, IOSTATE::ERROR}}}); + // GroundTruth.insert({, {{, IOSTATE::CLOSED}}}); +#endif + compareResults(GroundTruth, Llvmtssolver); + +#if false const std::map> Gt = { // In foo() {6, @@ -353,26 +428,59 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_07) { // At exit in main() {16, {{"2", IOSTATE::CLOSED}, {"8", IOSTATE::CLOSED}}}}; compareResults(Gt, Llvmtssolver); +#endif } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_08) { initialize({PathToLlFiles + "typestate_08_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); + + std::map> + GroundTruth; + const auto FooFile = + SrcCodeLocationEntry(5, 9, HA->getICFG().getFunction("foo")); + const auto FooRet = + SrcCodeLocationEntry(7, 3, HA->getICFG().getFunction("foo")); + const auto MainFile = + SrcCodeLocationEntry(11, 9, HA->getICFG().getFunction("main")); + const auto MainReturn = + SrcCodeLocationEntry(13, 3, HA->getICFG().getFunction("main")); + GroundTruth.insert({FooRet, {{FooFile, IOSTATE::OPENED}}}); + GroundTruth.insert( + {MainReturn, {{FooFile, IOSTATE::OPENED}, {MainFile, IOSTATE::UNINIT}}}); + compareResults(GroundTruth, Llvmtssolver); + +#if false 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); +#endif } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_09) { initialize({PathToLlFiles + "typestate_09_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); + + std::map> + GroundTruth; + const auto FooFile = + SrcCodeLocationEntry(5, 9, HA->getICFG().getFunction("foo")); + const auto FooRet = + SrcCodeLocationEntry(7, 3, HA->getICFG().getFunction("foo")); + const auto MainFile = + SrcCodeLocationEntry(11, 9, HA->getICFG().getFunction("main")); + const auto MainReturn = + SrcCodeLocationEntry(15, 3, HA->getICFG().getFunction("main")); + GroundTruth.insert({FooRet, {{FooFile, IOSTATE::OPENED}}}); + GroundTruth.insert( + {MainReturn, {{FooFile, IOSTATE::CLOSED}, {MainFile, IOSTATE::CLOSED}}}); + compareResults(GroundTruth, Llvmtssolver); +#if false const std::map> Gt = { // At exit in foo() {8, @@ -384,13 +492,37 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_09) { // At exit in main() {18, {{"4", IOSTATE::CLOSED}, {"10", IOSTATE::CLOSED}}}}; compareResults(Gt, Llvmtssolver); +#endif } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_10) { initialize({PathToLlFiles + "typestate_10_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); + + std::map> + GroundTruth; + const auto BarFile = + SrcCodeLocationEntry(5, 9, HA->getICFG().getFunction("bar")); + const auto BarRet = + SrcCodeLocationEntry(6, 3, HA->getICFG().getFunction("bar")); + const auto FooFile = + SrcCodeLocationEntry(10, 9, HA->getICFG().getFunction("foo")); + const auto FooRet = + SrcCodeLocationEntry(12, 3, HA->getICFG().getFunction("foo")); + const auto MainFile = + SrcCodeLocationEntry(16, 9, HA->getICFG().getFunction("main")); + const auto MainReturn = + SrcCodeLocationEntry(20, 3, HA->getICFG().getFunction("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); + +#if false const std::map> Gt = { // At exit in bar() {4, {{"2", IOSTATE::UNINIT}}}, @@ -406,13 +538,38 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_10) { {"5", IOSTATE::CLOSED}, {"13", IOSTATE::CLOSED}}}}; compareResults(Gt, Llvmtssolver); +#endif } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_11) { initialize({PathToLlFiles + "typestate_11_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); + + std::map> + GroundTruth; + const auto BarFile = + SrcCodeLocationEntry(4, 16, HA->getICFG().getFunction("bar")); + const auto BarRet = + SrcCodeLocationEntry(4, 32, HA->getICFG().getFunction("bar")); + const auto FooFile = + SrcCodeLocationEntry(6, 16, HA->getICFG().getFunction("foo")); + const auto FooRet = + SrcCodeLocationEntry(6, 49, HA->getICFG().getFunction("foo")); + const auto MainFile = + SrcCodeLocationEntry(9, 9, HA->getICFG().getFunction("main")); + const auto MainReturn = + SrcCodeLocationEntry(13, 3, HA->getICFG().getFunction("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); + +#if false + const std::map> Gt = { // At exit in bar(): closing uninitialized file-handle gives error-state {6, @@ -433,13 +590,34 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_11) { {19, {{"2", IOSTATE::ERROR}, {"7", IOSTATE::ERROR}, {"13", IOSTATE::ERROR}}}}; compareResults(Gt, Llvmtssolver); +#endif } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_12) { initialize({PathToLlFiles + "typestate_12_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); + + std::map> + GroundTruth; + const auto BarFile = + SrcCodeLocationEntry(5, 9, HA->getICFG().getFunction("bar")); + const auto BarRet = + SrcCodeLocationEntry(7, 3, HA->getICFG().getFunction("bar")); + const auto AfterFoo = + SrcCodeLocationEntry(15, 3, HA->getICFG().getFunction("main")); + const auto MainFile = + SrcCodeLocationEntry(13, 9, HA->getICFG().getFunction("main")); + const auto MainReturn = + SrcCodeLocationEntry(17, 3, HA->getICFG().getFunction("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); + +#if false const std::map> Gt = { // At exit in bar() {6, @@ -453,13 +631,29 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_12) { // At exit in main() {16, {{"2", IOSTATE::CLOSED}, {"10", IOSTATE::CLOSED}}}}; compareResults(Gt, Llvmtssolver); +#endif } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_13) { initialize({PathToLlFiles + "typestate_13_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); + + std::map> + GroundTruth; + const auto File = + SrcCodeLocationEntry(4, 9, HA->getICFG().getFunction("main")); + const auto BeforeFirstFClose = + SrcCodeLocationEntry(7, 3, HA->getICFG().getFunction("main")); + const auto BeforeSecondFClose = + SrcCodeLocationEntry(8, 3, HA->getICFG().getFunction("main")); + const auto Return = + SrcCodeLocationEntry(10, 3, HA->getICFG().getFunction("main")); + GroundTruth.insert({BeforeFirstFClose, {{File, IOSTATE::OPENED}}}); + GroundTruth.insert({BeforeSecondFClose, {{File, IOSTATE::CLOSED}}}); + GroundTruth.insert({Return, {{File, IOSTATE::ERROR}}}); + compareResults(GroundTruth, Llvmtssolver); +#if false const std::map> Gt = { // Before first fclose() {8, {{"3", IOSTATE::OPENED}}}, @@ -468,13 +662,38 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_13) { // At exit in main() {11, {{"3", IOSTATE::ERROR}}}}; compareResults(Gt, Llvmtssolver); +#endif } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_14) { initialize({PathToLlFiles + "typestate_14_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); + + std::map> + GroundTruth; + const auto File = + SrcCodeLocationEntry(4, 9, HA->getICFG().getFunction("main")); + const auto BeforeFirstFOpen = + SrcCodeLocationEntry(5, 5, HA->getICFG().getFunction("main")); + const auto BeforeSecondFOpen = + SrcCodeLocationEntry(6, 5, HA->getICFG().getFunction("main")); + const auto BeforeFClose = + SrcCodeLocationEntry(7, 3, HA->getICFG().getFunction("main")); + const auto Return = + SrcCodeLocationEntry(9, 3, HA->getICFG().getFunction("main")); + GroundTruth.insert({BeforeFirstFOpen, {{File, IOSTATE::UNINIT}}}); + GroundTruth.insert({BeforeSecondFOpen, {{File, IOSTATE::OPENED}}}); + GroundTruth.insert({BeforeFClose, + {{File, IOSTATE::OPENED}, + {BeforeFirstFOpen, IOSTATE::OPENED}, + {BeforeSecondFOpen, IOSTATE::OPENED}}}); + GroundTruth.insert({Return, + {{File, IOSTATE::CLOSED}, + {BeforeFirstFOpen, IOSTATE::CLOSED}, + {BeforeSecondFOpen, IOSTATE::CLOSED}}}); + compareResults(GroundTruth, Llvmtssolver); +#if false const std::map> Gt = { // Before first fopen() {7, {{"5", IOSTATE::UNINIT}}}, @@ -491,13 +710,49 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_14) { {"7", IOSTATE::CLOSED}, {"9", IOSTATE::CLOSED}}}}; compareResults(Gt, Llvmtssolver); +#endif } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_15) { initialize({PathToLlFiles + "typestate_15_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); + + std::map> + GroundTruth; + const auto File = + SrcCodeLocationEntry(4, 9, HA->getICFG().getFunction("main")); + const auto BeforeFirstFOpen = + SrcCodeLocationEntry(5, 5, HA->getICFG().getFunction("main")); + const auto BeforeFirstFClose = + SrcCodeLocationEntry(6, 3, HA->getICFG().getFunction("main")); + const auto BeforeSecondFOpen = + SrcCodeLocationEntry(7, 5, HA->getICFG().getFunction("main")); + const auto BeforeSecondFClose = + SrcCodeLocationEntry(8, 3, HA->getICFG().getFunction("main")); + const auto Return = + SrcCodeLocationEntry(10, 3, HA->getICFG().getFunction("main")); + // GroundTruth.insert( + // {BeforeFirstFOpen, + // {{File, IOSTATE::OPENED}, {BeforeFirstFOpen, IOSTATE::OPENED}}}); + GroundTruth.insert({BeforeFirstFClose, + {{File, IOSTATE::CLOSED}, + {BeforeFirstFClose, IOSTATE::CLOSED}, + {BeforeSecondFOpen, IOSTATE::CLOSED}}}); + GroundTruth.insert({BeforeSecondFClose, + {{File, IOSTATE::OPENED}, + {BeforeFirstFOpen, IOSTATE::CLOSED}, + {BeforeFirstFClose, IOSTATE::CLOSED}, + {BeforeSecondFOpen, IOSTATE::OPENED}}}); + GroundTruth.insert({Return, + {{File, IOSTATE::CLOSED}, + {BeforeFirstFOpen, IOSTATE::ERROR}, + {BeforeFirstFClose, IOSTATE::ERROR}, + {BeforeSecondFOpen, IOSTATE::CLOSED}, + {BeforeSecondFClose, IOSTATE::CLOSED}}}); + compareResults(GroundTruth, Llvmtssolver); + +#if false const std::map> Gt = { // After store of ret val of first fopen() {9, @@ -550,16 +805,44 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_15) { {"11", IOSTATE::CLOSED}, {"13", IOSTATE::CLOSED}}}}; compareResults(Gt, Llvmtssolver); +#endif } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_16) { /// TODO: After the EF fix everything is BOT; --> Make the TSA more precise! + /// TODO: fix these not being able to be cast into an instruction + initialize({PathToLlFiles + "typestate_16_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); + +#if false + + std::map> + GroundTruth; + const auto FooFile = + SrcCodeLocationEntry(4, 16, HA->getICFG().getFunction("main")); + + const auto FooExit = + SrcCodeLocationEntry(11, 1, HA->getICFG().getFunction("main")); + const auto MainFile = + SrcCodeLocationEntry(14, 9, HA->getICFG().getFunction("main")); + const auto MainReturn = + SrcCodeLocationEntry(19, 3, HA->getICFG().getFunction("main")); + GroundTruth.insert({FooExit, {{FooFile, IOSTATE::BOT}}}); + GroundTruth.insert({MainReturn, + { + {MainFile, IOSTATE::BOT}, + {FooFile, IOSTATE::BOT}, + }}); + compareResults(GroundTruth, Llvmtssolver); + +#endif + +#if false + // Llvmtssolver.dumpResults(); // auto Pts = PT->getAliasSet(IRDB->getInstruction(2)); @@ -589,15 +872,45 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_16) { {"18", IOSTATE::BOT}}}}; // Overapproximation due to too flat lattice // (would expect CLOSED for both)! compareResults(Gt, Llvmtssolver); +#endif } // TODO: Check this case again! TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_17) { initialize({PathToLlFiles + "typestate_17_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); + std::map> + GroundTruth; + const auto FooFile = + SrcCodeLocationEntry(4, 16, HA->getICFG().getFunction("foo")); + const auto File = + SrcCodeLocationEntry(8, 9, HA->getICFG().getFunction("main")); + const auto FOpenFile = + SrcCodeLocationEntry(8, 9, HA->getICFG().getFunction("main")); + const auto BeforeLoop = + SrcCodeLocationEntry(14, 3, HA->getICFG().getFunction("main")); + const auto BeforeFGetC = + SrcCodeLocationEntry(14, 13, HA->getICFG().getFunction("main")); + const auto MainReturn = + SrcCodeLocationEntry(17, 3, HA->getICFG().getFunction("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); + +#if false + const std::map> Gt = { // Before loop {15, @@ -619,6 +932,7 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_17) { // correct as well as BOT) }}}; compareResults(Gt, Llvmtssolver); +#endif } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_18) { @@ -626,8 +940,24 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_18) { initialize({PathToLlFiles + "typestate_18_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); + + std::map> + GroundTruth; + const auto FooReturn = + SrcCodeLocationEntry(11, 1, HA->getICFG().getFunction("foo")); + const auto FooFile = + SrcCodeLocationEntry(4, 16, HA->getICFG().getFunction("foo")); + const auto MainFile = + SrcCodeLocationEntry(14, 9, HA->getICFG().getFunction("main")); + const auto MainReturn = + SrcCodeLocationEntry(19, 3, HA->getICFG().getFunction("main")); + GroundTruth.insert({FooReturn, {{FooFile, IOSTATE::BOT}}}); + GroundTruth.insert( + {MainReturn, {{MainFile, IOSTATE::BOT}, {FooFile, IOSTATE::BOT}}}); + compareResults(GroundTruth, Llvmtssolver); + +#if false const std::map> Gt = { // At exit in foo() {17, @@ -642,23 +972,42 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_18) { {"19", IOSTATE::BOT}}}}; // Overapproximation due to too flat lattice // (would expect CLOSED for both)! compareResults(Gt, Llvmtssolver); +#endif } // TODO: Check this case again! TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_19) { initialize({PathToLlFiles + "typestate_19_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); - Llvmtssolver.solve(); + + std::map> + GroundTruth; + const auto FooBeforeOpen = + SrcCodeLocationEntry(4, 21, HA->getICFG().getFunction("foo")); + const auto FooFile = + SrcCodeLocationEntry(4, 16, HA->getICFG().getFunction("foo")); + const auto FooExit = + SrcCodeLocationEntry(4, 32, HA->getICFG().getFunction("foo")); + const auto MainFile = + SrcCodeLocationEntry(7, 9, HA->getICFG().getFunction("main")); + const auto MainReturn = + SrcCodeLocationEntry(18, 3, HA->getICFG().getFunction("main")); + GroundTruth.insert({FooBeforeOpen, {{FooFile, IOSTATE::UNINIT}}}); + GroundTruth.insert({FooExit, {{FooFile, IOSTATE::BOT}}}); + GroundTruth.insert( + {MainReturn, {{MainFile, IOSTATE::CLOSED}, {FooFile, IOSTATE::CLOSED}}}); + compareResults(GroundTruth, Llvmtssolver); + +#if false 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); -} - #endif +} // main function for the test case int main(int Argc, char **Argv) { From cbb542ade5da5746a464f3e090e8a426c76ed923 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Mon, 18 Aug 2025 20:24:14 +0200 Subject: [PATCH 26/35] UninitVarTest fixed all but one --- .../Problems/IDETSAnalysisFileIOTest.cpp | 2 +- .../IFDSUninitializedVariablesTest.cpp | 199 ++++++++++++++++-- unittests/TestUtils/SrcCodeLocationEntry.h | 26 ++- 3 files changed, 205 insertions(+), 22 deletions(-) diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp index f62961e4f0..eb68db6837 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp @@ -740,7 +740,7 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_15) { {BeforeFirstFClose, IOSTATE::CLOSED}, {BeforeSecondFOpen, IOSTATE::CLOSED}}}); GroundTruth.insert({BeforeSecondFClose, - {{File, IOSTATE::OPENED}, + {{File, IOSTATE::CLOSED}, {BeforeFirstFOpen, IOSTATE::CLOSED}, {BeforeFirstFClose, IOSTATE::CLOSED}, {BeforeSecondFOpen, IOSTATE::OPENED}}}); diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp index a0a466bb23..954be19b1f 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp @@ -55,15 +55,17 @@ class IFDSUninitializedVariablesTest : public ::testing::Test { void compareResults( const std::set> &GroundTruth) { - auto GroundTruthEntries = getGroundTruthInsts(GroundTruth); + auto GroundTruthEntries = getGroundTruthInsts(GroundTruth, true); std::set> FoundUninitUses; for (const auto &Kvp : UninitProblem->getAllUndefUses()) { const auto *SourceInst = Kvp.first; + llvm::outs() << "SourceInst: " << SourceInst << "\n"; llvm::outs() << "*SourceInst: " << *SourceInst << "\n"; for (const auto *UV : Kvp.second) { + llvm::outs() << "UV: " << UV << "\n"; llvm::outs() << "*UV: " << *UV << "\n"; FoundUninitUses.insert({SourceInst, UV}); } @@ -77,6 +79,7 @@ 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 std::set> GroundTruth; compareResults(GroundTruth); @@ -89,16 +92,16 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_02_SHOULD_LEAK) { // binop_uninit uses uninitialized variable i in 'int j = i + 10;' std::set> GroundTruth; + // %4 = load i32, i32* %2, ID: 6 ; %2 is the uninitialized variable i // %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 - const auto Entry = - SrcCodeLocationEntry(2, 0, HA->getICFG().getIRDB()->getFunction("main")); + SrcCodeLocationEntry(2, 0, HA->getICFG().getFunction("main")); const auto EntryTwo = - SrcCodeLocationEntry(3, 11, HA->getICFG().getIRDB()->getFunction("main")); + SrcCodeLocationEntry(3, 11, HA->getICFG().getFunction("main")); const auto EntryThree = - SrcCodeLocationEntry(3, 13, HA->getICFG().getIRDB()->getFunction("main")); + SrcCodeLocationEntry(3, 13, HA->getICFG().getFunction("main")); GroundTruth.insert({EntryTwo, Entry}); GroundTruth.insert({EntryThree, EntryTwo}); @@ -112,6 +115,21 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_03_SHOULD_LEAK) { // callnoret uses uninitialized variable a in 'return a + 10;' of addTen(int) std::set> GroundTruth; + + const auto IntA = + SrcCodeLocationEntry(7, 7, HA->getICFG().getFunction("main")); + const auto CopyA = + SrcCodeLocationEntry(9, 10, HA->getICFG().getFunction("main")); + const auto ArgA = + SrcCodeLocationEntry(1, 16, HA->getICFG().getFunction("addTen")); + const auto LoadA = + SrcCodeLocationEntry(3, 10, HA->getICFG().getFunction("addTen")); + const auto Add = + SrcCodeLocationEntry(3, 12, HA->getICFG().getFunction("addTen")); + GroundTruth.insert({CopyA, IntA}); + GroundTruth.insert({Add, LoadA}); + GroundTruth.insert({LoadA, ArgA}); + #if false // %4 = load i32, i32* %2 ; %2 is the parameter a of addTen(int) containing // undef @@ -127,31 +145,36 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_03_SHOULD_LEAK) { compareResults(GroundTruth); } -#if false 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; + std::set> 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; + std::set> 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; + std::set> GroundTruth; + compareResults(GroundTruth); } /**************************************************************************************** @@ -173,12 +196,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; + std::set> GroundTruth; + compareResults(GroundTruth); } /**************************************************************************************** @@ -198,17 +224,31 @@ 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; + std::set> GroundTruth; + + // TODO: ask fabian why I have to use _Z3foov as the name here, but above I + // could just use the normal function name. + const auto IntI = + SrcCodeLocationEntry(2, 7, HA->getICFG().getFunction("_Z3foov")); + const auto UseOfI = + SrcCodeLocationEntry(3, 10, HA->getICFG().getFunction("_Z3foov")); + + GroundTruth.insert({UseOfI, IntI}); + +#if false //%2 = load i32, i32 %1 GroundTruth[2] = {"0"}; // What about this call? // %3 = call i32 @_Z3foov() // GroundTruth[8] = {""}; +#endif compareResults(GroundTruth); } @@ -217,15 +257,27 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_11_SHOULD_NOT_LEAK) { initialize({PathToLlFiles + "sanitizer_cpp_dbg.ll"}); IFDSSolver Solver(*UninitProblem, &HA->getICFG()); Solver.solve(); - map> GroundTruth; + + std::set> GroundTruth; // all undef-uses are sanitized; // However, the uninitialized variable j is read, which causes the analysis to // report an undef-use // 6 => {2} + const auto IntI = + SrcCodeLocationEntry(3, 7, HA->getICFG().getFunction("main")); + const auto UseOfI = + SrcCodeLocationEntry(4, 7, HA->getICFG().getFunction("main")); + + GroundTruth.insert({UseOfI, IntI}); + +#if false GroundTruth[6] = {"2"}; +#endif + compareResults(GroundTruth); } + //--------------------------------------------------------------------- // Not relevant any more; Test case covered by UninitTest_11 //--------------------------------------------------------------------- @@ -247,21 +299,51 @@ 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"}; + std::set> GroundTruth; + + const auto IntJ = + SrcCodeLocationEntry(3, 7, HA->getICFG().getFunction("main")); + const auto LoadJ = + SrcCodeLocationEntry(5, 7, HA->getICFG().getFunction("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; + + std::set> GroundTruth; + + const auto IntA = + SrcCodeLocationEntry(2, 7, HA->getICFG().getFunction("main")); + const auto IntB = + SrcCodeLocationEntry(3, 7, HA->getICFG().getFunction("main")); + const auto LoadA = + SrcCodeLocationEntry(6, 11, HA->getICFG().getFunction("main")); + const auto Multiply = + SrcCodeLocationEntry(6, 13, HA->getICFG().getFunction("main")); + const auto LoadB = + SrcCodeLocationEntry(6, 15, HA->getICFG().getFunction("main")); + + GroundTruth.insert({LoadA, IntA}); + GroundTruth.insert({LoadB, IntB}); + GroundTruth.insert({Multiply, LoadA}); + GroundTruth.insert({Multiply, LoadB}); + +#if false GroundTruth[14] = {"1"}; GroundTruth[15] = {"2"}; GroundTruth[16] = {"14", "15"}; +#endif + compareResults(GroundTruth); } /**************************************************************************************** @@ -297,19 +379,43 @@ 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; + std::set> GroundTruth; + + const auto ArgX = + SrcCodeLocationEntry(1, 18, HA->getICFG().getFunction("_Z8functionii")); + const auto IntI = + SrcCodeLocationEntry(2, 7, HA->getICFG().getFunction("_Z8functionii")); + const auto LoadX = + SrcCodeLocationEntry(3, 11, HA->getICFG().getFunction("_Z8functionii")); + const auto LoadI = + SrcCodeLocationEntry(5, 10, HA->getICFG().getFunction("_Z8functionii")); + const auto Add = + SrcCodeLocationEntry(5, 12, HA->getICFG().getFunction("_Z8functionii")); + const auto IntJ = + SrcCodeLocationEntry(10, 7, HA->getICFG().getFunction("main")); + const auto LoadJ = + SrcCodeLocationEntry(12, 16, HA->getICFG().getFunction("main")); + + GroundTruth.insert({LoadX, ArgX}); + GroundTruth.insert({LoadI, IntI}); + GroundTruth.insert({Add, LoadI}); + GroundTruth.insert({LoadJ, IntJ}); + +#if false // TODO remove GT[11] GroundTruth[11] = {"0"}; GroundTruth[16] = {"2"}; GroundTruth[18] = {"16"}; GroundTruth[34] = {"24"}; +#endif compareResults(GroundTruth); } @@ -367,13 +473,36 @@ 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; + std::set> GroundTruth; + + const auto ArgAddrX = + SrcCodeLocationEntry(2, 15, HA->getICFG().getFunction("main")); + const auto LoadX = + SrcCodeLocationEntry(4, 12, HA->getICFG().getFunction("main")); + const auto LoadXTwo = + SrcCodeLocationEntry(5, 14, HA->getICFG().getFunction("main")); + const auto IntI = + SrcCodeLocationEntry(9, 7, HA->getICFG().getFunction("main")); + const auto LoadI = + SrcCodeLocationEntry(10, 15, HA->getICFG().getFunction("main")); + + // TODO: ask fabian why the original unittest ground truth has 5 elements + // TODO: Also, why doesn't this crash if I say getFunction("main") when + // looking at insts in foo? + + GroundTruth.insert({LoadI, IntI}); + GroundTruth.insert({LoadX, ArgAddrX}); + GroundTruth.insert({LoadXTwo, ArgAddrX}); + +#if false + // Leaks at 11 and 14 due to field-insensitivity GroundTruth[11] = {"2"}; GroundTruth[14] = {"2"}; @@ -387,13 +516,44 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_20_SHOULD_LEAK) { // Analysis does not check uninit on actualparameters // GroundTruth[32] = {"31"}; compareResults(GroundTruth); + +#endif } + TEST_F(IFDSUninitializedVariablesTest, UninitTest_21_SHOULD_LEAK) { initialize({PathToLlFiles + "virtual_call_cpp_dbg.ll"}); IFDSSolver Solver(*UninitProblem, &HA->getICFG()); Solver.solve(); + std::set> GroundTruth; + + const auto FooXAddr = + SrcCodeLocationEntry(3, 15, HA->getICFG().getFunction("_Z3fooRi")); + const auto FooXLoad = + SrcCodeLocationEntry(3, 27, HA->getICFG().getFunction("_Z3fooRi")); + const auto BarXAddr = + SrcCodeLocationEntry(4, 15, HA->getICFG().getFunction("_Z3fooRi")); + const auto LoadX = + SrcCodeLocationEntry(6, 10, HA->getICFG().getFunction("_Z3barRi")); + const auto IntI = + SrcCodeLocationEntry(9, 7, HA->getICFG().getFunction("main")); + const auto IntJ = + SrcCodeLocationEntry(16, 7, HA->getICFG().getFunction("main")); + const auto BazCall = + SrcCodeLocationEntry(16, 11, HA->getICFG().getFunction("main")); + const auto LoadJ = + SrcCodeLocationEntry(17, 10, HA->getICFG().getFunction("main")); + // is passed as a reference, so I isn't being loaded here + // const auto LoadI = + // SrcCodeLocationEntry(16, 15, HA->getICFG().getFunction("main")); + + GroundTruth.insert({FooXLoad, IntI}); + GroundTruth.insert({FooXLoad, IntJ}); + GroundTruth.insert({LoadX, BarXAddr}); + GroundTruth.insert({LoadX, IntJ}); + GroundTruth.insert({LoadX, IntJ}); +#if false map> GroundTruth = { {3, {"0"}}, {8, {"5"}}, {10, {"5"}}, {35, {"34"}}, {37, {"17"}}}; // 3 => {0}; due to field-insensitivity @@ -401,11 +561,10 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_21_SHOULD_LEAK) { // 10 => {5}; due to alias-unawareness // 35 => {34}; actual leak // 37 => {17}; actual leak +#endif compareResults(GroundTruth); } -#endif - int main(int Argc, char **Argv) { ::testing::InitGoogleTest(&Argc, Argv); return RUN_ALL_TESTS(); diff --git a/unittests/TestUtils/SrcCodeLocationEntry.h b/unittests/TestUtils/SrcCodeLocationEntry.h index 4cce34bcf4..8984bd2311 100644 --- a/unittests/TestUtils/SrcCodeLocationEntry.h +++ b/unittests/TestUtils/SrcCodeLocationEntry.h @@ -2,6 +2,7 @@ #define PHASAR_UTILS_SRCCODELOCATIONENTRY_H #include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" +#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "phasar/Utils/Utilities.h" #include "llvm/ADT/Hashing.h" @@ -450,7 +451,8 @@ getValueFromEntryOrNull(const SrcCodeLocationEntry &Entry) { inline std::set> getGroundTruthInsts( const std::set> - &GroundTruth) { + &GroundTruth, + bool PrintData = false) { std::set> GroundTruthEntries; @@ -461,13 +463,35 @@ getGroundTruthInsts( const llvm::Value *CurrVal = getValueFromEntryOrNull(SecondEntry); if (!CurrInst) { + if (PrintData) { + llvm::outs() << "FirstEntry.Line: " << FirstEntry.Line + << " - FirstEntry.Column: " << FirstEntry.Column << "\n"; + } + llvm::report_fatal_error("Couldn't cast first entry to instruction\n"); continue; } if (!CurrVal) { + if (PrintData) { + llvm::outs() << "SecondEntry.Line: " << SecondEntry.Line + << " - SecondEntry.Column: " << SecondEntry.Column << "\n"; + } + llvm::report_fatal_error("Couldn't cast second entry to value\n"); continue; } + if (PrintData) { + llvm::outs() << "FirstEntry.Line: " << FirstEntry.Line + << " - FirstEntry.Column: " << FirstEntry.Column << "\n"; + llvm::outs() << "CurrInst: " << CurrInst << "\n"; + llvm::outs() << "llvmIRToString(CurrInst): " << llvmIRToString(CurrInst) + << "\n"; + llvm::outs() << "\nSecondEntry.Line: " << SecondEntry.Line + << " - SecondEntry.Column: " << SecondEntry.Column << "\n"; + llvm::outs() << "CurrVal: " << CurrVal << "\n"; + llvm::outs() << "llvmIRToString(CurrVal): " << llvmIRToString(CurrVal) + << "\n"; + } GroundTruthEntries.insert({CurrInst, CurrVal}); } From eda263799bc6eebb1972667f0da4691a195783f1 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Wed, 20 Aug 2025 22:33:15 +0200 Subject: [PATCH 27/35] fixed all but 03 of TSAnalysisFile --- .../Problems/IDETSAnalysisFileIOTest.cpp | 504 +++++------------- .../IFDSUninitializedVariablesTest.cpp | 104 ++-- 2 files changed, 181 insertions(+), 427 deletions(-) diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp index eb68db6837..2880e245c0 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp @@ -155,26 +155,9 @@ class IDETSAnalysisFileIOTest : public ::testing::Test { << "[Error]: Couldn't cast FirstResult to Instruction.\n"; } } - EXPECT_EQ(Results, GT) << "At " << llvmIRToShortString(CurrInst); - } -#if false - 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))); - } - } - EXPECT_EQ(Results, GT) << "At " << llvmIRToShortString(Inst); + EXPECT_EQ(Results, GT) << "At " << llvmIRToShortString(CurrInst); } -#endif } }; // Test Fixture @@ -182,10 +165,6 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_01) { 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}}}}; std::map> GroundTruth; @@ -225,21 +204,40 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_03) { std::map> GroundTruth; + // %f = alloca ptr, align 8 const auto MainFile = SrcCodeLocationEntry(6, 9, HA->getICFG().getFunction("main")); + // %f.addr = alloca ptr, align 8 const auto FooFile = SrcCodeLocationEntry(3, 16, HA->getICFG().getFunction("foo")); - const auto FooBegin = + const auto FooFClose = SrcCodeLocationEntry(3, 21, HA->getICFG().getFunction("foo")); + // %0 = load ptr, ptr %f + const auto PassFToFClose = + SrcCodeLocationEntry(3, 28, HA->getICFG().getFunction("foo")); + // ret void const auto FooRet = SrcCodeLocationEntry(3, 32, HA->getICFG().getFunction("foo")); + // %0 = load ptr, ptr %f, align 8 + const auto PassFToFoo = + SrcCodeLocationEntry(9, 7, HA->getICFG().getFunction("main")); + // ret i32 0 const auto Return = SrcCodeLocationEntry(11, 3, HA->getICFG().getFunction("main")); - GroundTruth.insert({FooBegin, {{FooFile, IOSTATE::OPENED}}}); - GroundTruth.insert({FooRet, {{FooFile, IOSTATE::CLOSED}}}); - GroundTruth.insert({Return, {{MainFile, IOSTATE::CLOSED}}}); + // Entry in foo() + GroundTruth.insert({FooFClose, {{FooFile, IOSTATE::OPENED}}}); + // Exit in foo() + GroundTruth.insert({FooRet, + {{FooFile, IOSTATE::CLOSED}, + {FooFClose, IOSTATE::CLOSED}, + {PassFToFClose, IOSTATE::CLOSED}}}); + // Exit in main() + GroundTruth.insert({Return, + {{FooFClose, IOSTATE::CLOSED}, + {MainFile, IOSTATE::CLOSED}, + {PassFToFoo, IOSTATE::CLOSED}}}); compareResults(GroundTruth, Llvmtssolver); - +// TODO: go over old and new ground truth with fabian #if false // llvmtssolver.printReport(); const std::map> Gt = { @@ -295,29 +293,25 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_05) { GroundTruth; const auto File = SrcCodeLocationEntry(6, 9, HA->getICFG().getFunction("main")); + const auto CallFOpen = + SrcCodeLocationEntry(7, 7, HA->getICFG().getFunction("main")); const auto AfterFOpen = SrcCodeLocationEntry(8, 7, HA->getICFG().getFunction("main")); + const auto LoadFile = + SrcCodeLocationEntry(9, 12, HA->getICFG().getFunction("main")); const auto AfterFClose = SrcCodeLocationEntry(10, 3, HA->getICFG().getFunction("main")); const auto Return = SrcCodeLocationEntry(11, 3, HA->getICFG().getFunction("main")); - GroundTruth.insert({AfterFOpen, {{File, IOSTATE::OPENED}}}); - GroundTruth.insert({AfterFClose, {{File, IOSTATE::CLOSED}}}); - GroundTruth.insert({Return, {{File, IOSTATE::BOT}}}); + 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); -#if false - 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); -#endif } // TODO: fix @@ -374,61 +368,51 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_07) { std::map> GroundTruth; + // %f.addr = alloca ptr, align 8 const auto FooFile = SrcCodeLocationEntry(3, 16, HA->getICFG().getFunction("foo")); - const auto FooExit = + // ret void + const auto FooRet = SrcCodeLocationEntry(3, 32, HA->getICFG().getFunction("foo")); - const auto File = + // %f = alloca ptr, align 8 + const auto MainFile = SrcCodeLocationEntry(6, 9, HA->getICFG().getFunction("main")); - const auto FClose = + // %0 = load ptr, ptr %f, align 8 + const auto MainFileLoad = + SrcCodeLocationEntry(7, 10, HA->getICFG().getFunction("main")); + // %call = call i32 @fclose(ptr noundef %0) + const auto CallFClose = SrcCodeLocationEntry(7, 3, HA->getICFG().getFunction("main")); - const auto AfterFClose = + // %call1 = call noalias ptr @fopen(ptr noundef @.str, ptr noundef @.str.1) + const auto Call1FOpen = + SrcCodeLocationEntry(8, 7, HA->getICFG().getFunction("main")); + // store ptr %call1, ptr %f, align 8 + const auto StoreOfCall1 = SrcCodeLocationEntry(8, 5, HA->getICFG().getFunction("main")); - const auto AfterFOpen = - SrcCodeLocationEntry(10, 3, HA->getICFG().getFunction("main")); - const auto FForFoo = + // %1 = load ptr, ptr %f, align 8 + const auto LoadMainFile = SrcCodeLocationEntry(10, 7, HA->getICFG().getFunction("main")); - GroundTruth.insert({FooExit, {{FooFile, IOSTATE::CLOSED}}}); - GroundTruth.insert({FClose, {{File, IOSTATE::UNINIT}}}); - GroundTruth.insert({AfterFClose, {{File, IOSTATE::ERROR}}}); - // TODO: fix IOSTATE::OPENED part below failing - GroundTruth.insert({AfterFOpen, - {{File, IOSTATE::ERROR}, - {AfterFClose, IOSTATE::ERROR}, - {FForFoo, IOSTATE::OPENED}}}); -#if false - // GroundTruth.insert({, {{, IOSTATE::ERROR}}}); - // GroundTruth.insert({, {{, IOSTATE::CLOSED}}}); -#endif - compareResults(GroundTruth, Llvmtssolver); + // ret i32 0 + const auto MainReturn = + SrcCodeLocationEntry(12, 3, HA->getICFG().getFunction("main")); -#if false - 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); -#endif + 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) { @@ -450,15 +434,6 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_08) { GroundTruth.insert( {MainReturn, {{FooFile, IOSTATE::OPENED}, {MainFile, IOSTATE::UNINIT}}}); compareResults(GroundTruth, Llvmtssolver); - -#if false - 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); -#endif } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_09) { @@ -480,19 +455,6 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_09) { GroundTruth.insert( {MainReturn, {{FooFile, IOSTATE::CLOSED}, {MainFile, IOSTATE::CLOSED}}}); compareResults(GroundTruth, Llvmtssolver); -#if false - 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); -#endif } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_10) { @@ -521,24 +483,6 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_10) { {FooFile, IOSTATE::CLOSED}, {MainFile, IOSTATE::CLOSED}}}); compareResults(GroundTruth, Llvmtssolver); - -#if false - 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); -#endif } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_11) { @@ -567,30 +511,6 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_11) { {FooFile, IOSTATE::ERROR}, {MainFile, IOSTATE::ERROR}}}); compareResults(GroundTruth, Llvmtssolver); - -#if false - - 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); -#endif } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_12) { @@ -616,22 +536,6 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_12) { GroundTruth.insert( {MainReturn, {{MainFile, IOSTATE::CLOSED}, {BarFile, IOSTATE::CLOSED}}}); compareResults(GroundTruth, Llvmtssolver); - -#if false - 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); -#endif } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_13) { @@ -653,16 +557,6 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_13) { GroundTruth.insert({BeforeSecondFClose, {{File, IOSTATE::CLOSED}}}); GroundTruth.insert({Return, {{File, IOSTATE::ERROR}}}); compareResults(GroundTruth, Llvmtssolver); -#if false - 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); -#endif } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_14) { @@ -693,24 +587,6 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_14) { {BeforeFirstFOpen, IOSTATE::CLOSED}, {BeforeSecondFOpen, IOSTATE::CLOSED}}}); compareResults(GroundTruth, Llvmtssolver); -#if false - 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); -#endif } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_15) { @@ -720,162 +596,79 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_15) { std::map> GroundTruth; + // 5: %f = alloca ptr, align 8 const auto File = SrcCodeLocationEntry(4, 9, HA->getICFG().getFunction("main")); - const auto BeforeFirstFOpen = - SrcCodeLocationEntry(5, 5, HA->getICFG().getFunction("main")); - const auto BeforeFirstFClose = - SrcCodeLocationEntry(6, 3, HA->getICFG().getFunction("main")); - const auto BeforeSecondFOpen = + // %call = call noalias ptr @fopen + const auto FOpen = + SrcCodeLocationEntry(5, 7, HA->getICFG().getFunction("main")); + // %0 = load ptr, ptr %f, align 8 + const auto LoadFile = + SrcCodeLocationEntry(6, 10, HA->getICFG().getFunction("main")); + // %call2 = call noalias ptr @fopen + const auto SecondFOpen = + SrcCodeLocationEntry(7, 7, HA->getICFG().getFunction("main")); + // store ptr %call2, ptr %f, align 8 + const auto StoreSecondFOpen = SrcCodeLocationEntry(7, 5, HA->getICFG().getFunction("main")); - const auto BeforeSecondFClose = - SrcCodeLocationEntry(8, 3, HA->getICFG().getFunction("main")); + // %1 = load ptr, ptr %f, align 8 + const auto SecondLoadFile = + SrcCodeLocationEntry(8, 10, HA->getICFG().getFunction("main")); + // ret i32 0 const auto Return = SrcCodeLocationEntry(10, 3, HA->getICFG().getFunction("main")); - // GroundTruth.insert( - // {BeforeFirstFOpen, - // {{File, IOSTATE::OPENED}, {BeforeFirstFOpen, IOSTATE::OPENED}}}); - GroundTruth.insert({BeforeFirstFClose, + + GroundTruth.insert( + {LoadFile, {{File, IOSTATE::OPENED}, {FOpen, IOSTATE::OPENED}}}); + GroundTruth.insert({SecondFOpen, {{File, IOSTATE::CLOSED}, - {BeforeFirstFClose, IOSTATE::CLOSED}, - {BeforeSecondFOpen, IOSTATE::CLOSED}}}); - GroundTruth.insert({BeforeSecondFClose, + {FOpen, IOSTATE::CLOSED}, + {LoadFile, IOSTATE::CLOSED}}}); + GroundTruth.insert({StoreSecondFOpen, {{File, IOSTATE::CLOSED}, - {BeforeFirstFOpen, IOSTATE::CLOSED}, - {BeforeFirstFClose, IOSTATE::CLOSED}, - {BeforeSecondFOpen, IOSTATE::OPENED}}}); + {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}, - {BeforeFirstFOpen, IOSTATE::ERROR}, - {BeforeFirstFClose, IOSTATE::ERROR}, - {BeforeSecondFOpen, IOSTATE::CLOSED}, - {BeforeSecondFClose, IOSTATE::CLOSED}}}); + {FOpen, IOSTATE::ERROR}, + {LoadFile, IOSTATE::ERROR}, + {SecondFOpen, IOSTATE::CLOSED}, + {SecondLoadFile, IOSTATE::CLOSED}}}); compareResults(GroundTruth, Llvmtssolver); - -#if false - 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); -#endif } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_16) { /// TODO: After the EF fix everything is BOT; --> Make the TSA more precise! - /// TODO: fix these not being able to be cast into an instruction - initialize({PathToLlFiles + "typestate_16_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); Llvmtssolver.solve(); -#if false - std::map> GroundTruth; const auto FooFile = - SrcCodeLocationEntry(4, 16, HA->getICFG().getFunction("main")); - + SrcCodeLocationEntry(4, 16, HA->getICFG().getFunction("foo")); const auto FooExit = - SrcCodeLocationEntry(11, 1, HA->getICFG().getFunction("main")); + SrcCodeLocationEntry(11, 1, HA->getICFG().getFunction("foo")); const auto MainFile = SrcCodeLocationEntry(14, 9, HA->getICFG().getFunction("main")); const auto MainReturn = SrcCodeLocationEntry(19, 3, HA->getICFG().getFunction("main")); + // At exit in foo() GroundTruth.insert({FooExit, {{FooFile, IOSTATE::BOT}}}); - GroundTruth.insert({MainReturn, - { - {MainFile, IOSTATE::BOT}, - {FooFile, IOSTATE::BOT}, - }}); + // At exit in main() + GroundTruth.insert( + {MainReturn, {{FooFile, IOSTATE::BOT}, {MainFile, IOSTATE::BOT}}}); compareResults(GroundTruth, Llvmtssolver); - -#endif - -#if false - - // 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); -#endif } -// TODO: Check this case again! TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_17) { initialize({PathToLlFiles + "typestate_17_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); @@ -908,31 +701,6 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_17) { {File, IOSTATE::BOT}, {FOpenFile, IOSTATE::BOT}}}); compareResults(GroundTruth, Llvmtssolver); - -#if false - - 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); -#endif } TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_18) { @@ -956,26 +724,8 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_18) { GroundTruth.insert( {MainReturn, {{MainFile, IOSTATE::BOT}, {FooFile, IOSTATE::BOT}}}); compareResults(GroundTruth, Llvmtssolver); - -#if false - 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); -#endif } -// TODO: Check this case again! TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_19) { initialize({PathToLlFiles + "typestate_19_c_dbg.ll"}); IDESolver Llvmtssolver(*TSProblem, &HA->getICFG()); @@ -983,30 +733,22 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_19) { std::map> GroundTruth; - const auto FooBeforeOpen = - SrcCodeLocationEntry(4, 21, HA->getICFG().getFunction("foo")); const auto FooFile = SrcCodeLocationEntry(4, 16, HA->getICFG().getFunction("foo")); - const auto FooExit = - SrcCodeLocationEntry(4, 32, HA->getICFG().getFunction("foo")); const auto MainFile = SrcCodeLocationEntry(7, 9, HA->getICFG().getFunction("main")); + const auto WhileCond = + SrcCodeLocationEntry(11, 3, HA->getICFG().getFunction("main")); + const auto StoreCall = + SrcCodeLocationEntry(11, 13, HA->getICFG().getFunction("main")); const auto MainReturn = SrcCodeLocationEntry(18, 3, HA->getICFG().getFunction("main")); - GroundTruth.insert({FooBeforeOpen, {{FooFile, IOSTATE::UNINIT}}}); - GroundTruth.insert({FooExit, {{FooFile, IOSTATE::BOT}}}); + + GroundTruth.insert({WhileCond, {{MainFile, IOSTATE::UNINIT}}}); + GroundTruth.insert({StoreCall, {{MainFile, IOSTATE::BOT}}}); GroundTruth.insert( - {MainReturn, {{MainFile, IOSTATE::CLOSED}, {FooFile, IOSTATE::CLOSED}}}); + {MainReturn, {{FooFile, IOSTATE::CLOSED}, {MainFile, IOSTATE::CLOSED}}}); compareResults(GroundTruth, Llvmtssolver); - -#if false - 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); -#endif } // main function for the test case diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp index 954be19b1f..8b8885c624 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp @@ -13,6 +13,7 @@ #include "llvm/IR/Function.h" #include "llvm/IR/Instruction.h" +#include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" #include "llvm/IR/Value.h" @@ -66,7 +67,7 @@ class IFDSUninitializedVariablesTest : public ::testing::Test { for (const auto *UV : Kvp.second) { llvm::outs() << "UV: " << UV << "\n"; - llvm::outs() << "*UV: " << *UV << "\n"; + llvm::outs() << "*UV: " << *UV << "\n\n"; FoundUninitUses.insert({SourceInst, UV}); } } @@ -130,19 +131,6 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_03_SHOULD_LEAK) { GroundTruth.insert({Add, LoadA}); GroundTruth.insert({LoadA, ArgA}); -#if false - // %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"}; -#endif - compareResults(GroundTruth); } @@ -230,11 +218,8 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_10_SHOULD_LEAK) { IFDSSolver Solver(*UninitProblem, &HA->getICFG()); Solver.solve(); - UninitProblem->emitTextReport(Solver.getSolverResults(), llvm::outs()); std::set> GroundTruth; - // TODO: ask fabian why I have to use _Z3foov as the name here, but above I - // could just use the normal function name. const auto IntI = SrcCodeLocationEntry(2, 7, HA->getICFG().getFunction("_Z3foov")); const auto UseOfI = @@ -242,13 +227,6 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_10_SHOULD_LEAK) { GroundTruth.insert({UseOfI, IntI}); -#if false - //%2 = load i32, i32 %1 - GroundTruth[2] = {"0"}; - // What about this call? - // %3 = call i32 @_Z3foov() - // GroundTruth[8] = {""}; -#endif compareResults(GroundTruth); } @@ -271,10 +249,6 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_11_SHOULD_NOT_LEAK) { GroundTruth.insert({UseOfI, IntI}); -#if false - GroundTruth[6] = {"2"}; -#endif - compareResults(GroundTruth); } @@ -338,14 +312,9 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_14_SHOULD_LEAK) { GroundTruth.insert({Multiply, LoadA}); GroundTruth.insert({Multiply, LoadB}); -#if false - GroundTruth[14] = {"1"}; - GroundTruth[15] = {"2"}; - GroundTruth[16] = {"14", "15"}; -#endif - compareResults(GroundTruth); } + /**************************************************************************************** * Fails probably due to field-insensitivity * @@ -403,11 +372,12 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_16_SHOULD_LEAK) { const auto LoadJ = SrcCodeLocationEntry(12, 16, HA->getICFG().getFunction("main")); + // TODO: rewrite comment below + // TODO remove GT[11] GroundTruth.insert({LoadX, ArgX}); GroundTruth.insert({LoadI, IntI}); GroundTruth.insert({Add, LoadI}); GroundTruth.insert({LoadJ, IntJ}); - #if false // TODO remove GT[11] GroundTruth[11] = {"0"}; @@ -483,24 +453,53 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_20_SHOULD_LEAK) { std::set> GroundTruth; const auto ArgAddrX = - SrcCodeLocationEntry(2, 15, HA->getICFG().getFunction("main")); + SrcCodeLocationEntry(2, 15, HA->getICFG().getFunction("_Z3fooRii")); const auto LoadX = - SrcCodeLocationEntry(4, 12, HA->getICFG().getFunction("main")); + SrcCodeLocationEntry(4, 12, HA->getICFG().getFunction("_Z3fooRii")); const auto LoadXTwo = - SrcCodeLocationEntry(5, 14, HA->getICFG().getFunction("main")); + SrcCodeLocationEntry(5, 14, HA->getICFG().getFunction("_Z3fooRii")); + const auto FooExit = + SrcCodeLocationEntry(6, 1, HA->getICFG().getFunction("_Z3fooRii")); + // const auto IntN = + // SrcCodeLocationEntry(3, 7, HA->getICFG().getFunction("_Z3fooRii")); const auto IntI = SrcCodeLocationEntry(9, 7, HA->getICFG().getFunction("main")); - const auto LoadI = - SrcCodeLocationEntry(10, 15, HA->getICFG().getFunction("main")); + const auto IntJ = + SrcCodeLocationEntry(10, 7, HA->getICFG().getFunction("main")); + const auto RetOfFoo = + SrcCodeLocationEntry(10, 11, HA->getICFG().getFunction("main")); + const auto LoadJ = + SrcCodeLocationEntry(11, 18, HA->getICFG().getFunction("main")); // TODO: ask fabian why the original unittest ground truth has 5 elements // TODO: Also, why doesn't this crash if I say getFunction("main") when // looking at insts in foo? - GroundTruth.insert({LoadI, IntI}); + // GroundTruth.insert({LoadXTwo, IntI}); + + // Leaks due to field-insensitivity GroundTruth.insert({LoadX, ArgAddrX}); GroundTruth.insert({LoadXTwo, ArgAddrX}); + // Load uninitialized variable i + // GroundTruth.insert({LoadI, IntI}); + + // Load recursive return-value for returning it + GroundTruth.insert({LoadJ, IntJ}); + // + // // 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); + #if false // Leaks at 11 and 14 due to field-insensitivity @@ -532,8 +531,11 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_21_SHOULD_LEAK) { SrcCodeLocationEntry(3, 15, HA->getICFG().getFunction("_Z3fooRi")); const auto FooXLoad = SrcCodeLocationEntry(3, 27, HA->getICFG().getFunction("_Z3fooRi")); + const auto BarXAddr = - SrcCodeLocationEntry(4, 15, HA->getICFG().getFunction("_Z3fooRi")); + SrcCodeLocationEntry(4, 15, HA->getICFG().getFunction("_Z3barRi")); + const auto Load = + SrcCodeLocationEntry(5, 3, HA->getICFG().getFunction("_Z3barRi")); const auto LoadX = SrcCodeLocationEntry(6, 10, HA->getICFG().getFunction("_Z3barRi")); const auto IntI = @@ -542,17 +544,27 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_21_SHOULD_LEAK) { SrcCodeLocationEntry(16, 7, HA->getICFG().getFunction("main")); const auto BazCall = SrcCodeLocationEntry(16, 11, HA->getICFG().getFunction("main")); + const auto BazCall2 = + SrcCodeLocationEntry(16, 11, HA->getICFG().getFunction("main")); const auto LoadJ = SrcCodeLocationEntry(17, 10, HA->getICFG().getFunction("main")); // is passed as a reference, so I isn't being loaded here // const auto LoadI = // SrcCodeLocationEntry(16, 15, HA->getICFG().getFunction("main")); - GroundTruth.insert({FooXLoad, IntI}); - GroundTruth.insert({FooXLoad, IntJ}); + // 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}); - GroundTruth.insert({LoadX, IntJ}); - GroundTruth.insert({LoadX, IntJ}); + // 35 => {34}; actual leak + GroundTruth.insert({BazCall, IntJ}); + // 37 => {17}; actual leak + GroundTruth.insert({BazCall2, IntJ}); + #if false map> GroundTruth = { {3, {"0"}}, {8, {"5"}}, {10, {"5"}}, {35, {"34"}}, {37, {"17"}}}; From 52ff60c57ca2bde819e14e4671880f07283fe564 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Thu, 21 Aug 2025 16:55:32 +0200 Subject: [PATCH 28/35] Fixed all but one test --- .../Problems/IDETSAnalysisFileIOTest.cpp | 11 ++- .../IFDSUninitializedVariablesTest.cpp | 79 ++++++++++++++----- 2 files changed, 65 insertions(+), 25 deletions(-) diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp index 2880e245c0..83162391d6 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp @@ -210,8 +210,8 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_03) { // %f.addr = alloca ptr, align 8 const auto FooFile = SrcCodeLocationEntry(3, 16, HA->getICFG().getFunction("foo")); - const auto FooFClose = - SrcCodeLocationEntry(3, 21, HA->getICFG().getFunction("foo")); + // const auto FooFClose = + // SrcCodeLocationEntry(3, 21, HA->getICFG().getFunction("foo")); // %0 = load ptr, ptr %f const auto PassFToFClose = SrcCodeLocationEntry(3, 28, HA->getICFG().getFunction("foo")); @@ -225,15 +225,14 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_03) { const auto Return = SrcCodeLocationEntry(11, 3, HA->getICFG().getFunction("main")); // Entry in foo() - GroundTruth.insert({FooFClose, {{FooFile, IOSTATE::OPENED}}}); + // GroundTruth.insert({FooFClose, {{FooFile, IOSTATE::OPENED}}}); // Exit in foo() GroundTruth.insert({FooRet, - {{FooFile, IOSTATE::CLOSED}, - {FooFClose, IOSTATE::CLOSED}, + {// {FooFile, IOSTATE::CLOSED}, {PassFToFClose, IOSTATE::CLOSED}}}); // Exit in main() GroundTruth.insert({Return, - {{FooFClose, IOSTATE::CLOSED}, + {// {FooFClose, IOSTATE::CLOSED}, {MainFile, IOSTATE::CLOSED}, {PassFToFoo, IOSTATE::CLOSED}}}); compareResults(GroundTruth, Llvmtssolver); diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp index 8b8885c624..589156690a 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp @@ -16,6 +16,7 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" #include "llvm/IR/Value.h" +#include "llvm/Support/Casting.h" #include "SourceMapping.h" #include "SrcCodeLocationEntry.h" @@ -452,41 +453,52 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_20_SHOULD_LEAK) { std::set> GroundTruth; + // %x.addr = alloca ptr, align 8 const auto ArgAddrX = SrcCodeLocationEntry(2, 15, HA->getICFG().getFunction("_Z3fooRii")); + // %retval = alloca ptr, align 8 + // const auto RetVal = + // SrcCodeLocationEntry(5, 3, HA->getICFG().getFunction("_Z3fooRii")); + // %1 = load ptr, ptr %x.addr, align 8, !dbg !240, !psr.id !241 | ID: 11 const auto LoadX = SrcCodeLocationEntry(4, 12, HA->getICFG().getFunction("_Z3fooRii")); + // %2 = load ptr, ptr %x.addr const auto LoadXTwo = SrcCodeLocationEntry(5, 14, HA->getICFG().getFunction("_Z3fooRii")); + // %4 = load ptr, ptr %retval const auto FooExit = SrcCodeLocationEntry(6, 1, HA->getICFG().getFunction("_Z3fooRii")); // const auto IntN = // SrcCodeLocationEntry(3, 7, HA->getICFG().getFunction("_Z3fooRii")); const auto IntI = SrcCodeLocationEntry(9, 7, HA->getICFG().getFunction("main")); + // %j = alloca i32, align 4 const auto IntJ = SrcCodeLocationEntry(10, 7, HA->getICFG().getFunction("main")); - const auto RetOfFoo = + // %call = call noundef nonnull align 4 dereferenceable(4) ptr @_Z3fooRii(ptr + // noundef nonnull align 4 dereferenceable(4) %i, i32 noundef 10) + const auto CallFooRec = SrcCodeLocationEntry(10, 11, HA->getICFG().getFunction("main")); + // %0 = load i32, ptr %call, align 4 + const auto Load0 = + SrcCodeLocationEntry(10, 11, HA->getICFG().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + // %1 = load i32, ptr %j, align 4, !dbg !274, !psr.id !275 | ID: 31 const auto LoadJ = SrcCodeLocationEntry(11, 18, HA->getICFG().getFunction("main")); - // TODO: ask fabian why the original unittest ground truth has 5 elements - // TODO: Also, why doesn't this crash if I say getFunction("main") when - // looking at insts in foo? - - // GroundTruth.insert({LoadXTwo, IntI}); - // Leaks due to field-insensitivity GroundTruth.insert({LoadX, ArgAddrX}); GroundTruth.insert({LoadXTwo, ArgAddrX}); - // Load uninitialized variable i - // GroundTruth.insert({LoadI, IntI}); - - // Load recursive return-value for returning it + // Load uninitialized variable GroundTruth.insert({LoadJ, IntJ}); - // + // Load recursive return-value for returning it + // GroundTruth.insert({FooExit, RetVal}); + // Load return-value of foo in main + GroundTruth.insert({Load0, CallFooRec}); // // Load return-value of foo in main // GroundTruth.insert({FooExit, IntJ}); @@ -526,44 +538,73 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_21_SHOULD_LEAK) { Solver.solve(); std::set> GroundTruth; - + // %x.addr = alloca ptr, align 8 const auto FooXAddr = SrcCodeLocationEntry(3, 15, HA->getICFG().getFunction("_Z3fooRi")); + // %0 = load ptr, ptr %x.addr, align 8 const auto FooXLoad = SrcCodeLocationEntry(3, 27, HA->getICFG().getFunction("_Z3fooRi")); - + // %x.addr = alloca ptr, align 8 const auto BarXAddr = SrcCodeLocationEntry(4, 15, HA->getICFG().getFunction("_Z3barRi")); + // %0 = load ptr, ptr %x.addr, align 8 const auto Load = SrcCodeLocationEntry(5, 3, HA->getICFG().getFunction("_Z3barRi")); + // %1 = load ptr, ptr %x.addr, align 8 const auto LoadX = SrcCodeLocationEntry(6, 10, HA->getICFG().getFunction("_Z3barRi")); + // const auto IntI = SrcCodeLocationEntry(9, 7, HA->getICFG().getFunction("main")); + // %j = alloca i32, align 4 const auto IntJ = SrcCodeLocationEntry(16, 7, HA->getICFG().getFunction("main")); + // %call = call noundef nonnull align 4 dereferenceable(4) ptr %1 const auto BazCall = - SrcCodeLocationEntry(16, 11, HA->getICFG().getFunction("main")); - const auto BazCall2 = - SrcCodeLocationEntry(16, 11, HA->getICFG().getFunction("main")); + SrcCodeLocationEntry(16, 11, HA->getICFG().getFunction("main"), + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }); + // This implementation to get %2 is bad, but it works + bool SkippedFirst = false; + // %2 = load i32, ptr %call, align 4 + const auto SecondLoadInIfEnd = SrcCodeLocationEntry( + 16, 11, HA->getICFG().getFunction("main"), + [&SkippedFirst](const llvm::Instruction *Inst) mutable { + if (llvm::isa(Inst)) { + if (!SkippedFirst) { + SkippedFirst = true; + return false; + } + return true; + } + + return false; + }); + // %3 = load i32, ptr %j, align 4 const auto LoadJ = SrcCodeLocationEntry(17, 10, HA->getICFG().getFunction("main")); // is passed as a reference, so I isn't being loaded here // const auto LoadI = // SrcCodeLocationEntry(16, 15, HA->getICFG().getFunction("main")); + // TODO: remove this comment: This GT is correct! // 3 => {0}; due to field-insensitivity GroundTruth.insert({FooXLoad, FooXAddr}); + // TODO: remove this comment: This GT is correct! // 8 => {5}; due to field-insensitivity GroundTruth.insert({Load, BarXAddr}); + // TODO: remove this comment: This GT is correct! // 10 => {5}; due to alias-unawareness GroundTruth.insert({LoadX, BarXAddr}); + + // TODO: remove this comment: GT is wrong. // 35 => {34}; actual leak - GroundTruth.insert({BazCall, IntJ}); + GroundTruth.insert({SecondLoadInIfEnd, BazCall}); // 37 => {17}; actual leak - GroundTruth.insert({BazCall2, IntJ}); + GroundTruth.insert({LoadJ, IntJ}); #if false map> GroundTruth = { From 2adb32c4ba1bb5715c317b802c8826a6187e9e81 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Thu, 21 Aug 2025 21:38:38 +0200 Subject: [PATCH 29/35] Fixed UninitTest_21 --- .../IFDSUninitializedVariablesTest.cpp | 105 +++++++++++------- unittests/TestUtils/SrcCodeLocationEntry.h | 41 ++++++- 2 files changed, 103 insertions(+), 43 deletions(-) diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp index 589156690a..2dec3a1b48 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp @@ -55,9 +55,17 @@ class IFDSUninitializedVariablesTest : public ::testing::Test { void TearDown() override {} void compareResults( - const std::set> - &GroundTruth) { - auto GroundTruthEntries = getGroundTruthInsts(GroundTruth, true); + std::set> + &GroundTruthEntries) { + for (const auto &Entry : GroundTruthEntries) { + const auto *GTInst = std::get<0>(Entry); + llvm::outs() << "GTInst: " << GTInst << "\n"; + llvm::outs() << "*GTInst: " << *GTInst << "\n"; + + const auto *GTValue = std::get<1>(Entry); + llvm::outs() << "GTValue: " << GTValue << "\n"; + llvm::outs() << "*GTValue: " << *GTValue << "\n\n"; + } std::set> FoundUninitUses; @@ -75,6 +83,30 @@ class IFDSUninitializedVariablesTest : public ::testing::Test { EXPECT_EQ(FoundUninitUses, GroundTruthEntries); } + + void compareResults( + const std::set> + &GroundTruth) { + auto GroundTruthEntries = getGroundTruthInsts(GroundTruth, true); + compareResults(GroundTruthEntries); + } + + void compareResults( + const std::set> + &GroundTruth, + const LLVMProjectIRDB &IRDB) { + std::set> + GroundTruthEntries; + + for (const auto &Entry : GroundTruth) { + const auto *First = testingLocInIR(std::get<0>(Entry), IRDB); + const auto *FirstAsInst = llvm::dyn_cast(First); + const auto *Second = testingLocInIR(std::get<1>(Entry), IRDB); + GroundTruthEntries.insert({FirstAsInst, Second}); + } + + compareResults(GroundTruthEntries); + } }; // Test Fixture TEST_F(IFDSUninitializedVariablesTest, UninitTest_01_SHOULD_NOT_LEAK) { @@ -451,53 +483,48 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_20_SHOULD_LEAK) { IFDSSolver Solver(*UninitProblem, &HA->getICFG()); Solver.solve(); - std::set> GroundTruth; + std::set> GroundTruth; - // %x.addr = alloca ptr, align 8 - const auto ArgAddrX = - SrcCodeLocationEntry(2, 15, HA->getICFG().getFunction("_Z3fooRii")); - // %retval = alloca ptr, align 8 - // const auto RetVal = - // SrcCodeLocationEntry(5, 3, HA->getICFG().getFunction("_Z3fooRii")); - // %1 = load ptr, ptr %x.addr, align 8, !dbg !240, !psr.id !241 | ID: 11 - const auto LoadX = - SrcCodeLocationEntry(4, 12, HA->getICFG().getFunction("_Z3fooRii")); - // %2 = load ptr, ptr %x.addr - const auto LoadXTwo = - SrcCodeLocationEntry(5, 14, HA->getICFG().getFunction("_Z3fooRii")); - // %4 = load ptr, ptr %retval - const auto FooExit = - SrcCodeLocationEntry(6, 1, HA->getICFG().getFunction("_Z3fooRii")); - // const auto IntN = - // SrcCodeLocationEntry(3, 7, HA->getICFG().getFunction("_Z3fooRii")); const auto IntI = SrcCodeLocationEntry(9, 7, HA->getICFG().getFunction("main")); - // %j = alloca i32, align 4 - const auto IntJ = - SrcCodeLocationEntry(10, 7, HA->getICFG().getFunction("main")); - // %call = call noundef nonnull align 4 dereferenceable(4) ptr @_Z3fooRii(ptr - // noundef nonnull align 4 dereferenceable(4) %i, i32 noundef 10) - const auto CallFooRec = - SrcCodeLocationEntry(10, 11, HA->getICFG().getFunction("main")); - // %0 = load i32, ptr %call, align 4 - const auto Load0 = - SrcCodeLocationEntry(10, 11, HA->getICFG().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - // %1 = load i32, ptr %j, align 4, !dbg !274, !psr.id !275 | ID: 31 - const auto LoadJ = - SrcCodeLocationEntry(11, 18, HA->getICFG().getFunction("main")); // 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 recursive return-value for returning it - // GroundTruth.insert({FooExit, RetVal}); + + // %retval = alloca ptr, align 8 + RetStmt RetOfFoo{"_Z3fooRii"}; + // %4 = load ptr, ptr %retval + LineColFun FooExit{6, 1, "_Z3fooRii"}; + GroundTruth.insert({FooExit, RetOfFoo}); // Load return-value of foo in main + // %0 = load i32, ptr %call, align 4 + LineColFunLambda Load0{10, 11, "main", [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }}; + // %call = call noundef nonnull align 4 dereferenceable(4) ptr @_Z3fooRii(ptr + // noundef nonnull align 4 dereferenceable(4) %i, i32 noundef 10) + LineColFunLambda CallFooRec{10, 11, "main", + [](const llvm::Instruction *Inst) { + return llvm::isa(Inst); + }}; GroundTruth.insert({Load0, CallFooRec}); // // Load return-value of foo in main // GroundTruth.insert({FooExit, IntJ}); @@ -510,7 +537,7 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_20_SHOULD_LEAK) { // Load return-value of foo in main // GroundTruth.insert({IntJ, RetOfFoo}); - compareResults(GroundTruth); + compareResults(GroundTruth, *HA->getICFG().getIRDB()); #if false diff --git a/unittests/TestUtils/SrcCodeLocationEntry.h b/unittests/TestUtils/SrcCodeLocationEntry.h index 8984bd2311..f918f766dd 100644 --- a/unittests/TestUtils/SrcCodeLocationEntry.h +++ b/unittests/TestUtils/SrcCodeLocationEntry.h @@ -79,6 +79,29 @@ struct LineColFun { "; InFunction: " + InFunction.str() + " }"; } }; +struct LineColFunLambda { + uint32_t Line{}; + uint32_t Col{}; + llvm::StringRef InFunction{}; + std::function Lambda{}; + + // TODO: impl lambda into std::tie and std::string + + friend bool operator<(LineColFunLambda LC1, LineColFunLambda LC2) noexcept { + return std::tie(LC1.InFunction, LC1.Line, LC1.Col) < + std::tie(LC2.InFunction, LC2.Line, LC2.Col); + } + friend bool operator==(LineColFunLambda LC1, LineColFunLambda 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) + "; Col: " + std::to_string(Col) + + "; InFunction: " + InFunction.str() + + "; Lambda: Cannot be converted to string yet. }"; + } +}; struct LineColFunOp { uint32_t Line{}; @@ -156,10 +179,10 @@ struct RetStmt { }; struct TestingSrcLocation - : public std::variant { - using VarT = std::variant; + : public std::variant { + using VarT = std::variant; using VarT::variant; template [[nodiscard]] constexpr bool isa() const noexcept { @@ -200,6 +223,12 @@ template <> struct hash { llvm::hash_value(std::make_pair(LCF.Line, LCF.Col)), LCF.InFunction); } }; +template <> struct hash { + size_t operator()(psr::LineColFunLambda 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::LineColFunOp LCF) const noexcept { return llvm::hash_combine( @@ -272,6 +301,10 @@ testingLocInIR(TestingSrcLocation Loc, const LLVMProjectIRDB &IRDB, const auto *InFun = GetFunction(LC.InFunction); return unittest::getInstAtOrNull(InFun, LC.Line, LC.Col); }, + [&](LineColFunLambda LC) -> llvm ::Value const * { + const auto *InFun = GetFunction(LC.InFunction); + return unittest::getInstAtOrNull(InFun, LC.Line, LC.Col, LC.Lambda); + }, [&](LineColFunOp LC) -> llvm ::Value const * { const auto *InFun = GetFunction(LC.InFunction); return unittest::getInstAtOrNull( From 5d2bfeea50e635dfd95ebf214fde12be7e493974 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Fri, 22 Aug 2025 09:36:32 +0200 Subject: [PATCH 30/35] Enable modeling of instruction-operands in TestingSrcLocation + fix 20th uninit test --- .../IFDSUninitializedVariablesTest.cpp | 9 ++-- unittests/TestUtils/SrcCodeLocationEntry.h | 52 +++++++++++++++++-- 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp index 2dec3a1b48..70cf705861 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp @@ -10,6 +10,7 @@ #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/Function.h" #include "llvm/IR/Instruction.h" @@ -81,7 +82,9 @@ class IFDSUninitializedVariablesTest : public ::testing::Test { } } - EXPECT_EQ(FoundUninitUses, GroundTruthEntries); + EXPECT_EQ(FoundUninitUses, GroundTruthEntries) + << "Expected: " << PrettyPrinter{GroundTruthEntries} + << "; got: " << PrettyPrinter{FoundUninitUses}; } void compareResults( @@ -509,11 +512,9 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_20_SHOULD_LEAK) { // Load recursive return-value for returning it - // %retval = alloca ptr, align 8 - RetStmt RetOfFoo{"_Z3fooRii"}; // %4 = load ptr, ptr %retval LineColFun FooExit{6, 1, "_Z3fooRii"}; - GroundTruth.insert({FooExit, RetOfFoo}); + GroundTruth.insert({FooExit, OperandOf{0, FooExit}}); // Load return-value of foo in main // %0 = load i32, ptr %call, align 4 LineColFunLambda Load0{10, 11, "main", [](const llvm::Instruction *Inst) { diff --git a/unittests/TestUtils/SrcCodeLocationEntry.h b/unittests/TestUtils/SrcCodeLocationEntry.h index f918f766dd..80d52f48b6 100644 --- a/unittests/TestUtils/SrcCodeLocationEntry.h +++ b/unittests/TestUtils/SrcCodeLocationEntry.h @@ -161,7 +161,7 @@ struct RetVal { return R1.InFunction == R2.InFunction; } [[nodiscard]] std::string str() const { - return std::string("RetVal { InFunction: ") + InFunction.str() + +" }"; + return std::string("RetVal { InFunction: ") + InFunction.str() + " }"; } }; struct RetStmt { @@ -174,15 +174,34 @@ struct RetStmt { return R1.InFunction == R2.InFunction; } [[nodiscard]] std::string str() const { - return std::string("RetStmt { InFunction: ") + InFunction.str() + +" }"; + return std::string("RetStmt { InFunction: ") + InFunction.str() + " }"; + } +}; + +struct OperandOf { + uint32_t OperandIndex{}; + LineColFun 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; + GlobalVar, ArgNo, ArgInFun, RetVal, RetStmt, + OperandOf> { + using VarT = + std::variant; using VarT::variant; template [[nodiscard]] constexpr bool isa() const noexcept { @@ -264,6 +283,13 @@ template <> struct hash { } }; +template <> struct hash { + size_t operator()(psr::OperandOf Op) const noexcept { + return llvm::hash_combine(Op.OperandIndex, + hash{}(Op.Inst)); + } +}; + template <> struct hash { size_t operator()(const psr::TestingSrcLocation &Loc) const noexcept { return std::hash{}(Loc); @@ -361,6 +387,22 @@ testingLocInIR(TestingSrcLocation Loc, const LLVMProjectIRDB &IRDB, 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); } From a3bd34e3ed2d2d739d1c73a54faac8fcc1423f32 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Fri, 22 Aug 2025 14:13:20 +0200 Subject: [PATCH 31/35] reworked test 06 --- .../Problems/IDETSAnalysisFileIOTest.cpp | 65 ++++++++++++++++--- 1 file changed, 57 insertions(+), 8 deletions(-) diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp index 83162391d6..8845fc6aae 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp @@ -236,7 +236,8 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_03) { {MainFile, IOSTATE::CLOSED}, {PassFToFoo, IOSTATE::CLOSED}}}); compareResults(GroundTruth, Llvmtssolver); -// TODO: go over old and new ground truth with fabian + + // Old ground truth #if false // llvmtssolver.printReport(); const std::map> Gt = { @@ -313,9 +314,6 @@ TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_05) { compareResults(GroundTruth, Llvmtssolver); } -// TODO: fix -#if false - TEST_F(IDETSAnalysisFileIOTest, DISABLED_HandleTypeState_06) { // This test fails due to imprecise points-to information initialize({PathToLlFiles + "typestate_06_c_dbg.ll"}); @@ -324,10 +322,62 @@ TEST_F(IDETSAnalysisFileIOTest, DISABLED_HandleTypeState_06) { std::map> GroundTruth; - const auto File = + + // %f = alloca ptr, align 8 + const auto FileF = + SrcCodeLocationEntry(5, 9, HA->getICFG().getFunction("main")); + // %d = alloca ptr, align 8 + const auto FileD = SrcCodeLocationEntry(6, 9, HA->getICFG().getFunction("main")); - GroundTruth.insert({Opened, {{File, IOSTATE::UNINIT}}}); + // %call = call noalias ptr @fopen(ptr noundef @.str, ptr noundef @.str.1) + const auto FirstFOpenCall = + SrcCodeLocationEntry(7, 7, HA->getICFG().getFunction("main")); + // store ptr %call, ptr %f, align 8 + const auto StoreFirstFOpenRetVal = + SrcCodeLocationEntry(7, 5, HA->getICFG().getFunction("main")); + // %call1 = call noalias ptr @fopen(ptr noundef @.str.2, ptr noundef @.str.3) + const auto SecondFOpenCall = + SrcCodeLocationEntry(8, 7, HA->getICFG().getFunction("main")); + // store ptr %call1, ptr %d, align 8 + const auto StoreSecondFOpenRetVal = + SrcCodeLocationEntry(8, 5, HA->getICFG().getFunction("main")); + // %0 = load ptr, ptr %f, align 8 + const auto LoadFileF = + SrcCodeLocationEntry(10, 10, HA->getICFG().getFunction("main")); + // %call2 = call i32 @fclose(ptr noundef %0) + const auto CallFClose = + SrcCodeLocationEntry(10, 3, HA->getICFG().getFunction("main")); + // ret i32 0 + const auto Return = + SrcCodeLocationEntry(12, 3, HA->getICFG().getFunction("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); + + // Old ground truth +#if false const std::map> Gt = { // Before first fopen() {8, {{"5", IOSTATE::UNINIT}, {"6", IOSTATE::UNINIT}}}, @@ -356,9 +406,8 @@ TEST_F(IDETSAnalysisFileIOTest, DISABLED_HandleTypeState_06) { // After if statement {14, {{"5", IOSTATE::CLOSED}, {"6", IOSTATE::OPENED}}}}; compareResults(Gt, Llvmtssolver); -} - #endif +} TEST_F(IDETSAnalysisFileIOTest, HandleTypeState_07) { initialize({PathToLlFiles + "typestate_07_c_dbg.ll"}); From 254f8b677da0c045575bd79ac79ec6694623be3c Mon Sep 17 00:00:00 2001 From: mxHuber Date: Fri, 22 Aug 2025 14:22:04 +0200 Subject: [PATCH 32/35] cleanup --- .../Problems/IDEFeatureTaintAnalysisTest.cpp | 9 +--- .../IDEInstInteractionAnalysisTest.cpp | 9 +--- .../IFDSUninitializedVariablesTest.cpp | 46 +------------------ 3 files changed, 5 insertions(+), 59 deletions(-) diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEFeatureTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEFeatureTaintAnalysisTest.cpp index da689fb881..2549f2c99d 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEFeatureTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEFeatureTaintAnalysisTest.cpp @@ -305,12 +305,7 @@ TEST_F(IDEFeatureTaintAnalysisTest, HandleBasicTest_03) { false); } -PHASAR_SKIP_TEST(TEST_F(IDEFeatureTaintAnalysisTest, HandleBasicTest_04) { - // If we use libcxx this won't work since internal implementation is different - // TODO: Test this out, now that we have a src-code based definition of the - // ground-truth! - LIBCPP_GTEST_SKIP; - +TEST_F(IDEFeatureTaintAnalysisTest, HandleBasicTest_04) { std::set GroundTruth; auto Main23 = LineColFun{11, 3, "main"}; @@ -346,7 +341,7 @@ PHASAR_SKIP_TEST(TEST_F(IDEFeatureTaintAnalysisTest, HandleBasicTest_04) { doAnalysisAndCompareResults("basic_04_cpp_dbg.ll", {"main"}, GroundTruth, false); -}) +} TEST_F(IDEFeatureTaintAnalysisTest, HandleBasicTest_05) { std::set GroundTruth; diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp index 06e6ce0944..5b9242b67d 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp @@ -552,12 +552,7 @@ TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_03) { false); } -PHASAR_SKIP_TEST(TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_04) { - // If we use libcxx this won't work since internal implementation is different - // TODO: Test this out, now that we have a src-code based definition of the - // ground-truth! - LIBCPP_GTEST_SKIP; - +TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_04) { std::set GroundTruth; auto Main23 = LineColFun{11, 3, "main"}; @@ -593,7 +588,7 @@ PHASAR_SKIP_TEST(TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_04) { doAnalysisAndCompareResults("basic_04_cpp_dbg.ll", {"main"}, GroundTruth, false); -}) +} TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_05) { std::set GroundTruth; diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp index 70cf705861..d68bdeec00 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSUninitializedVariablesTest.cpp @@ -408,21 +408,11 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_16_SHOULD_LEAK) { const auto LoadJ = SrcCodeLocationEntry(12, 16, HA->getICFG().getFunction("main")); - // TODO: rewrite comment below - // TODO remove GT[11] + // TODO remove GroundTruth.insert({LoadX, ArgX}) below GroundTruth.insert({LoadX, ArgX}); GroundTruth.insert({LoadI, IntI}); GroundTruth.insert({Add, LoadI}); GroundTruth.insert({LoadJ, IntJ}); -#if false - // TODO remove GT[11] - GroundTruth[11] = {"0"}; - - GroundTruth[16] = {"2"}; - GroundTruth[18] = {"16"}; - GroundTruth[34] = {"24"}; -#endif - compareResults(GroundTruth); } @@ -539,24 +529,6 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_20_SHOULD_LEAK) { // GroundTruth.insert({IntJ, RetOfFoo}); compareResults(GroundTruth, *HA->getICFG().getIRDB()); - -#if false - - // Leaks at 11 and 14 due to field-insensitivity - GroundTruth[11] = {"2"}; - GroundTruth[14] = {"2"}; - - // Load uninitialized variable i - GroundTruth[31] = {"24"}; - // Load recursive return-value for returning it - GroundTruth[20] = {"1"}; - // Load return-value of foo in main - GroundTruth[29] = {"28"}; - // Analysis does not check uninit on actualparameters - // GroundTruth[32] = {"31"}; - compareResults(GroundTruth); - -#endif } TEST_F(IFDSUninitializedVariablesTest, UninitTest_21_SHOULD_LEAK) { @@ -616,33 +588,17 @@ TEST_F(IFDSUninitializedVariablesTest, UninitTest_21_SHOULD_LEAK) { // const auto LoadI = // SrcCodeLocationEntry(16, 15, HA->getICFG().getFunction("main")); - // TODO: remove this comment: This GT is correct! // 3 => {0}; due to field-insensitivity GroundTruth.insert({FooXLoad, FooXAddr}); - - // TODO: remove this comment: This GT is correct! // 8 => {5}; due to field-insensitivity GroundTruth.insert({Load, BarXAddr}); - - // TODO: remove this comment: This GT is correct! // 10 => {5}; due to alias-unawareness GroundTruth.insert({LoadX, BarXAddr}); - - // TODO: remove this comment: GT is wrong. // 35 => {34}; actual leak GroundTruth.insert({SecondLoadInIfEnd, BazCall}); // 37 => {17}; actual leak GroundTruth.insert({LoadJ, IntJ}); -#if false - map> GroundTruth = { - {3, {"0"}}, {8, {"5"}}, {10, {"5"}}, {35, {"34"}}, {37, {"17"}}}; - // 3 => {0}; due to field-insensitivity - // 8 => {5}; due to field-insensitivity - // 10 => {5}; due to alias-unawareness - // 35 => {34}; actual leak - // 37 => {17}; actual leak -#endif compareResults(GroundTruth); } From 301b8abd000895f8a0b5b07fb5f6287b8849172d Mon Sep 17 00:00:00 2001 From: mxHuber Date: Fri, 22 Aug 2025 14:35:46 +0200 Subject: [PATCH 33/35] readded LIBCPP_GTEST_SKIP --- .../DataFlow/IfdsIde/Problems/IDEFeatureTaintAnalysisTest.cpp | 3 +++ .../IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEFeatureTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEFeatureTaintAnalysisTest.cpp index 2549f2c99d..402cc59407 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEFeatureTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEFeatureTaintAnalysisTest.cpp @@ -306,6 +306,9 @@ TEST_F(IDEFeatureTaintAnalysisTest, HandleBasicTest_03) { } TEST_F(IDEFeatureTaintAnalysisTest, HandleBasicTest_04) { + + LIBCPP_GTEST_SKIP; + std::set GroundTruth; auto Main23 = LineColFun{11, 3, "main"}; diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp index 5b9242b67d..23aeb6f108 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysisTest.cpp @@ -553,6 +553,9 @@ TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_03) { } TEST_F(IDEInstInteractionAnalysisTest, HandleBasicTest_04) { + + LIBCPP_GTEST_SKIP; + std::set GroundTruth; auto Main23 = LineColFun{11, 3, "main"}; From 87a1ded4d3cd7e591bf7093025785d7947074447 Mon Sep 17 00:00:00 2001 From: mxHuber Date: Mon, 25 Aug 2025 10:25:00 +0200 Subject: [PATCH 34/35] fixed use after scope in taint analysis test --- .../IfdsIde/Problems/IFDSTaintAnalysisTest.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp index 6348e8c58a..390c347197 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysisTest.cpp @@ -92,10 +92,10 @@ class IFDSTaintAnalysisTest : public ::testing::Test { createAnalysisProblem(*HA, &*TSF, EntryPoints); } - void initialize(const llvm::Twine &IRFile, const LLVMTaintConfig &Config) { + void initialize(const llvm::Twine &IRFile, const LLVMTaintConfig *Config) { HA.emplace(IRFile, EntryPoints); TaintProblem = - createAnalysisProblem(*HA, &Config, EntryPoints); + createAnalysisProblem(*HA, Config, EntryPoints); } template @@ -443,8 +443,8 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_LibSummary_01) { } TEST_F(IFDSTaintAnalysisTest, TaintTest_DoubleFree_01) { - initialize({PathToLlFiles + "double_free_01_c_dbg.ll"}, - getDoubleFreeConfig()); + auto DoubleFreeConf = getDoubleFreeConfig(); + initialize({PathToLlFiles + "double_free_01_c_dbg.ll"}, &DoubleFreeConf); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); @@ -457,8 +457,8 @@ TEST_F(IFDSTaintAnalysisTest, TaintTest_DoubleFree_01) { } TEST_F(IFDSTaintAnalysisTest, TaintTest_DoubleFree_02) { - initialize({PathToLlFiles + "double_free_02_c_dbg.ll"}, - getDoubleFreeConfig()); + auto DoubleFreeConf = getDoubleFreeConfig(); + initialize({PathToLlFiles + "double_free_02_c_dbg.ll"}, &DoubleFreeConf); IFDSSolver TaintSolver(*TaintProblem, &HA->getICFG()); TaintSolver.solve(); From e71d933c7e2dde263c3ea9452541d196ead69b97 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Mon, 25 Aug 2025 19:30:37 +0200 Subject: [PATCH 35/35] Make IDEExtendedTaintAnalysisTest more compact --- .../DataFlow/IfdsIde/Solver/IDESolver.h | 8 +- .../DataFlow/IfdsIde/Problems/CMakeLists.txt | 2 +- .../Problems/IDEExtendedTaintAnalysisTest.cpp | 354 +++++------------- unittests/TestUtils/SrcCodeLocationEntry.h | 7 +- 4 files changed, 112 insertions(+), 259 deletions(-) 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/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/CMakeLists.txt b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/CMakeLists.txt index c7842c38d7..7d5a903495 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/CMakeLists.txt +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/CMakeLists.txt @@ -28,5 +28,5 @@ endif() test_require_config_file("DOTGraphConfig.json") foreach(TEST_SRC ${IfdsIdeProblemSources}) - add_phasar_unittest(${TEST_SRC} DEBUG) + add_phasar_unittest(${TEST_SRC}) endforeach(TEST_SRC) diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp index 3348fb62b5..988952783b 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysisTest.cpp @@ -11,43 +11,25 @@ #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/PhasarLLVM/Utils/LLVMShorthands.h" -#include "phasar/Utils/DebugOutput.h" #include "phasar/Utils/Utilities.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Demangle/Demangle.h" #include "llvm/IR/Function.h" #include "llvm/IR/InstrTypes.h" -#include "llvm/IR/Instruction.h" #include "llvm/IR/Instructions.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/Casting.h" -#include "SourceMapping.h" #include "SrcCodeLocationEntry.h" #include "TestConfig.h" #include "gtest/gtest.h" -#include "nlohmann/json.hpp" -#include #include -#include #include #include -using namespace std; using namespace psr; -using json = nlohmann::json; using CallBackPairTy = std::pair::config_callback_t, IDEExtendedTaintAnalysis<>::config_callback_t>; @@ -59,15 +41,15 @@ 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( - HelperAnalyses &HA, - const std::set> - &GroundTruth, + const llvm::Twine &IRFilePath, + const std::map &GroundTruth, std::variant Config, bool DumpResults = true) { + HelperAnalyses HA(PathToLLFiles + IRFilePath, EntryPoints); + auto TC = std::visit(Overloaded{[&](std::monostate) { return LLVMTaintConfig(HA.getProjectIRDB()); @@ -101,27 +83,19 @@ class IDETaintAnalysisTest : public ::testing::Test { compareResults(TaintProblem, Solver, GroundTruth); } - void SetUp() override { ValueAnnotationPass::resetValueID(); } - - void TearDown() override {} + void + compareResults(IDEExtendedTaintAnalysis<> &TaintProblem, + IDESolver_P> &Solver, + const std::map &GroundTruth) { + auto GroundTruthEntries = convertTestingLocationSetMapInIR( + GroundTruth, *TaintProblem.getProjectIRDB()); - void compareResults( - IDEExtendedTaintAnalysis<> &TaintProblem, - IDESolver_P> &Solver, - const std::set> - &GroundTruth) { - auto GroundTruthEntries = getGroundTruthInsts(GroundTruth); - - std::set> + std::map> FoundLeaks; - for (const auto &Leak : + for (const auto &[LeakInst, LeakVals] : TaintProblem.getAllLeaks(Solver.getSolverResults())) { - llvm::errs() << "Leak: " << PrettyPrinter{Leak} << '\n'; - - for (const auto &LV : Leak.second) { - FoundLeaks.insert({Leak.first, LV}); - } + FoundLeaks[LeakInst].insert(LeakVals.begin(), LeakVals.end()); } EXPECT_EQ(FoundLeaks, GroundTruthEntries); @@ -129,10 +103,6 @@ class IDETaintAnalysisTest : public ::testing::Test { }; // Test Fixture TEST_F(IDETaintAnalysisTest, XTaint01_Json) { - HelperAnalyses HA({PathToLLFiles + "xtaint01_json_cpp_dbg.ll"}, EntryPoints); - - std::set> GroundTruth; - TaintConfigData Config; FunctionData FuncDataMain; @@ -146,302 +116,184 @@ TEST_F(IDETaintAnalysisTest, XTaint01_Json) { Config.Functions.push_back(std::move(FuncDataMain)); Config.Functions.push_back(std::move(FuncDataPrint)); - SrcCodeLocationEntry Call = - SrcCodeLocationEntry(8, 3, HA.getProjectIRDB().getFunction("main")); - SrcCodeLocationEntry Leak = - SrcCodeLocationEntry(8, 9, HA.getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); + std::map GroundTruth = {{ + LineColFun{8, 3, "main"}, + {LineColFunOp{8, 9, "main", llvm::Instruction::Load}}, + }}; - GroundTruth.insert({Call, Leak}); - - doAnalysis(HA, GroundTruth, &Config); + doAnalysis("xtaint01_json_cpp_dbg.ll", GroundTruth, &Config); } TEST_F(IDETaintAnalysisTest, XTaint01) { - HelperAnalyses HA({PathToLLFiles + "xtaint01_cpp_dbg.ll"}, EntryPoints); - std::set> GroundTruth; - - SrcCodeLocationEntry Call = - SrcCodeLocationEntry(8, 3, HA.getProjectIRDB().getFunction("main")); - SrcCodeLocationEntry Leak = - SrcCodeLocationEntry(8, 9, HA.getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); + std::map GroundTruth = { + {LineColFun{8, 3, "main"}, + {LineColFunOp{8, 9, "main", llvm::Instruction::Load}}}}; - GroundTruth.insert({Call, Leak}); - - doAnalysis(HA, GroundTruth, std::monostate{}); + doAnalysis("xtaint01_cpp_dbg.ll", GroundTruth, std::monostate{}); } TEST_F(IDETaintAnalysisTest, XTaint02) { - HelperAnalyses HA({PathToLLFiles + "xtaint02_cpp_dbg.ll"}, EntryPoints); - std::set> GroundTruth; - - SrcCodeLocationEntry Call = - SrcCodeLocationEntry(9, 3, HA.getProjectIRDB().getFunction("main")); - SrcCodeLocationEntry Leak = - SrcCodeLocationEntry(9, 9, HA.getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); + std::map GroundTruth = { + {LineColFun{9, 3, "main"}, + {LineColFunOp{9, 9, "main", llvm::Instruction::Load}}}}; - GroundTruth.insert({Call, Leak}); - - doAnalysis(HA, GroundTruth, std::monostate{}, true); + doAnalysis("xtaint02_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint03) { - HelperAnalyses HA({PathToLLFiles + "xtaint03_cpp_dbg.ll"}, EntryPoints); - std::set> GroundTruth; - - SrcCodeLocationEntry Call = - SrcCodeLocationEntry(10, 3, HA.getProjectIRDB().getFunction("main")); - SrcCodeLocationEntry Leak = - SrcCodeLocationEntry(10, 9, HA.getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); + std::map GroundTruth = { + {LineColFun{10, 3, "main"}, + {LineColFunOp{10, 9, "main", llvm::Instruction::Load}}}}; - GroundTruth.insert({Call, Leak}); - - doAnalysis(HA, GroundTruth, std::monostate{}, true); + doAnalysis("xtaint03_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint04) { - HelperAnalyses HA({PathToLLFiles + "xtaint04_cpp_dbg.ll"}, EntryPoints); - std::set> GroundTruth; - - SrcCodeLocationEntry Call = - SrcCodeLocationEntry(6, 3, HA.getProjectIRDB().getFunction("_Z3barPi")); - - // TODO: the counter implementation isn't great, as it still relies on IR - // behaviour that might change based on operating system or other factors. A - // better implementation would be good here. - int Counter = 0; - SrcCodeLocationEntry Leak = - SrcCodeLocationEntry(6, 9, HA.getProjectIRDB().getFunction("_Z3barPi"), - [Counter](const llvm::Instruction *Inst) mutable { - Counter++; - return Counter == 3; - }); - - GroundTruth.insert({Call, Leak}); - - doAnalysis(HA, GroundTruth, std::monostate{}, true); + auto Call = LineColFun{6, 3, "_Z3barPi"}; + + std::map GroundTruth = { + {Call, {OperandOf{0, Call}}}}; + + doAnalysis("xtaint04_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } // XTaint05 is similar to 06, but even harder TEST_F(IDETaintAnalysisTest, XTaint06) { - HelperAnalyses HA({PathToLLFiles + "xtaint06_cpp_dbg.ll"}, EntryPoints); - std::set> GroundTruth; - - // no leaks expected + std::map GroundTruth = { + // no leaks expected + }; - doAnalysis(HA, GroundTruth, std::monostate{}, true); + 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. TEST_F(IDETaintAnalysisTest, DISABLED_XTaint07) { - HelperAnalyses HA({PathToLLFiles + "xtaint07_cpp_dbg.ll"}, EntryPoints); - std::set> GroundTruth; - - SrcCodeLocationEntry Call = - SrcCodeLocationEntry(10, 0, HA.getProjectIRDB().getFunction("main")); - SrcCodeLocationEntry Leak = - SrcCodeLocationEntry(10, 18, HA.getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - GroundTruth.insert({Call, Leak}); - - doAnalysis(HA, GroundTruth, std::monostate{}, true); + std::map GroundTruth = { + {LineColFun{10, 0, "main"}, + {LineColFunOp{10, 18, "main", llvm::Instruction::Load}}}}; + + doAnalysis("xtaint07_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, DISABLED_XTaint08) { - HelperAnalyses HA({PathToLLFiles + "xtaint08_cpp_dbg.ll"}, EntryPoints); - std::set> GroundTruth; - - SrcCodeLocationEntry Call = - SrcCodeLocationEntry(20, 0, HA.getProjectIRDB().getFunction("main")); - SrcCodeLocationEntry Leak = - SrcCodeLocationEntry(20, 18, HA.getProjectIRDB().getFunction("main"), - [](const llvm::Instruction *Inst) { - return llvm::isa(Inst); - }); - GroundTruth.insert({Call, Leak}); - - doAnalysis(HA, GroundTruth, std::monostate{}, true); + std::map GroundTruth = { + {LineColFun{20, 3, "main"}, + {LineColFunOp{20, 18, "main", llvm::Instruction::Load}}}}; + + doAnalysis("xtaint08_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint09_1) { - HelperAnalyses HA({PathToLLFiles + "xtaint09_1_cpp_dbg.ll"}, EntryPoints); - std::set> GroundTruth; + std::map GroundTruth = { + {LineColFun{14, 3, "main"}, {LineColFun{14, 8, "main"}}}}; - SrcCodeLocationEntry Call = - SrcCodeLocationEntry(14, 3, HA.getProjectIRDB().getFunction("main")); - SrcCodeLocationEntry Leak = - SrcCodeLocationEntry(14, 8, HA.getProjectIRDB().getFunction("main")); - GroundTruth.insert({Call, Leak}); - - doAnalysis(HA, GroundTruth, std::monostate{}, true); + doAnalysis("xtaint09_1_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint09) { - HelperAnalyses HA({PathToLLFiles + "xtaint09_cpp_dbg.ll"}, EntryPoints); - std::set> GroundTruth; - - SrcCodeLocationEntry Call = - SrcCodeLocationEntry(16, 3, HA.getProjectIRDB().getFunction("main")); - // TODO: the counter implementation isn't great, as it still relies on IR - // behaviour that might change based on operating system or other factors. A - // better implementation would be good here. - int Counter = 0; - SrcCodeLocationEntry Leak = - SrcCodeLocationEntry(16, 8, HA.getProjectIRDB().getFunction("main"), - [Counter](const llvm::Instruction *Inst) mutable { - Counter++; - return Counter == 2; - }); - GroundTruth.insert({Call, Leak}); - - doAnalysis(HA, GroundTruth, std::monostate{}, true); + auto SinkCall = LineColFun{16, 3, "main"}; + std::map GroundTruth = { + {SinkCall, {OperandOf{0, SinkCall}}}}; + + doAnalysis("xtaint09_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, DISABLED_XTaint10) { - HelperAnalyses HA({PathToLLFiles + "xtaint10_cpp_dbg.ll"}, EntryPoints); - std::set> GroundTruth; + std::map GroundTruth = { + // no leaks expected + }; - // GroundTruth.insert(SrcCodeLocEntry(, {})); - - doAnalysis(HA, GroundTruth, std::monostate{}, true); + doAnalysis("xtaint10_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, DISABLED_XTaint11) { - HelperAnalyses HA({PathToLLFiles + "xtaint11_cpp_dbg.ll"}, EntryPoints); - std::set> GroundTruth; - - // GroundTruth.insert(SrcCodeLocEntry(, {})); + std::map GroundTruth = { + // no leaks expected + }; - doAnalysis(HA, GroundTruth, std::monostate{}, true); + doAnalysis("xtaint11_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint12) { - HelperAnalyses HA({PathToLLFiles + "xtaint12_cpp_dbg.ll"}, EntryPoints); - std::set> GroundTruth; + std::map GroundTruth = { + {LineColFun{19, 3, "main"}, {LineColFun{19, 8, "main"}}}}; - GroundTruth.insert( - {SrcCodeLocationEntry(19, 3, HA.getProjectIRDB().getFunction("main")), - SrcCodeLocationEntry(19, 8, HA.getProjectIRDB().getFunction("main"))}); - - doAnalysis(HA, GroundTruth, std::monostate{}, true); + doAnalysis("xtaint12_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint13) { - HelperAnalyses HA({PathToLLFiles + "xtaint13_cpp_dbg.ll"}, EntryPoints); - std::set> GroundTruth; - - GroundTruth.insert( - {SrcCodeLocationEntry(17, 3, HA.getProjectIRDB().getFunction("main")), - SrcCodeLocationEntry(17, 8, HA.getProjectIRDB().getFunction("main"))}); + std::map GroundTruth = { + {LineColFun{17, 3, "main"}, {LineColFun{17, 8, "main"}}}}; - doAnalysis(HA, GroundTruth, std::monostate{}, true); + doAnalysis("xtaint13_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint14) { - std::set> GroundTruth; - HelperAnalyses HA({PathToLLFiles + "xtaint14_cpp_dbg.ll"}, EntryPoints); + std::map GroundTruth = { + {LineColFun{24, 3, "main"}, {LineColFun{24, 8, "main"}}}}; - GroundTruth.insert( - {SrcCodeLocationEntry(24, 3, HA.getProjectIRDB().getFunction("main")), - SrcCodeLocationEntry(24, 8, HA.getProjectIRDB().getFunction("main"))}); - - doAnalysis(HA, GroundTruth, std::monostate{}, true); + 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) { - HelperAnalyses HA({PathToLLFiles + "xtaint15_cpp_dbg.ll"}, EntryPoints); - std::set> GroundTruth; - - // GroundTruth.insert(SrcCodeLocEntry(, {})); + std::map GroundTruth = { + // no leaks expected + }; - doAnalysis(HA, GroundTruth, std::monostate{}, true); + doAnalysis("xtaint15_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint16) { - HelperAnalyses HA({PathToLLFiles + "xtaint16_cpp_dbg.ll"}, EntryPoints); - std::set> GroundTruth; + std::map GroundTruth = { + {LineColFun{13, 3, "main"}, {LineColFun{13, 8, "main"}}}}; - GroundTruth.insert( - {SrcCodeLocationEntry(13, 3, HA.getProjectIRDB().getFunction("main")), - SrcCodeLocationEntry(13, 8, HA.getProjectIRDB().getFunction("main"))}); - - doAnalysis(HA, GroundTruth, std::monostate{}, true); + doAnalysis("xtaint16_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint17) { - HelperAnalyses HA({PathToLLFiles + "xtaint17_cpp_dbg.ll"}, EntryPoints); - std::set> GroundTruth; - - GroundTruth.insert( - {SrcCodeLocationEntry(17, 3, HA.getProjectIRDB().getFunction("main")), - SrcCodeLocationEntry(17, 8, HA.getProjectIRDB().getFunction("main"))}); + std::map GroundTruth = { + {LineColFun{17, 3, "main"}, {LineColFun{17, 8, "main"}}}}; - doAnalysis(HA, GroundTruth, std::monostate{}, true); + doAnalysis("xtaint17_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint18) { - HelperAnalyses HA({PathToLLFiles + "xtaint18_cpp_dbg.ll"}, EntryPoints); - std::set> GroundTruth; + std::map GroundTruth = { + // no leaks expected + }; - doAnalysis(HA, {}, std::monostate{}, true); + doAnalysis("xtaint18_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } PHASAR_SKIP_TEST(TEST_F(IDETaintAnalysisTest, XTaint19) { // Is now the same as XTaint17 GTEST_SKIP(); - HelperAnalyses HA({PathToLLFiles + "xtaint19_cpp_dbg.ll"}, EntryPoints); - std::set> GroundTruth; + std::map GroundTruth = { + {LineColFun{17, 3, "main"}, {LineColFun{17, 8, "main"}}}}; - GroundTruth.insert( - {SrcCodeLocationEntry(17, 3, HA.getProjectIRDB().getFunction("main")), - SrcCodeLocationEntry(17, 8, HA.getProjectIRDB().getFunction("main"))}); - - doAnalysis(HA, GroundTruth, std::monostate{}, true); + doAnalysis("xtaint19_cpp_dbg.ll", GroundTruth, std::monostate{}, true); }) TEST_F(IDETaintAnalysisTest, XTaint20) { - HelperAnalyses HA({PathToLLFiles + "xtaint20_cpp_dbg.ll"}, EntryPoints); - std::set> GroundTruth; - - GroundTruth.insert( - {SrcCodeLocationEntry(12, 3, HA.getProjectIRDB().getFunction("main")), - SrcCodeLocationEntry(6, 7, HA.getProjectIRDB().getFunction("main"))}); - GroundTruth.insert( - {SrcCodeLocationEntry(13, 3, HA.getProjectIRDB().getFunction("main")), - SrcCodeLocationEntry(13, 8, HA.getProjectIRDB().getFunction("main"))}); + std::map GroundTruth = { + {LineColFun{12, 3, "main"}, {LineColFun{6, 7, "main"}}}, + {LineColFun{13, 3, "main"}, {LineColFun{13, 8, "main"}}}, + }; - doAnalysis(HA, GroundTruth, std::monostate{}, true); + doAnalysis("xtaint20_cpp_dbg.ll", GroundTruth, std::monostate{}, true); } TEST_F(IDETaintAnalysisTest, XTaint21) { - HelperAnalyses HA({PathToLLFiles + "xtaint21_cpp_dbg.ll"}, EntryPoints); - std::set> GroundTruth; - - GroundTruth.insert( - {SrcCodeLocationEntry(17, 3, HA.getProjectIRDB().getFunction("main")), - SrcCodeLocationEntry(11, 7, HA.getProjectIRDB().getFunction("main"))}); - GroundTruth.insert( - {SrcCodeLocationEntry(18, 3, HA.getProjectIRDB().getFunction("main")), - SrcCodeLocationEntry(18, 8, HA.getProjectIRDB().getFunction("main"))}); + 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) { @@ -465,7 +317,7 @@ TEST_F(IDETaintAnalysisTest, XTaint21) { return Ret; }; - doAnalysis(HA, GroundTruth, + doAnalysis("xtaint21_cpp_dbg.ll", GroundTruth, CallBackPairTy{std::move(SourceCB), std::move(SinkCB)}); } diff --git a/unittests/TestUtils/SrcCodeLocationEntry.h b/unittests/TestUtils/SrcCodeLocationEntry.h index 80d52f48b6..558ebcaab5 100644 --- a/unittests/TestUtils/SrcCodeLocationEntry.h +++ b/unittests/TestUtils/SrcCodeLocationEntry.h @@ -300,7 +300,8 @@ template <> struct hash { namespace psr { [[nodiscard]] inline const llvm::Value * -testingLocInIR(TestingSrcLocation Loc, const LLVMProjectIRDB &IRDB, +testingLocInIR(TestingSrcLocation Loc, + const ProjectIRDBBase &IRDB, const llvm::Function *InterestingFunction = nullptr) { const auto GetFunction = [&IRDB](llvm::StringRef Name) { const auto *InFun = IRDB.getFunctionDefinition(Name); @@ -410,7 +411,7 @@ testingLocInIR(TestingSrcLocation Loc, const LLVMProjectIRDB &IRDB, template [[nodiscard]] inline std::set convertTestingLocationSetInIR( - const SetTy &Locs, const LLVMProjectIRDB &IRDB, + const SetTy &Locs, const ProjectIRDBBase &IRDB, const llvm::Function *InterestingFunction = nullptr) { std::set Ret; llvm::transform(Locs, std::inserter(Ret, Ret.end()), @@ -422,7 +423,7 @@ convertTestingLocationSetInIR( template [[nodiscard]] inline auto convertTestingLocationSetMapInIR( - const MapTy &Locs, const LLVMProjectIRDB &IRDB, + const MapTy &Locs, const ProjectIRDBBase &IRDB, const llvm::Function *InterestingFunction = nullptr) { std::map> Ret; llvm::transform(