Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
0c6d0c0
Start with sparse ICFG
fabianbs96 Mar 29, 2024
58d4f67
Build sparse CFG (not tested yet)
fabianbs96 Apr 1, 2024
acc467d
Integrate Sparse CFG into IDESolver + add test (WIP)
fabianbs96 Apr 4, 2024
fd00f1f
Make sparse IDE work for linear constant analysis
fabianbs96 Apr 7, 2024
833a139
Add taint analysis to SparseIDETest (passes) -- NO SPARSITY!!
fabianbs96 Apr 7, 2024
93087b0
minor
fabianbs96 Apr 7, 2024
d101dc7
Select right opt tool for mem2reg
fabianbs96 Jun 9, 2024
a9dc76f
Introduce PSR_FWD
fabianbs96 Jun 9, 2024
ca3b968
Integrate sparse ifds taint analysis into phasar-cli
fabianbs96 Jun 9, 2024
2167bbe
Merge branch 'development' into f-SparseIDE
fabianbs96 Jun 9, 2024
9523fe5
Fix build after merge from dev +relax opt path requirement
fabianbs96 Jun 9, 2024
c4994e0
Fix opt-tool selection
fabianbs96 Jun 9, 2024
cf14f78
fallback
fabianbs96 Jun 9, 2024
cdb2f85
Merge branch 'development' into f-SparseIDE
fabianbs96 Oct 14, 2024
0d0b592
Fixed seqfault if find() = end()
mxHuber Oct 18, 2024
8f820b3
AliasAnalysis for fuzzyMayAlias
mxHuber Oct 29, 2024
3dbc530
changed to LLVMAliasInfoRef
mxHuber Oct 30, 2024
dcb239d
some cleanup
fabianbs96 Nov 28, 2024
2335d4e
Merge branch 'development' into f-SparseIDE
fabianbs96 Nov 28, 2024
c9d9ba1
minor
fabianbs96 Dec 15, 2024
037befa
Merge branch 'development' into f-SparseIDE
fabianbs96 Feb 14, 2025
16c7c4a
Merge branch 'development' into f-SparseIDE
fabianbs96 Feb 22, 2025
e378fab
Merge branch 'development' into f-SparseIDE
fabianbs96 Mar 3, 2025
13140d3
Merge branch 'development' into f-SparseIDE
fabianbs96 Mar 4, 2025
4e32608
Fix build due to merge
fabianbs96 Mar 4, 2025
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
2 changes: 2 additions & 0 deletions .clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ Checks: '-*,
-readability-convert-member-functions-to-static,
-readability-isolate-declaration,
-readability-identifier-length,
-readability-redundant-member-init,
-readability-use-anyofallof,
cppcoreguidelines-*,
-cppcoreguidelines-avoid-non-const-global-variables,
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ set(RELEASE_CONFIGURATIONS RELWITHDEBINFO RELEASE CACHE INTERNAL "" FORCE)
# https://reviews.llvm.org/D157613

string(APPEND CMAKE_CXX_FLAGS " -MP -fstack-protector-strong -ffunction-sections -fdata-sections -pipe")
string(APPEND CMAKE_CXX_FLAGS_DEBUG " -Og -fno-omit-frame-pointer")
string(APPEND CMAKE_CXX_FLAGS_DEBUG " -fno-omit-frame-pointer")
string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " -fno-omit-frame-pointer")
string(APPEND CMAKE_CXX_FLAGS_RELEASE "")

Expand Down
28 changes: 28 additions & 0 deletions config/double-free-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "double-free",
"version": 1.0,
"functions": [
{
"name": "free",
"params": {
"source": [
0
],
"sink": [
0
]
}
},
{
"name": "_ZdlPv",
"params": {
"source": [
0
],
"sink": [
0
]
}
}
]
}
2 changes: 1 addition & 1 deletion include/phasar/ControlFlow/CFGBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ template <typename Derived> class CFGBase {
return self().getAsJsonImpl(Fun);
}

private:
protected:
Derived &self() noexcept { return static_cast<Derived &>(*this); }
const Derived &self() const noexcept {
return static_cast<const Derived &>(*this);
Expand Down
43 changes: 43 additions & 0 deletions include/phasar/ControlFlow/SparseCFGBase.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/******************************************************************************
* Copyright (c) 2024 Fabian Schiebel.
* All rights reserved. This program and the accompanying materials are made
* available under the terms of LICENSE.txt.
*
* Contributors:
* Fabian Schiebel and others
*****************************************************************************/

#ifndef PHASAR_CONTROLFLOW_SPARSECFGBASE_H
#define PHASAR_CONTROLFLOW_SPARSECFGBASE_H

#include "phasar/ControlFlow/CFGBase.h"
#include "phasar/Utils/ByRef.h"
#include "phasar/Utils/Nullable.h"

namespace psr {
template <typename Derived> class SparseCFGBase : public CFGBase<Derived> {
public:
using typename CFGBase<Derived>::n_t;
using typename CFGBase<Derived>::f_t;

/// Gets the next instruction in control-flow order, starting from
/// FromInstruction, that may use or define Val.
/// If the next user is ambiguous, returns null.
[[nodiscard]] Nullable<n_t>
nextUserOrNull(ByConstRef<n_t> FromInstruction) const {
return self().nextUserOrNullImpl(FromInstruction);
}

protected:
using CFGBase<Derived>::self;
};

template <typename ICF, typename Domain>
// NOLINTNEXTLINE(readability-identifier-naming)
constexpr bool is_sparse_cfg_v = is_crtp_base_of_v<SparseCFGBase, ICF>
&&std::is_same_v<typename ICF::n_t, typename Domain::n_t>
&&std::is_same_v<typename ICF::f_t, typename Domain::f_t>;

} // namespace psr

#endif // PHASAR_CONTROLFLOW_SPARSECFGBASE_H
54 changes: 54 additions & 0 deletions include/phasar/ControlFlow/SparseCFGProvider.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/******************************************************************************
* Copyright (c) 2024 Fabian Schiebel.
* All rights reserved. This program and the accompanying materials are made
* available under the terms of LICENSE.txt.
*
* Contributors:
* Fabian Schiebel and others
*****************************************************************************/

#ifndef PHASAR_CONTROLFLOW_SPARSECFGPROVIDER_H
#define PHASAR_CONTROLFLOW_SPARSECFGPROVIDER_H

#include "phasar/Utils/ByRef.h"

#include <type_traits>

namespace psr {
template <typename T> T valueOf(T Val) { return Val; }

template <typename Derived, typename F, typename V> class SparseCFGProvider {
public:
using f_t = F;
using v_t = V;

template <typename D>
[[nodiscard]] decltype(auto) getSparseCFG(ByConstRef<f_t> Fun,
const D &Val) const {
using psr::valueOf;
static_assert(std::is_convertible_v<decltype(valueOf(Val)), v_t>);
return self().getSparseCFGImpl(Fun, valueOf(Val));
}

private:
Derived &self() noexcept { return static_cast<Derived &>(*this); }
const Derived &self() const noexcept {
return static_cast<const Derived &>(*this);
}
};

template <typename T, typename D, typename = void>
struct has_getSparseCFG : std::false_type {}; // NOLINT
template <typename T, typename D>
struct has_getSparseCFG<
T, D,
std::void_t<decltype(std::declval<const T>().getSparseCFG(
std::declval<typename T::f_t>(), std::declval<D>()))>>
: std::true_type {};

template <typename T, typename D>
// NOLINTNEXTLINE
static constexpr bool has_getSparseCFG_v = has_getSparseCFG<T, D>::value;
} // namespace psr

#endif // PHASAR_CONTROLFLOW_SPARSECFGPROVIDER_H
3 changes: 2 additions & 1 deletion include/phasar/DataFlow/IfdsIde/FlowFunctions.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#ifndef PHASAR_DATAFLOW_IFDSIDE_FLOWFUNCTIONS_H
#define PHASAR_DATAFLOW_IFDSIDE_FLOWFUNCTIONS_H

#include "phasar/Utils/Macros.h"
#include "phasar/Utils/TypeTraits.h"

#include "llvm/ADT/ArrayRef.h"
Expand Down Expand Up @@ -131,7 +132,7 @@ Container makeContainer(Range &&Rng) {
Container C;
reserveIfPossible(C, Rng.size());
for (auto &&Fact : Rng) {
C.insert(std::forward<decltype(Fact)>(Fact));
C.insert(PSR_FWD(Fact));
}
return C;
}
Expand Down
83 changes: 73 additions & 10 deletions include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#define PHASAR_DATAFLOW_IFDSIDE_SOLVER_IDESOLVER_H

#include "phasar/Config/Configuration.h"
#include "phasar/ControlFlow/SparseCFGProvider.h"
#include "phasar/DB/ProjectIRDBBase.h"
#include "phasar/DataFlow/IfdsIde/EdgeFunction.h"
#include "phasar/DataFlow/IfdsIde/EdgeFunctionStats.h"
Expand All @@ -35,15 +36,19 @@
#include "phasar/DataFlow/IfdsIde/SolverResults.h"
#include "phasar/Domain/AnalysisDomain.h"
#include "phasar/Utils/Average.h"
#include "phasar/Utils/ByRef.h"
#include "phasar/Utils/DOTGraph.h"
#include "phasar/Utils/JoinLattice.h"
#include "phasar/Utils/Logger.h"
#include "phasar/Utils/Macros.h"
#include "phasar/Utils/Nullable.h"
#include "phasar/Utils/PAMMMacros.h"
#include "phasar/Utils/Table.h"
#include "phasar/Utils/Utilities.h"

#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/TypeName.h"
#include "llvm/Support/raw_ostream.h"

#include "nlohmann/json.hpp"
Expand Down Expand Up @@ -81,14 +86,24 @@ class IDESolver
using t_t = typename AnalysisDomainTy::t_t;
using v_t = typename AnalysisDomainTy::v_t;

template <typename I>
IDESolver(IDETabulationProblem<AnalysisDomainTy, Container> &Problem,
const i_t *ICF)
: IDEProblem(Problem), ZeroValue(Problem.getZeroValue()), ICF(ICF),
const I *ICF)
: IDEProblem(Problem), ZeroValue(Problem.getZeroValue()),
ICF(&static_cast<const i_t &>(*ICF)), SVFG(ICF),
SolverConfig(Problem.getIFDSIDESolverConfig()),
CachedFlowEdgeFunctions(Problem), AllTop(Problem.allTopFunction()),
JumpFn(std::make_shared<JumpFunctions<AnalysisDomainTy, Container>>()),
Seeds(Problem.initialSeeds()) {
assert(ICF != nullptr);

if constexpr (has_getSparseCFG_v<I, d_t>) {
NextUserOrNullCB = [](const void *SVFG, ByConstRef<f_t> Fun,
ByConstRef<d_t> d3, ByConstRef<n_t> n) {
auto &&SCFG = static_cast<const I *>(SVFG)->getSparseCFG(Fun, d3);
return SCFG.nextUserOrNull(n);
};
}
}

IDESolver(IDETabulationProblem<AnalysisDomainTy, Container> *Problem,
Expand Down Expand Up @@ -339,6 +354,15 @@ class IDESolver
}

protected:
Nullable<n_t> getNextUserOrNull(ByConstRef<f_t> Fun, ByConstRef<d_t> d3,
ByConstRef<n_t> n) {
if (!NextUserOrNullCB || IDEProblem.isZeroValue(d3)) {
return {};
}

return NextUserOrNullCB(SVFG, Fun, d3, n);
}

/// Lines 13-20 of the algorithm; processing a call site in the caller's
/// context.
///
Expand Down Expand Up @@ -382,6 +406,15 @@ class IDESolver

bool HasNoCalleeInformation = true;

auto &&Fun = ICF->getFunctionOf(n);
auto GetNextUse = [this, &Fun, &n](n_t nPrime, ByConstRef<d_t> d3) {
if (auto &&NextUser = getNextUserOrNull(Fun, d3, n)) {
return psr::unwrapNullable(PSR_FWD(NextUser));
}

return nPrime;
};

// for each possible callee
for (f_t SCalledProcN : Callees) { // still line 14
// check if a special summary for the called procedure exists
Expand Down Expand Up @@ -409,7 +442,9 @@ class IDESolver
"Queried Summary Edge Function: " << SumEdgFnE);
PHASAR_LOG_LEVEL(DEBUG,
"Compose: " << SumEdgFnE << " * " << f << '\n');
WorkList.emplace_back(PathEdge(d1, ReturnSiteN, std::move(d3)),

auto DestN = GetNextUse(ReturnSiteN, d3);
WorkList.emplace_back(PathEdge(d1, DestN, std::move(d3)),
IDEProblem.extend(f, SumEdgFnE));
}
}
Expand Down Expand Up @@ -508,8 +543,10 @@ class IDESolver
d_t d5_restoredCtx = restoreContextOnReturnedFact(n, d2, d5);
// propagte the effects of the entire call
PHASAR_LOG_LEVEL(DEBUG, "Compose: " << fPrime << " * " << f);

auto DestN = GetNextUse(RetSiteN, d5_restoredCtx);
WorkList.emplace_back(
PathEdge(d1, RetSiteN, std::move(d5_restoredCtx)),
PathEdge(d1, DestN, std::move(d5_restoredCtx)),
IDEProblem.extend(f, fPrime));
}
}
Expand Down Expand Up @@ -545,7 +582,8 @@ class IDESolver
auto fPrime = IDEProblem.extend(f, EdgeFnE);
PHASAR_LOG_LEVEL(DEBUG, "Compose: " << EdgeFnE << " * " << f << " = "
<< fPrime);
WorkList.emplace_back(PathEdge(d1, ReturnSiteN, std::move(d3)),
auto DestN = GetNextUse(ReturnSiteN, d3);
WorkList.emplace_back(PathEdge(d1, DestN, std::move(d3)),
std::move(fPrime));
}
}
Expand All @@ -563,6 +601,8 @@ class IDESolver
EdgeFunction<l_t> f = jumpFunction(Edge);
auto [d1, n, d2] = Edge.consume();

const auto &Fun = ICF->getFunctionOf(n);

for (const auto nPrime : ICF->getSuccsOf(n)) {
FlowFunctionPtrType FlowFunc =
CachedFlowEdgeFunctions.getNormalFlowFunction(n, nPrime);
Expand All @@ -575,14 +615,23 @@ class IDESolver
CachedFlowEdgeFunctions.getNormalEdgeFunction(n, d2, nPrime, d3);
PHASAR_LOG_LEVEL(DEBUG, "Queried Normal Edge Function: " << g);
EdgeFunction<l_t> fPrime = IDEProblem.extend(f, g);

auto DestN = [&, &n = n] {
if (auto &&NextUser = getNextUserOrNull(Fun, d3, n)) {
return psr::unwrapNullable(PSR_FWD(NextUser));
}

return nPrime;
}();

if (SolverConfig.emitESG()) {
IntermediateEdgeFunctions[std::make_tuple(n, d2, nPrime, d3)]
IntermediateEdgeFunctions[std::make_tuple(n, d2, DestN, d3)]
.push_back(g);
}
PHASAR_LOG_LEVEL(DEBUG,
"Compose: " << g << " * " << f << " = " << fPrime);
INC_COUNTER("EF Queries", 1, Full);
WorkList.emplace_back(PathEdge(d1, nPrime, std::move(d3)),
WorkList.emplace_back(PathEdge(d1, DestN, std::move(d3)),
std::move(fPrime));
}
}
Expand Down Expand Up @@ -915,6 +964,7 @@ class IDESolver
for (const auto &Entry : Inc) {
// line 22
n_t c = Entry.first;
auto &&Fun = ICF->getFunctionOf(c);
// for each return site
for (n_t RetSiteC : ICF->getReturnSitesOfCallAt(c)) {
// compute return-flow function
Expand Down Expand Up @@ -968,9 +1018,19 @@ class IDESolver
d_t d3 = ValAndFunc.first;
d_t d5_restoredCtx = restoreContextOnReturnedFact(c, d4, d5);
PHASAR_LOG_LEVEL(DEBUG, "Compose: " << fPrime << " * " << f3);
WorkList.emplace_back(PathEdge(std::move(d3), RetSiteC,
std::move(d5_restoredCtx)),
IDEProblem.extend(f3, fPrime));

auto DestN = [&] {
if (auto &&NextUser =
getNextUserOrNull(Fun, d5_restoredCtx, c)) {
return psr::unwrapNullable(PSR_FWD(NextUser));
}

return RetSiteC;
}();

WorkList.emplace_back(
PathEdge(std::move(d3), DestN, std::move(d5_restoredCtx)),
IDEProblem.extend(f3, fPrime));
}
}
}
Expand Down Expand Up @@ -1809,7 +1869,10 @@ class IDESolver
IDETabulationProblem<AnalysisDomainTy, Container> &IDEProblem;
d_t ZeroValue;
const i_t *ICF;
const void *SVFG;
IFDSIDESolverConfig &SolverConfig;
Nullable<n_t> (*NextUserOrNullCB)(const void *, ByConstRef<f_t>,
ByConstRef<d_t>, ByConstRef<n_t>) = nullptr;

std::vector<std::pair<PathEdge<n_t, d_t>, EdgeFunction<l_t>>> WorkList;
std::vector<std::pair<n_t, d_t>> ValuePropWL;
Expand Down
10 changes: 5 additions & 5 deletions include/phasar/DataFlow/IfdsIde/Solver/IFDSSolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,17 @@ class IFDSSolver
using n_t = typename AnalysisDomainTy::n_t;
using i_t = typename AnalysisDomainTy::i_t;

template <typename IfdsDomainTy,
template <typename IfdsDomainTy, typename I,
typename = std::enable_if_t<
std::is_base_of_v<IfdsDomainTy, AnalysisDomainTy>>>
IFDSSolver(IFDSTabulationProblem<IfdsDomainTy, Container> &IFDSProblem,
const i_t *ICF)
: IDESolver<WithBinaryValueDomain<AnalysisDomainTy>>(&IFDSProblem, ICF) {}
template <typename IfdsDomainTy,
const I *ICF)
: IDESolver<WithBinaryValueDomain<AnalysisDomainTy>>(IFDSProblem, ICF) {}
template <typename IfdsDomainTy, typename I,
typename = std::enable_if_t<
std::is_base_of_v<IfdsDomainTy, AnalysisDomainTy>>>
IFDSSolver(IFDSTabulationProblem<IfdsDomainTy, Container> *IFDSProblem,
const i_t *ICF)
const I *ICF)
: IDESolver<WithBinaryValueDomain<AnalysisDomainTy>>(IFDSProblem, ICF) {}

~IFDSSolver() override = default;
Expand Down
Loading
Loading