PhASAR, a static analysis framework where the solver is the product
A LLVM-based static analysis framework.
At a glance
- What is it?
- PhASAR is a C++ framework built on LLVM IR that lets you state a data-flow problem and have it solved automatically, with the pointer analysis, the call graph and the type hierarchy provided for you. The interesting part is the spread of solvers, from IFDS and IDE through a weighted pushdown variant to a monotone framework for intraprocedural work.
- Who is it for?
- PhASAR suits a research group that writes its own data-flow analyses and wants the infrastructure of call graphs, alias information and interprocedural control flow handled for it, and it suits an industrial team that wants a taint analysis without building one.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
You state the problem, the framework solves it
PhASAR is a LLVM-based static analysis framework written in C++. The core statement is that it allows users to specify arbitrary data-flow problems which are then solved in a fully-automated manner on the specified LLVM IR target code.
The sentence after that is the one that makes the design click. Computing points-to information and call graphs is done by the framework, thus you can focus on what matters.
So the division of labour is: PhASAR owns the expensive, reusable infrastructure, and you own the analysis. It reads LLVM IR, builds alias information, builds a type hierarchy, builds a call graph, builds the interprocedural control flow, and then runs your data-flow problem over that. An analysis that is a few dozen lines of your own code then produces results on a program you did not write.
The key features list shows how many ways the framework offers to express that problem. There is an IFDS/IDE solver for interprocedural data-flow, an experimental WPDS solver based on weighted pushdown systems which can solve any IFDS/IDE problem, and a MonoIFDS solver described as a high-performance data-flow solver for bottom-up IFDS analyses. There is sparse analysis in the form of SparseIFDS, SparseIDE and SparseWPDS for improved performance.
The supporting analysis infrastructure is listed separately. Call-graph construction offers several algorithms, CHA, RTA, VTA and alias-based. Type-hierarchy construction extracts high-level C++ type information from LLVM IR. The points-to and alias infrastructure is described as high-performance alias analyses for LLVM IR, with integration with state-of-the-art alias and points-to information from SVF supported. There is an interprocedural CFG, an ICFG, connecting control-flow with call-graph information. Path-tracking improves results reporting by reconstructing concrete data-flow paths from IFDS/IDE results, which turns a set of facts into something you can read.
Two entries are worth pulling out. The monotone solver is a simple intraprocedural analysis engine based on Monotone Frameworks, which is the classical approach and is a much lower bar than IFDS. And taint analysis is described as infrastructure for taint configuration and IFDS/IDE-based taint analysis, with the configuration coming from IR annotations, a JSON file or callbacks, so the sources and sinks are not hardcoded into your analysis.
The project also states a modern C++20 API with modular, easy-to-use interfaces, also for non C++ experts, and there is a literature page in the wiki collecting papers on PhASAR itself, which is what you want if you are writing a new analysis and need to know what has already been done.
A taint analysis in about twenty lines
The example in the README shows the framework's core concepts in one file, and it is the clearest available statement of what using PhASAR looks like.
#include "phasar.h"
// Load the target LLVM IR
auto IRDB = psr::LLVMProjectIRDB::loadOrExit("target.ll");
// Build alias information, a type-hierarchy, and a taint configuration
// (sources/sinks can come from IR annotations, a JSON file, or callbacks)
psr::LLVMAliasSet AS(&IRDB);
psr::DIBasedTypeHierarchy TH(IRDB);
psr::LLVMTaintConfig TC(IRDB);
// Build the interprocedural CFG using VTA call-graph construction
psr::LLVMBasedICFG ICFG(&IRDB, psr::CallGraphAnalysisType::VTA,
{"main"}, &TH, &AS);
// Instantiate and solve the taint analysis
psr::IFDSTaintAnalysis Problem(&IRDB, &AS, &TC, {"main"});
psr::solveIFDSProblem(Problem, ICFG);
// Inspect detected leaks
for (const auto &[Inst, Facts] : Problem.Leaks) {
llvm::outs() << "Leak at: " << psr::llvmIRToString(Inst) << '\n';
}The sequence is the argument. An IR database loads the target. Then the three analyses the framework provides are constructed: an alias set, a debug-info based type hierarchy, and a taint configuration. Then the interprocedural control flow is built with the VTA call graph algorithm, naming main as the entry point and passing in the type hierarchy and alias set. Then the analysis problem is instantiated with the same three inputs and the entry point, and solved with solveIFDSProblem.
The output is the leaks, with the instruction and its facts, printed through the LLVM IR printer.
Two design details are worth noting for anyone adapting this. The taint configuration's sources and sinks are decoupled from the analysis code, so the same analysis can be pointed at different taint specifications without recompiling the logic. And the entry point is passed as a string set, which means an analysis is not tied to a specific main function.
The README also points at examples/how-to/ for more examples including how to write a custom analysis, which is where the interesting material is for anyone extending the framework rather than just using it.
Building it, and the LLVM version you have to live with
The requirements are narrow in a way that matters. PhASAR requires at least C++20, and it supports C++20 modules as an experimental feature.
The LLVM constraint is the one that will decide your adoption. PhASAR supports LLVM versions between LLVM-16 and LLVM-22.1, using LLVM-16 by default. The project actively tests PhASAR with LLVM-16 and LLVM-22.1, so if something does not work, try these versions instead.
That is a useful piece of advice, because it tells you the tested pair and the supported range are not the same. The version is set with the PHASAR_LLVM_VERSION cmake variable, and there is a wrinkle. Since v18, LLVM uses minor versions, so you use -DPHASAR_LLVM_VERSION=17 for LLVM-17 but -DPHASAR_LLVM_VERSION=22.1 for LLVM-22. A version number that means different things depending on the release is exactly the kind of detail that costs an afternoon if it is not written down.
The Dockerfile shows the build in full, and it is worth reading because the options map onto the feature list. The base is ubuntu:24.04, with tzdata and a set of clang-20 and llvm tools installed through a mounted script. The build is configured with -DBUILD_PHASAR_CLANG=ON, with -DPHASAR_USE_Z3=ON, and with the unittest, IR and integration test targets all tied to the same RUN_TESTS argument. The entrypoint is phasar-cli, and the build ends by running phasar-cli --version as a smoke check.
The submodules check is a nice touch. The build refuses to continue if any directory under external/ is empty, with a message telling you to run git submodule update --init --recursive on the host. That converts a confusing link error later into a clear message at the right moment.
There is a bootstrap.sh in the root, a Dockerfile as well as a docker-compose.yml and a docker-compose.debug.yml, a conanfile.py for the Conan package manager, a Config.cmake.in, cmake/ and config/ directories, and a .pre-commit-config.yaml plus githooks/ for the formatting and hook setup, with a .clang-format and .clang-tidy for the C++ side.
BUILD.md holds the detailed build instructions, and the repository has a CHANGELOG.md, a CREDITS.txt, a CODE_OF_CONDUCT.md, CODING_GUIDELINES.txt and a docs/ directory.
Breaking changes on purpose, and who maintains it
The Breaking Changes section is short and unusual enough to be worth quoting. To keep PhASAR in a state that is well suited for state-of-the-art research in static analysis, as well as for productive use, we have to make breaking changes. The README refers to BreakingChanges.md for detailed information on what was broken recently and how to migrate.
That is an honest position for a research framework. A library that pins its API for compatibility accumulates the compromises of a decade, and a framework whose users are the people writing new analyses needs the API to track what the analyses need. The cost is on the adopter, who has to read a migration document when upgrading, and the benefit is that the framework does not have to carry a compatibility layer for every interface it has ever had.
The maintenance is academic but serious. PhASAR is primarily developed and maintained by the Secure Software Engineering Group at Heinz Nixdorf Institute at the University of Paderborn and Fraunhofer IEM. It was initially developed by Philipp Dominik Schubert, and it is currently maintained by Fabian Schiebel, Sriteja Kummita, Lucas Briese, Martin Mory and others.
The releases are dated in a year-month form, with v2604 as the April 2026 release, v2510 for October 2025 and v2503 for March 2025, which is a release cadence of roughly every six months to a year for a research framework.
The last push was on 2026-10-14, the default branch is development rather than main, and the licence is a custom one that GitHub cannot classify, with the LICENSE.txt file at the root and an MIT badge in the README header.
For integration, the recommendation is to use PhASAR as a library with cmake, using FetchContent or as a git submodule, and the README shows the two lines that matter in your own build:
add_subdirectory(external/phasar EXCLUDE_FROM_ALL) # Build phasar with your tool
...
target_link_libraries(yourphasartool
...
phasar # Make your tool link against phasar
)The EXCLUDE_FROM_ALL is the detail that separates a working integration from a broken one, because without it the PhASAR targets become part of your default build and its tests run in your pipeline.
Editorial conclusion
PhASAR suits a research group that writes its own data-flow analyses and wants the infrastructure of call graphs, alias information and interprocedural control flow handled for it, and it suits an industrial team that wants a taint analysis without building one. It is the wrong choice if you want a turnkey security scanner, since the output is the raw facts your analysis produces rather than a verdict, and it is the wrong choice if you are not on LLVM-16 through 22.1, because that is the supported range and the framework is pinned to it. Before starting, read BreakingChanges.md, since the project states plainly that it makes breaking changes to stay usable for state-of-the-art research, and check the LLVM version your build will use against the tested pair of LLVM-16 and 22.1.
Frequently asked questions
What is PhASAR?
A LLVM-based static analysis framework written in C++. You specify an arbitrary data-flow problem and the framework solves it automatically on the target LLVM IR, providing the points-to information, call graphs, alias analysis and type hierarchy so you can focus on the analysis itself.
Which LLVM versions does PhASAR support?
Between LLVM-16 and LLVM-22.1, with LLVM-16 used by default. The project actively tests with LLVM-16 and LLVM-22.1, and the version is set with the PHASAR_LLVM_VERSION cmake variable, where versions from 18 onwards need a minor version, so -DPHASAR_LLVM_VERSION=22.1 for LLVM-22.
What data-flow solvers does PhASAR offer?
An IFDS/IDE solver for interprocedural data-flow, an experimental WPDS solver based on weighted pushdown systems which can solve any IFDS/IDE problem, a MonoIFDS solver for bottom-up IFDS analyses, sparse variants SparseIFDS, SparseIDE and SparseWPDS, and a monotone solver for intraprocedural analysis based on Monotone Frameworks.
How do I use PhASAR as a library in my own CMake project?
The recommendation is to use it as a library with cmake, through FetchContent or as a git submodule, adding it with add_subdirectory(external/phasar EXCLUDE_FROM_ALL) and linking your tool against the phasar target. Depending on how you use it you may also need to add LLVM to your build.
Does PhASAR make breaking changes?
Yes, and deliberately. The README says that to keep PhASAR well suited for state-of-the-art research in static analysis as well as for productive use, they have to make breaking changes, and points to BreakingChanges.md for what was broken recently and how to migrate.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/secure-software-engineering-phasar)Was this useful?