Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Analysis Printer #677

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "phasar/DataFlow/IfdsIde/IFDSIDESolverConfig.h"
#include "phasar/DataFlow/IfdsIde/InitialSeeds.h"
#include "phasar/DataFlow/IfdsIde/SolverResults.h"
#include "phasar/PhasarLLVM/Utils/NullAnalysisPrinter.h"
#include "phasar/Utils/JoinLattice.h"
#include "phasar/Utils/Printer.h"
#include "phasar/Utils/Soundness.h"
Expand Down Expand Up @@ -78,10 +79,19 @@ class IDETabulationProblem : public FlowFunctions<AnalysisDomainTy, Container>,
std::optional<d_t>
ZeroValue) noexcept(std::is_nothrow_move_constructible_v<d_t>)
: IRDB(IRDB), EntryPoints(std::move(EntryPoints)),
ZeroValue(std::move(ZeroValue)) {
ZeroValue(std::move(ZeroValue)),
Printer(NullAnalysisPrinter<AnalysisDomainTy>::getInstance()) {
assert(IRDB != nullptr);
}

void setAnalysisPrinter(AnalysisPrinterBase<AnalysisDomainTy> *P) {
if (P) {
Printer = P;
} else {
Printer = NullAnalysisPrinter<AnalysisDomainTy>::getInstance();
}
}

~IDETabulationProblem() override = default;

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

[[maybe_unused]] Soundness SF = Soundness::Soundy;

AnalysisPrinterBase<AnalysisDomainTy> *Printer;
};

} // namespace psr
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#ifndef PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_IFDSFIELDSENSTAINTANALYSIS_UTILS_EXTENDEDVALUE_H
#define PHASAR_PHASARLLVM_DATAFLOW_IFDSIDE_IFDSFIELDSENSTAINTANALYSIS_UTILS_EXTENDEDVALUE_H

#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h"

#include <cassert>
#include <functional>
#include <string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -519,70 +519,41 @@ class IDETypeStateAnalysis
void emitTextReport(const SolverResults<n_t, d_t, l_t> &SR,
llvm::raw_ostream &OS = llvm::outs()) override {
LLVMBasedCFG CFG;
OS << "\n======= TYPE STATE RESULTS =======\n";
for (const auto &F : this->IRDB->getAllFunctions()) {
OS << '\n' << F->getName() << '\n';
for (const auto &BB : *F) {
for (const auto &I : BB) {
auto Results = SR.resultsAt(&I, true);

if (CFG.isExitInst(&I)) {
OS << "\nAt exit stmt: " << NToString(&I) << '\n';
for (auto Res : Results) {
if (const auto *Alloca =
llvm::dyn_cast<llvm::AllocaInst>(Res.first)) {
if (Res.second == TSD->error()) {
OS << "\n=== ERROR STATE DETECTED ===\nAlloca: "
<< DToString(Res.first) << '\n';
for (const auto *Pred : CFG.getPredsOf(&I)) {
OS << "\nPredecessor: " << NToString(Pred) << '\n';
auto PredResults = SR.resultsAt(Pred, true);
for (auto Res : PredResults) {
if (Res.first == Alloca) {
OS << "Pred State: " << LToString(Res.second) << '\n';
}
}
}
OS << "============================\n";
} else {
OS << "\nAlloca : " << DToString(Res.first)
<< "\nState : " << LToString(Res.second) << '\n';
Warning<IDETypeStateAnalysisDomain<TypeStateDescriptionTy>>
War(&I, Res.first, TSD->error());
fabianbs96 marked this conversation as resolved.
Show resolved Hide resolved
// ERROR STATE DETECTED
this->Printer->onResult(War);
}
} else {
OS << "\nInst: " << NToString(&I) << '\n'
<< "Fact: " << DToString(Res.first) << '\n'
<< "State: " << LToString(Res.second) << '\n';
}
}
} else {
for (auto Res : Results) {
if (const auto *Alloca =
llvm::dyn_cast<llvm::AllocaInst>(Res.first)) {
if (Res.second == TSD->error()) {
OS << "\n=== ERROR STATE DETECTED ===\nAlloca: "
<< DToString(Res.first) << '\n'
<< "\nAt IR Inst: " << NToString(&I) << '\n';
for (const auto *Pred : CFG.getPredsOf(&I)) {
OS << "\nPredecessor: " << NToString(Pred) << '\n';
auto PredResults = SR.resultsAt(Pred, true);
for (auto Res : PredResults) {
if (Res.first == Alloca) {
OS << "Pred State: " << LToString(Res.second) << '\n';
}
}
}
OS << "============================\n";
Warning<IDETypeStateAnalysisDomain<TypeStateDescriptionTy>>
War(&I, Res.first, TSD->error());
// ERROR STATE DETECTED
this->Printer->onResult(War);
}
} else {
OS << "\nInst: " << NToString(&I) << '\n'
<< "Fact: " << DToString(Res.first) << '\n'
<< "State: " << LToString(Res.second) << '\n';
}
}
}
}
}
OS << "\n--------------------------------------------\n";
}

this->Printer->onFinalize(OS);
}

private:
Expand Down
44 changes: 44 additions & 0 deletions include/phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#ifndef PHASAR_PHASARLLVM_UTILS_ANALYSISPRINTERBASE_H
#define PHASAR_PHASARLLVM_UTILS_ANALYSISPRINTERBASE_H

#include "llvm/Support/raw_ostream.h"

namespace psr {

template <typename AnalysisDomainTy> struct Warning {
MMory marked this conversation as resolved.
Show resolved Hide resolved
using n_t = typename AnalysisDomainTy::n_t;
using d_t = typename AnalysisDomainTy::d_t;
using l_t = typename AnalysisDomainTy::l_t;

n_t Instr;
d_t Fact;
l_t LatticeElement;

// Constructor
Warning(n_t Inst, d_t DfFact, l_t Lattice)
: Instr(std::move(Inst)), Fact(std::move(DfFact)),
LatticeElement(std::move(Lattice)) {}
};

template <typename AnalysisDomainTy> struct Results {
fabianbs96 marked this conversation as resolved.
Show resolved Hide resolved
std::vector<Warning<AnalysisDomainTy>> War;
};

template <typename AnalysisDomainTy> class AnalysisPrinterBase {
public:
virtual void onResult(Warning<AnalysisDomainTy> /*War*/) = 0;
virtual void onInitialize() = 0;
virtual void onFinalize(llvm::raw_ostream & /*OS*/) const = 0;

AnalysisPrinterBase() = default;
virtual ~AnalysisPrinterBase() = default;
AnalysisPrinterBase(const AnalysisPrinterBase &) = delete;
AnalysisPrinterBase &operator=(const AnalysisPrinterBase &) = delete;

AnalysisPrinterBase(AnalysisPrinterBase &&) = delete;
AnalysisPrinterBase &operator=(AnalysisPrinterBase &&) = delete;
};

} // namespace psr

#endif
47 changes: 47 additions & 0 deletions include/phasar/PhasarLLVM/Utils/DefaultAnalysisPrinter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#ifndef PHASAR_PHASARLLVM_UTILS_DEFAULTANALYSISPRINTER_H
#define PHASAR_PHASARLLVM_UTILS_DEFAULTANALYSISPRINTER_H

#include "phasar/Domain/BinaryDomain.h"
#include "phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h"
#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h"
#include "phasar/Utils/Printer.h"

#include <optional>
#include <type_traits>
#include <vector>

namespace psr {

template <typename AnalysisDomainTy>
class DefaultAnalysisPrinter : public AnalysisPrinterBase<AnalysisDomainTy> {
using l_t = typename AnalysisDomainTy::l_t;

public:
~DefaultAnalysisPrinter() override = default;
DefaultAnalysisPrinter() = default;

void onResult(Warning<AnalysisDomainTy> War) override {
AnalysisResults.War.emplace_back(std::move(War));
}

void onInitialize() override{};
void onFinalize(llvm::raw_ostream &OS = llvm::outs()) const override {
for (const auto &Iter : AnalysisResults.War) {

OS << "\nAt IR statement: " << NToString(Iter.Instr) << "\n";

OS << "\tFact: " << DToString(Iter.Fact) << "\n";

if constexpr (std::is_same_v<l_t, BinaryDomain>) {
OS << "Value: " << LToString(Iter.LatticeElement) << "\n";
}
}
}

private:
Results<AnalysisDomainTy> AnalysisResults{};
};

} // namespace psr

#endif
25 changes: 25 additions & 0 deletions include/phasar/PhasarLLVM/Utils/NullAnalysisPrinter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#ifndef PHASAR_PHASARLLVM_UTILS_NULLANALYSISPRINTER_H
#define PHASAR_PHASARLLVM_UTILS_NULLANALYSISPRINTER_H

#include "phasar/PhasarLLVM/Utils/AnalysisPrinterBase.h"

namespace psr {

template <typename AnalysisDomainTy>
class NullAnalysisPrinter final : public AnalysisPrinterBase<AnalysisDomainTy> {
public:
static NullAnalysisPrinter *getInstance() {
static auto Instance = NullAnalysisPrinter();
return &Instance;
}

void onInitialize() override{};
void onResult(Warning<AnalysisDomainTy> /*War*/) override{};
void onFinalize(llvm::raw_ostream & /*OS*/) const override{};

private:
NullAnalysisPrinter() = default;
};

} // namespace psr
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,9 @@ void IDEExtendedTaintAnalysis::reportLeakIfNecessary(
const llvm::Value *LeakCandidate) {
if (isSink(SinkCandidate, Inst)) {
Leaks[Inst].insert(LeakCandidate);
Warning<IDEExtendedTaintAnalysisDomain> War(
Inst, makeFlowFact(LeakCandidate), Top{});
Printer->onResult(War);
}
}

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

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

if (!PostProcessed) {
doPostProcessing(SR);
}

for (auto &[Inst, LeakSet] : Leaks) {
OS << "At " << NToString(Inst) << '\n';
for (const auto &Leak : LeakSet) {
OS << "\t" << llvmIRToShortString(Leak) << "\n";
Warning<IDEExtendedTaintAnalysisDomain> War(Inst, makeFlowFact(Leak),
Top{});
Printer->onResult(War);
}
}
OS << '\n';

Printer->onFinalize(OS);
}

// Helpers:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

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

#include "phasar/PhasarLLVM/Utils/LLVMShorthands.h"

#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Value.h"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,13 @@
#include "phasar/PhasarLLVM/DataFlow/IfdsIde/IFDSFieldSensTaintAnalysis/Utils/DataFlowUtils.h"

#include "llvm/IR/IntrinsicInst.h"
#include "llvm/Support/raw_ostream.h"

#include <set>
#include <string>
#include <utility>
#include <vector>

#include <llvm/Support/raw_ostream.h>

namespace psr {

IFDSFieldSensTaintAnalysis::IFDSFieldSensTaintAnalysis(
Expand Down
33 changes: 12 additions & 21 deletions lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h"
#include "phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMFlowFunctions.h"
#include "phasar/PhasarLLVM/DataFlow/IfdsIde/LLVMZeroValue.h"
#include "phasar/PhasarLLVM/Domain/LLVMAnalysisDomain.h"
#include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h"
#include "phasar/PhasarLLVM/TaintConfig/TaintConfigUtilities.h"
#include "phasar/PhasarLLVM/Utils/LLVMIRToSrc.h"
Expand Down Expand Up @@ -408,7 +409,11 @@ auto IFDSTaintAnalysis::getSummaryFlowFunction([[maybe_unused]] n_t CallSite,
return lambdaFlow([Leak{std::move(Leak)}, Kill{std::move(Kill)}, this,
CallSite](d_t Source) -> container_type {
if (Leak.count(Source)) {
Leaks[CallSite].insert(Source);
if (Leaks[CallSite].insert(Source).second) {
Warning<LLVMIFDSAnalysisDomainDefault> War(CallSite, Source,
topElement());
Printer->onResult(War);
}
}

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

if (Leak.count(Source)) {
Leaks[CallSite].insert(Source);
if (Leaks[CallSite].insert(Source).second) {
Warning<LLVMIFDSAnalysisDomainDefault> War(CallSite, Source,
topElement());
Printer->onResult(War);
}
}

return {Source};
Expand Down Expand Up @@ -478,25 +487,7 @@ void IFDSTaintAnalysis::emitTextReport(
const SolverResults<n_t, d_t, BinaryDomain> & /*SR*/,
llvm::raw_ostream &OS) {
OS << "\n----- Found the following leaks -----\n";
if (Leaks.empty()) {
OS << "No leaks found!\n";
return;
}

for (const auto &Leak : Leaks) {
OS << "At instruction\nIR : " << llvmIRToString(Leak.first) << '\n';
OS << "\nLeak(s):\n";
for (const auto *LeakedValue : Leak.second) {
OS << "IR : ";
// Get the actual leaked alloca instruction if possible
if (const auto *Load = llvm::dyn_cast<llvm::LoadInst>(LeakedValue)) {
OS << llvmIRToString(Load->getPointerOperand()) << '\n';
} else {
OS << llvmIRToString(LeakedValue) << '\n';
}
}
OS << "-------------------\n";
}
Printer->onFinalize(OS);
}

} // namespace psr
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@

#include "phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/TypeStateDescriptions/OpenSSLSecureMemoryDescription.h"

#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/ErrorHandling.h"

#include <string>

#include <llvm/ADT/STLExtras.h>

using namespace std;
using namespace psr;

Expand Down
Loading
Loading