Skip to content

Commit 1e9f3b7

Browse files
fabianbs96SanthoshMohan97sritejakv
authored
Analysis Printer (#677)
* Analysis Printer (#17) * Initial Commit * AnalysisPrinter Second commit * Initial Commit * Integrate Printer with client Analysis and test * Addressing Review comments * Integrate AnalysisPrinter with all analyses and template class modified * vector emplace_back instead of push_back * Testcase for AnalysisPrinter * GroundTruth derived class initial commit * AnalysisPrinter Test complete and Test * fixing myphasartool file * Test pre-commit fix * Adding Test cases and fixing PR failure * 1.template params to N,D,L 2.remove AnalysisType param from AnalysisResults 3.rearranging class variables * 1.template params to N,D,L 2.remove AnalysisType param from AnalysisResults 3.rearranging class variables * Null AnalysisPrinter singleton * Adding AnalysisPrinter to IDETabulation Problem * making free (N,D,L)ToString functions * disable copy and move for analysis-printer * Default NullAnalysisPrinter and explicit print methods * removing SetAnalysisPrinter from client analyses and modified Testcase for AnalysisPrinter * Adding superclass for AnalysisPrinter * Addressing review comments and fixing PR build failure * fix: minors * fix: minor (clang-tidy) * fix: review feedback * misc: minor refactoring --------- Co-authored-by: SanthoshMohan <santhoshmohan0897@gmail.com> Co-authored-by: Sriteja Kummita <sriteja.ku@gmail.com> * fix: review feedback --------- Co-authored-by: SanthoshMohan <santhoshmohan0897@gmail.com> Co-authored-by: Sriteja Kummita <sriteja.ku@gmail.com>
1 parent fc14480 commit 1e9f3b7

13 files changed

Lines changed: 295 additions & 70 deletions

File tree

include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "phasar/DataFlow/IfdsIde/IFDSIDESolverConfig.h"
2020
#include "phasar/DataFlow/IfdsIde/InitialSeeds.h"
2121
#include "phasar/DataFlow/IfdsIde/SolverResults.h"
22+
#include "phasar/PhasarLLVM/Utils/NullAnalysisPrinter.h"
2223
#include "phasar/Utils/JoinLattice.h"
2324
#include "phasar/Utils/Printer.h"
2425
#include "phasar/Utils/Soundness.h"
@@ -78,10 +79,19 @@ class IDETabulationProblem : public FlowFunctions<AnalysisDomainTy, Container>,
7879
std::optional<d_t>
7980
ZeroValue) noexcept(std::is_nothrow_move_constructible_v<d_t>)
8081
: IRDB(IRDB), EntryPoints(std::move(EntryPoints)),
81-
ZeroValue(std::move(ZeroValue)) {
82+
ZeroValue(std::move(ZeroValue)),
83+
Printer(NullAnalysisPrinter<AnalysisDomainTy>::getInstance()) {
8284
assert(IRDB != nullptr);
8385
}
8486

87+
void setAnalysisPrinter(AnalysisPrinterBase<AnalysisDomainTy> *P) {
88+
if (P) {
89+
Printer = P;
90+
} else {
91+
Printer = NullAnalysisPrinter<AnalysisDomainTy>::getInstance();
92+
}
93+
}
94+
8595
~IDETabulationProblem() override = default;
8696

8797
/// Checks if the given data-flow fact is the special tautological lambda (or
@@ -167,6 +177,8 @@ class IDETabulationProblem : public FlowFunctions<AnalysisDomainTy, Container>,
167177
IFDSIDESolverConfig SolverConfig{};
168178

169179
[[maybe_unused]] Soundness SF = Soundness::Soundy;
180+
181+
AnalysisPrinterBase<AnalysisDomainTy> *Printer;
170182
};
171183

172184
} // namespace psr

include/phasar/PhasarLLVM/DataFlow/IfdsIde/IFDSFieldSensTaintAnalysis/Utils/ExtendedValue.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#ifndef PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_IFDSFIELDSENSTAINTANALYSIS_UTILS_EXTENDEDVALUE_H
66
#define PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_IFDSFIELDSENSTAINTANALYSIS_UTILS_EXTENDEDVALUE_H
77

8+
#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h"
9+
810
#include <cassert>
911
#include <functional>
1012
#include <string>

include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETypeStateAnalysis.h

Lines changed: 11 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -519,70 +519,41 @@ class IDETypeStateAnalysis
519519
void emitTextReport(const SolverResults<n_t, d_t, l_t> &SR,
520520
llvm::raw_ostream &OS = llvm::outs()) override {
521521
LLVMBasedCFG CFG;
522-
OS << "\n======= TYPE STATE RESULTS =======\n";
523522
for (const auto &F : this->IRDB->getAllFunctions()) {
524-
OS << '\n' << F->getName() << '\n';
525523
for (const auto &BB : *F) {
526524
for (const auto &I : BB) {
527525
auto Results = SR.resultsAt(&I, true);
526+
528527
if (CFG.isExitInst(&I)) {
529-
OS << "\nAt exit stmt: " << NToString(&I) << '\n';
530528
for (auto Res : Results) {
531529
if (const auto *Alloca =
532530
llvm::dyn_cast<llvm::AllocaInst>(Res.first)) {
533531
if (Res.second == TSD->error()) {
534-
OS << "\n=== ERROR STATE DETECTED ===\nAlloca: "
535-
<< DToString(Res.first) << '\n';
536-
for (const auto *Pred : CFG.getPredsOf(&I)) {
537-
OS << "\nPredecessor: " << NToString(Pred) << '\n';
538-
auto PredResults = SR.resultsAt(Pred, true);
539-
for (auto Res : PredResults) {
540-
if (Res.first == Alloca) {
541-
OS << "Pred State: " << LToString(Res.second) << '\n';
542-
}
543-
}
544-
}
545-
OS << "============================\n";
546-
} else {
547-
OS << "\nAlloca : " << DToString(Res.first)
548-
<< "\nState : " << LToString(Res.second) << '\n';
532+
Warning<IDETypeStateAnalysisDomain<TypeStateDescriptionTy>>
533+
Warn(&I, Res.first, TSD->error());
534+
// ERROR STATE DETECTED
535+
this->Printer->onResult(Warn);
549536
}
550-
} else {
551-
OS << "\nInst: " << NToString(&I) << '\n'
552-
<< "Fact: " << DToString(Res.first) << '\n'
553-
<< "State: " << LToString(Res.second) << '\n';
554537
}
555538
}
556539
} else {
557540
for (auto Res : Results) {
558541
if (const auto *Alloca =
559542
llvm::dyn_cast<llvm::AllocaInst>(Res.first)) {
560543
if (Res.second == TSD->error()) {
561-
OS << "\n=== ERROR STATE DETECTED ===\nAlloca: "
562-
<< DToString(Res.first) << '\n'
563-
<< "\nAt IR Inst: " << NToString(&I) << '\n';
564-
for (const auto *Pred : CFG.getPredsOf(&I)) {
565-
OS << "\nPredecessor: " << NToString(Pred) << '\n';
566-
auto PredResults = SR.resultsAt(Pred, true);
567-
for (auto Res : PredResults) {
568-
if (Res.first == Alloca) {
569-
OS << "Pred State: " << LToString(Res.second) << '\n';
570-
}
571-
}
572-
}
573-
OS << "============================\n";
544+
Warning<IDETypeStateAnalysisDomain<TypeStateDescriptionTy>>
545+
Warn(&I, Res.first, TSD->error());
546+
// ERROR STATE DETECTED
547+
this->Printer->onResult(Warn);
574548
}
575-
} else {
576-
OS << "\nInst: " << NToString(&I) << '\n'
577-
<< "Fact: " << DToString(Res.first) << '\n'
578-
<< "State: " << LToString(Res.second) << '\n';
579549
}
580550
}
581551
}
582552
}
583553
}
584-
OS << "\n--------------------------------------------\n";
585554
}
555+
556+
this->Printer->onFinalize(OS);
586557
}
587558

588559
private:
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#ifndef PHASAR_PHASARLLVM_UTILS_ANALYSISPRINTERBASE_H
2+
#define PHASAR_PHASARLLVM_UTILS_ANALYSISPRINTERBASE_H
3+
4+
#include "llvm/Support/raw_ostream.h"
5+
6+
namespace psr {
7+
8+
template <typename AnalysisDomainTy> struct Warning {
9+
using n_t = typename AnalysisDomainTy::n_t;
10+
using d_t = typename AnalysisDomainTy::d_t;
11+
using l_t = typename AnalysisDomainTy::l_t;
12+
13+
n_t Instr;
14+
d_t Fact;
15+
l_t LatticeElement;
16+
17+
// Constructor
18+
Warning(n_t Inst, d_t DfFact, l_t Lattice)
19+
: Instr(std::move(Inst)), Fact(std::move(DfFact)),
20+
LatticeElement(std::move(Lattice)) {}
21+
};
22+
23+
template <typename AnalysisDomainTy> struct DataflowAnalysisResults {
24+
std::vector<Warning<AnalysisDomainTy>> War;
25+
};
26+
27+
template <typename AnalysisDomainTy> class AnalysisPrinterBase {
28+
public:
29+
virtual void onResult(Warning<AnalysisDomainTy> /*War*/) = 0;
30+
virtual void onInitialize() = 0;
31+
virtual void onFinalize(llvm::raw_ostream & /*OS*/) const = 0;
32+
33+
AnalysisPrinterBase() = default;
34+
virtual ~AnalysisPrinterBase() = default;
35+
AnalysisPrinterBase(const AnalysisPrinterBase &) = delete;
36+
AnalysisPrinterBase &operator=(const AnalysisPrinterBase &) = delete;
37+
38+
AnalysisPrinterBase(AnalysisPrinterBase &&) = delete;
39+
AnalysisPrinterBase &operator=(AnalysisPrinterBase &&) = delete;
40+
};
41+
42+
} // namespace psr
43+
44+
#endif
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#ifndef PHASAR_PHASARLLVM_UTILS_DEFAULTANALYSISPRINTER_H
2+
#define PHASAR_PHASARLLVM_UTILS_DEFAULTANALYSISPRINTER_H
3+
4+
#include "phasar/Domain/BinaryDomain.h"
5+
#include "phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h"
6+
#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h"
7+
#include "phasar/Utils/Printer.h"
8+
9+
#include <optional>
10+
#include <type_traits>
11+
#include <vector>
12+
13+
namespace psr {
14+
15+
template <typename AnalysisDomainTy>
16+
class DefaultAnalysisPrinter : public AnalysisPrinterBase<AnalysisDomainTy> {
17+
using l_t = typename AnalysisDomainTy::l_t;
18+
19+
public:
20+
~DefaultAnalysisPrinter() override = default;
21+
DefaultAnalysisPrinter() = default;
22+
23+
void onResult(Warning<AnalysisDomainTy> War) override {
24+
AnalysisResults.War.emplace_back(std::move(War));
25+
}
26+
27+
void onInitialize() override{};
28+
void onFinalize(llvm::raw_ostream &OS = llvm::outs()) const override {
29+
for (const auto &Iter : AnalysisResults.War) {
30+
31+
OS << "\nAt IR statement: " << NToString(Iter.Instr) << "\n";
32+
33+
OS << "\tFact: " << DToString(Iter.Fact) << "\n";
34+
35+
if constexpr (std::is_same_v<l_t, BinaryDomain>) {
36+
OS << "Value: " << LToString(Iter.LatticeElement) << "\n";
37+
}
38+
}
39+
}
40+
41+
private:
42+
DataflowAnalysisResults<AnalysisDomainTy> AnalysisResults{};
43+
};
44+
45+
} // namespace psr
46+
47+
#endif
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#ifndef PHASAR_PHASARLLVM_UTILS_NULLANALYSISPRINTER_H
2+
#define PHASAR_PHASARLLVM_UTILS_NULLANALYSISPRINTER_H
3+
4+
#include "phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h"
5+
6+
namespace psr {
7+
8+
template <typename AnalysisDomainTy>
9+
class NullAnalysisPrinter final : public AnalysisPrinterBase<AnalysisDomainTy> {
10+
public:
11+
static NullAnalysisPrinter *getInstance() {
12+
static auto Instance = NullAnalysisPrinter();
13+
return &Instance;
14+
}
15+
16+
void onInitialize() override{};
17+
void onResult(Warning<AnalysisDomainTy> /*War*/) override{};
18+
void onFinalize(llvm::raw_ostream & /*OS*/) const override{};
19+
20+
private:
21+
NullAnalysisPrinter() = default;
22+
};
23+
24+
} // namespace psr
25+
#endif

lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEExtendedTaintAnalysis.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,9 @@ void IDEExtendedTaintAnalysis::reportLeakIfNecessary(
227227
const llvm::Value *LeakCandidate) {
228228
if (isSink(SinkCandidate, Inst)) {
229229
Leaks[Inst].insert(LeakCandidate);
230+
Warning<IDEExtendedTaintAnalysisDomain> Warn(
231+
Inst, makeFlowFact(LeakCandidate), Top{});
232+
Printer->onResult(Warn);
230233
}
231234
}
232235

@@ -744,19 +747,20 @@ auto IDEExtendedTaintAnalysis::getSummaryEdgeFunction(n_t Curr, d_t CurrNode,
744747

745748
void IDEExtendedTaintAnalysis::emitTextReport(
746749
const SolverResults<n_t, d_t, l_t> &SR, llvm::raw_ostream &OS) {
747-
OS << "===== IDEExtendedTaintAnalysis-Results =====\n";
748750

749751
if (!PostProcessed) {
750752
doPostProcessing(SR);
751753
}
752754

753755
for (auto &[Inst, LeakSet] : Leaks) {
754-
OS << "At " << NToString(Inst) << '\n';
755756
for (const auto &Leak : LeakSet) {
756-
OS << "\t" << llvmIRToShortString(Leak) << "\n";
757+
Warning<IDEExtendedTaintAnalysisDomain> Warn(Inst, makeFlowFact(Leak),
758+
Top{});
759+
Printer->onResult(Warn);
757760
}
758761
}
759-
OS << '\n';
762+
763+
Printer->onFinalize(OS);
760764
}
761765

762766
// Helpers:

lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
#include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h"
1111

12+
#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h"
13+
1214
#include "llvm/IR/Instruction.h"
1315
#include "llvm/IR/Instructions.h"
1416
#include "llvm/IR/Value.h"

lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSFieldSensTaintAnalysis.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,13 @@
2828
#include "phasar/PhasarLLVM/DataFlow/IfdsIde/IFDSFieldSensTaintAnalysis/Utils/DataFlowUtils.h"
2929

3030
#include "llvm/IR/IntrinsicInst.h"
31+
#include "llvm/Support/raw_ostream.h"
3132

3233
#include <set>
3334
#include <string>
3435
#include <utility>
3536
#include <vector>
3637

37-
#include <llvm/Support/raw_ostream.h>
38-
3938
namespace psr {
4039

4140
IFDSFieldSensTaintAnalysis::IFDSFieldSensTaintAnalysis(

lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h"
1717
#include "phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMFlowFunctions.h"
1818
#include "phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMZeroValue.h"
19+
#include "phasar/PhasarLLVM/Domain/LLVMAnalysisDomain.h"
1920
#include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h"
2021
#include "phasar/PhasarLLVM/TaintConfig/TaintConfigUtilities.h"
2122
#include "phasar/PhasarLLVM/Utils/LLVMIRToSrc.h"
@@ -408,7 +409,11 @@ auto IFDSTaintAnalysis::getSummaryFlowFunction([[maybe_unused]] n_t CallSite,
408409
return lambdaFlow([Leak{std::move(Leak)}, Kill{std::move(Kill)}, this,
409410
CallSite](d_t Source) -> container_type {
410411
if (Leak.count(Source)) {
411-
Leaks[CallSite].insert(Source);
412+
if (Leaks[CallSite].insert(Source).second) {
413+
Warning<LLVMIFDSAnalysisDomainDefault> Warn(CallSite, Source,
414+
topElement());
415+
Printer->onResult(Warn);
416+
}
412417
}
413418

414419
if (Kill.count(Source)) {
@@ -433,7 +438,11 @@ auto IFDSTaintAnalysis::getSummaryFlowFunction([[maybe_unused]] n_t CallSite,
433438
}
434439

435440
if (Leak.count(Source)) {
436-
Leaks[CallSite].insert(Source);
441+
if (Leaks[CallSite].insert(Source).second) {
442+
Warning<LLVMIFDSAnalysisDomainDefault> Warn(CallSite, Source,
443+
topElement());
444+
Printer->onResult(Warn);
445+
}
437446
}
438447

439448
return {Source};
@@ -478,25 +487,7 @@ void IFDSTaintAnalysis::emitTextReport(
478487
const SolverResults<n_t, d_t, BinaryDomain> & /*SR*/,
479488
llvm::raw_ostream &OS) {
480489
OS << "\n----- Found the following leaks -----\n";
481-
if (Leaks.empty()) {
482-
OS << "No leaks found!\n";
483-
return;
484-
}
485-
486-
for (const auto &Leak : Leaks) {
487-
OS << "At instruction\nIR : " << llvmIRToString(Leak.first) << '\n';
488-
OS << "\nLeak(s):\n";
489-
for (const auto *LeakedValue : Leak.second) {
490-
OS << "IR : ";
491-
// Get the actual leaked alloca instruction if possible
492-
if (const auto *Load = llvm::dyn_cast<llvm::LoadInst>(LeakedValue)) {
493-
OS << llvmIRToString(Load->getPointerOperand()) << '\n';
494-
} else {
495-
OS << llvmIRToString(LeakedValue) << '\n';
496-
}
497-
}
498-
OS << "-------------------\n";
499-
}
490+
Printer->onFinalize(OS);
500491
}
501492

502493
} // namespace psr

0 commit comments

Comments
 (0)