Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
eddec04
Add FlowFunctionFactory concept
fabianbs96 Apr 16, 2026
1032186
Add EdgeFunctionFactory concept
fabianbs96 Apr 16, 2026
1553e06
Add IFDSProblem concept
fabianbs96 Apr 16, 2026
d8fcc68
Merge branch 'development' into f-DevirtualizeIFDSIDETabulationProblem
fabianbs96 Apr 19, 2026
daf7b77
Add IDEProblem
fabianbs96 Apr 19, 2026
78286c0
Use IDEProblem in IterativeIDESolver
fabianbs96 Apr 19, 2026
c4b5a2e
Add IFDS/IDE problem-wrappers
fabianbs96 Apr 19, 2026
e106ea8
Merge branch 'development' into f-DevirtualizeIFDSIDETabulationProblem
fabianbs96 Jun 8, 2026
32c517c
flow-function abstraction
fabianbs96 Jun 9, 2026
348a6b5
PSR_INTERNAL_LINKAGE
fabianbs96 Jun 11, 2026
4593e5b
Add virtual wrapper for non-virtual ide problem
fabianbs96 Jun 11, 2026
585c683
Make LegacyIDEProblemWrapper work for IFDS problems as well + integra…
fabianbs96 Jun 11, 2026
3852ea2
Devirtualize IDELinearConstantAnalysis + create mixin to make transit…
fabianbs96 Jun 11, 2026
b72ca74
Integrate devirt IDEProblem into PathAwareIDESolver + several minor t…
fabianbs96 Jun 12, 2026
9c54d51
Devirt IFDSTaintAnalysis + make CFLFieldSensIFDSProblem compatible
fabianbs96 Jun 12, 2026
f53f95f
minor
fabianbs96 Jun 12, 2026
6476704
Merge branch 'development' into f-DevirtualizeIFDSIDETabulationProblem
fabianbs96 Jun 12, 2026
94d229a
Devirtualize default Ifds/Ide problems
fabianbs96 Jun 12, 2026
b70cfb3
minor
fabianbs96 Jun 12, 2026
8c47ce7
Many small changes (mostly in FE-Cache)
fabianbs96 Jun 13, 2026
cc79578
Further devirtualize CFLFieldSensIFDSProblem
fabianbs96 Jun 13, 2026
a0b488b
Devirtualize IIA
fabianbs96 Jun 13, 2026
c7d3509
Devirtualize FTA + XTaint
fabianbs96 Jun 13, 2026
527d7db
Devirtualize TSA
fabianbs96 Jun 13, 2026
8ab8432
Fix sample ifds program
fabianbs96 Jun 13, 2026
6f96a61
minor
fabianbs96 Jun 13, 2026
3e52ec5
minor
fabianbs96 Jun 13, 2026
36019bb
Correct allTopFunction() for IFDS problems
fabianbs96 Jun 14, 2026
f9f4f02
Deprecate the ref-taking IFDSSolver ctor overload
fabianbs96 Jun 14, 2026
11c373a
Deprecate the overload of the IDESolver ctor that takes the problem b…
fabianbs96 Jun 14, 2026
d619917
small comment
fabianbs96 Jun 14, 2026
e12a003
Fix some issues
fabianbs96 Jun 14, 2026
fc148f1
Let AI simplify the code a bit
fabianbs96 Jun 14, 2026
9d74b22
Further simplificytion, based on guarantees of IFDSProblem/IDEPooblem…
fabianbs96 Jun 14, 2026
1d8b448
minor
fabianbs96 Jun 14, 2026
ef7e64b
Attempt to fix CI caching
fabianbs96 Jun 15, 2026
d07a500
More explicit types + better Nullable
fabianbs96 Jun 15, 2026
76a3686
minor
fabianbs96 Jun 15, 2026
85c5bfb
Merge branch 'development' into f-DevirtualizeIFDSIDETabulationProblem
fabianbs96 Jul 13, 2026
c1eb824
Fix compilation with gcc
fabianbs96 Jul 18, 2026
85a0a33
Reduce warnings by GCC
fabianbs96 Jul 18, 2026
411f60c
Fix IterIDESolver requirement
fabianbs96 Jul 18, 2026
01ab215
Use newer clang in CI to fix internal compiler error
fabianbs96 Jul 18, 2026
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
5 changes: 3 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
fail-fast: true
matrix:
os: [ubuntu-24.04, ubuntu-24.04-arm]
compiler: [ [clang++-20, clang-20, "clang-20 libclang-rt-20-dev clang-tools-20"] ]
compiler: [ [clang++-21, clang-21, "clang-21 libclang-rt-21-dev clang-tools-21"] ]
build: [ Debug, Release, DebugLibdeps, DebugCov ]
llvm-version: [ 16, "22.1" ]
include:
Expand All @@ -31,7 +31,7 @@ jobs:
- build: DebugCov
cmake_build_type: Debug
flags: -DCODE_COVERAGE=ON
extra_dependencies: llvm-20 # For coverage
extra_dependencies: llvm-21 # For coverage
- llvm-version: 16
llvm-major-version: 16
- llvm-version: "22.1"
Expand Down Expand Up @@ -75,6 +75,7 @@ jobs:
-DBUILD_PHASAR_CLANG=OFF \
-DPHASAR_USE_Z3=ON \
-DPHASAR_BUILD_MODULES=ON \
-DPHASAR_TARGET_ARCH="" \
-DPHASAR_LLVM_VERSION=${{ matrix.llvm-version }} \
${{ matrix.flags }} \
-G Ninja
Expand Down
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,9 @@ include(add_nlohmann_json)
add_nlohmann_json()
add_json_schema_validator()

# TBB
find_package(TBB)

# Coverage
if (CODE_COVERAGE)
set(CODE_COVERAGE_SCRIPT "${CMAKE_CURRENT_BINARY_DIR}/code-coverage.cmake")
Expand Down Expand Up @@ -415,6 +418,10 @@ target_sources(phasar_interface INTERFACE
BASE_DIRS "${PHASAR_SRC_DIR}/include" "${PHASAR_BINARY_DIR}/include"
FILES ${PHASAR_PUBLIC_HEADERS} "${PHASAR_BINARY_DIR}/include/phasar/Config/phasar-config.h"
)
if (TARGET TBB::tbb)
target_link_libraries(phasar_interface INTERFACE TBB::tbb)
endif()


# Some preprocessor symbols that need to be available in phasar sources, but should not be installed
add_cxx_compile_definitions(PHASAR_SRC_DIR="${CMAKE_SOURCE_DIR}")
Expand Down
11 changes: 11 additions & 0 deletions config/double-free-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,17 @@
0
]
}
},
{
"name": "_ZdaPv",
"params": {
"source": [
0
],
"sink": [
0
]
}
}
]
}
15 changes: 8 additions & 7 deletions examples/how-to/07-write-ifds-analysis/simple.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,23 @@ class ExampleTaintAnalysis : public psr::DefaultAliasAwareIFDSProblem {
/// Provides the initial seeds, i.e., the <stmt, fact> pairs that are assumed
/// to hold un-conditionally at the beginning of the analysis.
/// This is the start state that the IFDS solver will use to start with.
[[nodiscard]] psr::InitialSeeds<n_t, d_t, l_t> initialSeeds() override {
[[nodiscard]] psr::InitialSeeds<n_t, d_t, l_t> initialSeeds() {
psr::InitialSeeds<n_t, d_t, l_t> Seeds;

psr::LLVMBasedCFG CFG;
// Here, we just say that for all entry-functions in the EntryPoints, the
// zero-value should hold at the very first statement.
addSeedsForStartingPoints(EntryPoints, IRDB, CFG, Seeds, getZeroValue());
addSeedsForStartingPoints(EntryPoints, getProjectIRDB(), CFG, Seeds,
getZeroValue());

return Seeds;
};

/// Here, we define special semantics of function-calls that are specified
/// outside of the target program. In the case of taint analysis, we need to
/// handle sources, sinks and sanitizers here:
[[nodiscard]] FlowFunctionPtrType
getSummaryFlowFunction(n_t CallSite, f_t DestFun) override {
[[nodiscard]] FlowFunctionPtrType getSummaryFlowFunction(n_t CallSite,
f_t DestFun) {
const auto *CS = llvm::cast<llvm::CallBase>(CallSite);

// Process the effects of source or sink functions that are called
Expand All @@ -60,7 +61,7 @@ class ExampleTaintAnalysis : public psr::DefaultAliasAwareIFDSProblem {
if (Gen.empty() && Leak.empty() && Kill.empty()) {
// This CallSite apparently is not calling a special source/sink/sanitizer
// function. Fallback to the default-behavior.
return DefaultAliasAwareIFDSProblem::getSummaryFlowFunction(CS, DestFun);
return nullptr;
}

// Since our analysis is alias-aware, we must handle aliasing here:
Expand All @@ -76,13 +77,13 @@ class ExampleTaintAnalysis : public psr::DefaultAliasAwareIFDSProblem {
return Gen;
}

if (Leak.count(Source)) {
if (Leak.contains(Source)) {
// In case of a sink, we create a leak if one of the leaking parameters
// (Leak) is tainted (Source).
Leaks.insert(CS);
}

if (Kill.count(Source)) {
if (Kill.contains(Source)) {
// In case of a sanitizer, we kill tainted values (Source) that flow
// into the sanitizied parameters (Kill).
return {};
Expand Down
33 changes: 18 additions & 15 deletions examples/how-to/08-write-ide-analysis/simple.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,19 +54,19 @@ class ExampleLinearConstantAnalysis
/// to hold un-conditionally at the beginning of the analysis.
/// Similar to IFDS, this is the start state that the IDE solver will use to
/// start with.
[[nodiscard]] psr::InitialSeeds<n_t, d_t, l_t> initialSeeds() override {
[[nodiscard]] psr::InitialSeeds<n_t, d_t, l_t> initialSeeds() {
psr::InitialSeeds<n_t, d_t, l_t> Seeds;

psr::LLVMBasedCFG CFG;
// Here, we just say that for all entry-functions in the EntryPoints, the
// zero-value should hold at the very first statement.
addSeedsForStartingPoints(EntryPoints, IRDB, CFG, Seeds, getZeroValue(),
bottomElement());
addSeedsForStartingPoints(EntryPoints, getProjectIRDB(), CFG, Seeds,
getZeroValue(), bottomElement());

return Seeds;
};

FlowFunctionPtrType getNormalFlowFunction(n_t Curr, n_t Succ) override {
FlowFunctionPtrType getNormalFlowFunction(n_t Curr, n_t Succ) {
if (const auto *Alloca = llvm::dyn_cast<llvm::AllocaInst>(Curr)) {
// Freshly allocated variables hold no constant value

Expand All @@ -88,7 +88,7 @@ class ExampleLinearConstantAnalysis
return this->DefaultNoAliasIDEProblem::getNormalFlowFunction(Curr, Succ);
}

FlowFunctionPtrType getCallFlowFunction(n_t CallSite, f_t DestFun) override {
FlowFunctionPtrType getCallFlowFunction(n_t CallSite, f_t DestFun) {
// We definitely want to re-use as much as possible from the default
// call-flow-function
auto DefaultFn =
Expand Down Expand Up @@ -118,7 +118,7 @@ class ExampleLinearConstantAnalysis
}

FlowFunctionPtrType getRetFlowFunction(n_t CallSite, f_t CalleeFun,
n_t ExitInst, n_t RetSite) override {
n_t ExitInst, n_t RetSite) {

auto DefaultFn = this->DefaultNoAliasIDEProblem::getRetFlowFunction(
CallSite, CalleeFun, ExitInst, RetSite);
Expand Down Expand Up @@ -352,8 +352,7 @@ class ExampleLinearConstantAnalysis
};

psr::EdgeFunction<l_t> getNormalEdgeFunction(n_t Curr, d_t CurrNode,
n_t /*Succ*/,
d_t SuccNode) override {
n_t /*Succ*/, d_t SuccNode) {
if (isZeroValue(CurrNode) && !isZeroValue(SuccNode)) {
// Handle the two cases, where we generate facts from zero:

Expand Down Expand Up @@ -384,8 +383,11 @@ class ExampleLinearConstantAnalysis
}

// Attach the arithmetic transformer to this edge
return BinOp{Op, llvm::dyn_cast<llvm::ConstantInt>(Lop),
llvm::dyn_cast<llvm::ConstantInt>(Rop)};
return BinOp{
.OpCode = Op,
.LeftConst = llvm::dyn_cast<llvm::ConstantInt>(Lop),
.RightConst = llvm::dyn_cast<llvm::ConstantInt>(Rop),
};
}

// Pass everything else as identity
Expand All @@ -394,7 +396,7 @@ class ExampleLinearConstantAnalysis

psr::EdgeFunction<l_t> getCallEdgeFunction(n_t CallSite, d_t SrcNode,
f_t /*DestinationFunction*/,
d_t DestNode) override {
d_t DestNode) {
if (isZeroValue(SrcNode) && !isZeroValue(DestNode)) {
// If a constant int is passed as parameter, we need to generate the
// parameter inside the callee from zero
Expand All @@ -408,9 +410,10 @@ class ExampleLinearConstantAnalysis
return psr::EdgeIdentity<l_t>{};
}

psr::EdgeFunction<l_t>
getReturnEdgeFunction(n_t CallSite, f_t /*CalleeFunction*/, n_t ExitStmt,
d_t ExitNode, n_t /*RetSite*/, d_t RetNode) override {
psr::EdgeFunction<l_t> getReturnEdgeFunction(n_t CallSite,
f_t /*CalleeFunction*/,
n_t ExitStmt, d_t ExitNode,
n_t /*RetSite*/, d_t RetNode) {
if (isZeroValue(ExitNode) && RetNode == CallSite) {
// If we return a literal constant int, we must generate the corresponding
// value at the call-site from zero, i.e., the CallSite itself in case of
Expand All @@ -428,7 +431,7 @@ class ExampleLinearConstantAnalysis
psr::EdgeFunction<l_t>
getCallToRetEdgeFunction(n_t /*CallSite*/, d_t /*CallNode*/, n_t /*RetSite*/,
d_t /*RetSiteNode*/,
llvm::ArrayRef<f_t> /*Callees*/) override {
llvm::ArrayRef<f_t> /*Callees*/) {
// The call-to-return edge-function handles facts that are not affected by
// the call. This is usually the identity function.
return psr::EdgeIdentity<l_t>{};
Expand Down
9 changes: 9 additions & 0 deletions include/phasar/DB/ProjectIRDB.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "llvm/ADT/StringRef.h"

#include <concepts>
#include <type_traits>

namespace psr {

Expand Down Expand Up @@ -112,6 +113,14 @@ concept ProjectIRDB =
requires ProjectSymbolTable<T>;
};

template <typename T>
concept ProjectIRDBPtr =
ProjectIRDB<std::remove_reference_t<decltype(*std::declval<T>())>>;
template <typename T>
concept ProjectIRDBConstPtr =
std::is_const_v<std::remove_reference_t<decltype(*std::declval<T>())>> &&
ProjectIRDB<std::remove_cvref_t<decltype(*std::declval<T>())>>;

// NOLINTNEXTLINE(readability-identifier-naming)
auto IRDBGetFunctionDef(const ProjectIRDB auto *IRDB) noexcept {
return [IRDB](llvm::StringRef Name) {
Expand Down
4 changes: 4 additions & 0 deletions include/phasar/DataFlow.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@
#include "phasar/DataFlow/IfdsIde/EdgeFunctions.h"
#include "phasar/DataFlow/IfdsIde/EntryPointUtils.h"
#include "phasar/DataFlow/IfdsIde/FlowFunctions.h"
#include "phasar/DataFlow/IfdsIde/IDEProblem.h"
#include "phasar/DataFlow/IfdsIde/IDEProblemWrapper.h"
#include "phasar/DataFlow/IfdsIde/IDETabulationProblem.h"
#include "phasar/DataFlow/IfdsIde/IFDSProblem.h"
#include "phasar/DataFlow/IfdsIde/IFDSTabulationProblem.h"
#include "phasar/DataFlow/IfdsIde/IfdsToIdeProblemAdapter.h"
#include "phasar/DataFlow/IfdsIde/InitialSeeds.h"
#include "phasar/DataFlow/IfdsIde/Solver/FlowEdgeFunctionCache.h"
#include "phasar/DataFlow/IfdsIde/Solver/IDESolver.h"
Expand Down
9 changes: 7 additions & 2 deletions include/phasar/DataFlow/IfdsIde/EdgeFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ concept IsEdgeFunction = requires(const T &EF, typename T::l_t Src) {
{ EF.computeTarget(Src) } -> std::convertible_to<typename T::l_t>;
};

template <typename T, typename L>
concept IsEdgeFunctionFor = IsEdgeFunction<T> && requires {
requires std::same_as<typename T::l_t, L>;
};

template <typename T>
concept HasEFCompose = requires(EdgeFunctionRef<T> EFRef,
const EdgeFunction<typename T::l_t> &EF) {
Expand Down Expand Up @@ -110,7 +115,7 @@ class EdgeFunctionBase {
/// \brief Non-null reference to an edge function that is guarenteed to be
/// managed by an EdgeFunction object.
template <typename EF>
class [[gsl::Pointer(EF)]] EdgeFunctionRef final : EdgeFunctionBase {
class PSR_POINTER(EF) EdgeFunctionRef final : EdgeFunctionBase {
template <typename L> friend class EdgeFunction;

public:
Expand Down Expand Up @@ -160,7 +165,7 @@ class [[gsl::Pointer(EF)]] EdgeFunctionRef final : EdgeFunctionBase {
template <typename L>
// -- combined copy and move assignment
// NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
class [[clang::trivial_abi, gsl::Owner]] EdgeFunction final : EdgeFunctionBase {
class PSR_TRIVIAL_ABI PSR_OWNER() EdgeFunction final : EdgeFunctionBase {
public:
using l_t = L;

Expand Down
Loading
Loading