Skip to content

Commit 986b414

Browse files
fabianbs96Fabian Schiebel
andauthored
CFL Field Sensitivity (#814)
* Add alloc-sites-aware default problem + start adding IDEDroid-like formulation of field-sensitive IFDS * Continue with CFL implementation (WIP) * Fully compiling CFL-field-sens IFDS implementation * Add some simple unittests (WIP) * Add a hack to make the alias information partially field sensitive * Change alias handling * Add more (passing) XTaint tests * Add sanitizer-customization-point + fix bug in combine() with EdgeIdentity * Fix minor compilation issue * Out-comment unnecessary stuff * Convert CFLFieldSensTest to testingSrcLocation + add logger to FieldSensAllocSitesAwareIFDSProblem * Optimize CFLFieldSensEdgeValue::applyTransforms * Some cleanup + optimize creation of CFLFieldSensEdgeFunction * minor * Some optimizations * Add corner case tests * Fix edge-cases in CFL-Fieldsens analysis + make corresponding tests (xtaint 22,23) pass * Small tweak in CFLFieldSensTest + minor * Add structural sharing for Store- and Load sequences * Some cleanup + small enhancement to LatticeDomain-join * Add some comment * Fix errors after merge * minor * Integrate CFL-fieldsens analysis into phasar-cli for IFDSTaintAnalysis * Rename cfl fieldsens analysis problem + introduce own namespace for it * Add generic mechanism to filter IFDS analysis results field-sensitively * Properly handling non-existing value * Add some comments + minor * pre-commit * Fix stack-use-after-return in IdBasedSolverResults * small optimization based on alltop --------- Co-authored-by: Fabian Schiebel <fabian.schiebel@uni-paderborn.de>
1 parent 1310d47 commit 986b414

36 files changed

Lines changed: 2760 additions & 183 deletions

include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ template <typename L> struct EdgeIdentity final {
3939
[[nodiscard]] static EdgeFunction<l_t>
4040
join(EdgeFunctionRef<EdgeIdentity> This,
4141
const EdgeFunction<l_t> &OtherFunction);
42+
43+
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, EdgeIdentity) {
44+
return OS << "EdgeIdentity";
45+
}
4246
};
4347

4448
template <typename L> struct ConstantEdgeFunction {
@@ -164,6 +168,10 @@ template <typename L> struct AllBottom final {
164168
{
165169
return LHS.BottomValue == RHS.BottomValue;
166170
}
171+
172+
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, AllBottom) {
173+
return OS << "AllBottom";
174+
}
167175
};
168176

169177
template <typename L> struct AllTop final {
@@ -202,10 +210,14 @@ template <typename L> struct AllTop final {
202210
{
203211
return LHS.TopValue == RHS.TopValue;
204212
}
213+
214+
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, AllTop) {
215+
return OS << "AllTop";
216+
}
205217
};
206218

207219
template <typename L, typename ConcreteEF>
208-
EdgeFunction<L>
220+
inline EdgeFunction<L>
209221
defaultComposeOrNull(EdgeFunctionRef<ConcreteEF> This,
210222
const EdgeFunction<L> &SecondFunction) noexcept {
211223
if (llvm::isa<EdgeIdentity<L>>(SecondFunction)) {
@@ -218,7 +230,7 @@ defaultComposeOrNull(EdgeFunctionRef<ConcreteEF> This,
218230
}
219231

220232
template <typename L>
221-
EdgeFunction<L>
233+
inline EdgeFunction<L>
222234
defaultComposeOrNull(const EdgeFunction<L> &This,
223235
const EdgeFunction<L> &SecondFunction) noexcept {
224236
if (llvm::isa<EdgeIdentity<L>>(SecondFunction)) {
@@ -409,8 +421,8 @@ template <typename L, uint8_t N> struct JoinEdgeFunction {
409421
/// Joining with EdgeIdentity will overapproximate to (AllBottom if N==0, else
410422
/// JoinEdgeFunction).
411423
template <typename L, uint8_t N = 0, typename ConcreteEF>
412-
EdgeFunction<L> defaultJoinOrNull(EdgeFunctionRef<ConcreteEF> This,
413-
const EdgeFunction<L> &OtherFunction) {
424+
inline EdgeFunction<L> defaultJoinOrNull(EdgeFunctionRef<ConcreteEF> This,
425+
const EdgeFunction<L> &OtherFunction) {
414426
if (llvm::isa<AllBottom<L>>(OtherFunction)) {
415427
return OtherFunction;
416428
}
@@ -428,8 +440,8 @@ EdgeFunction<L> defaultJoinOrNull(EdgeFunctionRef<ConcreteEF> This,
428440
}
429441

430442
template <typename L, uint8_t N = 0>
431-
EdgeFunction<L> defaultJoinOrNull(const EdgeFunction<L> &This,
432-
const EdgeFunction<L> &OtherFunction) {
443+
inline EdgeFunction<L> defaultJoinOrNull(const EdgeFunction<L> &This,
444+
const EdgeFunction<L> &OtherFunction) {
433445
if (llvm::isa<AllBottom<L>>(OtherFunction) || llvm::isa<AllTop<L>>(This)) {
434446
return OtherFunction;
435447
}
@@ -447,6 +459,23 @@ EdgeFunction<L> defaultJoinOrNull(const EdgeFunction<L> &This,
447459
return nullptr;
448460
}
449461

462+
/// Similar to defaultJoinOrNull(), but does not handle This==OtherFunction and
463+
/// EdgeIdentity.
464+
template <typename L>
465+
inline EdgeFunction<L>
466+
defaultJoinOrNullNoId(const EdgeFunction<L> &This,
467+
const EdgeFunction<L> &OtherFunction) {
468+
if (llvm::isa<AllBottom<L>>(OtherFunction) || llvm::isa<AllTop<L>>(This)) {
469+
return OtherFunction;
470+
}
471+
if (llvm::isa<AllTop<L>>(OtherFunction) || llvm::isa<AllBottom<L>>(This) ||
472+
OtherFunction.referenceEquals(This)) {
473+
return This;
474+
}
475+
476+
return nullptr;
477+
}
478+
450479
template <typename L>
451480
EdgeFunction<L> EdgeIdentity<L>::join(EdgeFunctionRef<EdgeIdentity> This,
452481
const EdgeFunction<L> &OtherFunction) {

include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <set>
3535
#include <string>
3636
#include <type_traits>
37+
#include <utility>
3738

3839
namespace psr {
3940

@@ -122,6 +123,19 @@ class IDETabulationProblem : public FlowFunctions<AnalysisDomainTy, Container>,
122123
}
123124
}
124125

126+
[[nodiscard]] constexpr AnalysisPrinterBase<AnalysisDomainTy> &
127+
printer() noexcept {
128+
assert(Printer != nullptr);
129+
return *Printer;
130+
}
131+
132+
[[nodiscard]] constexpr MaybeUniquePtr<AnalysisPrinterBase<AnalysisDomainTy>>
133+
consumePrinter() noexcept {
134+
assert(Printer != nullptr);
135+
return std::exchange(Printer,
136+
NullAnalysisPrinter<AnalysisDomainTy>::getInstance());
137+
}
138+
125139
/// Checks if the given data-flow fact is the special tautological lambda (or
126140
/// zero) fact.
127141
[[nodiscard]] virtual bool isZeroValue(d_t FlowFact) const noexcept {
@@ -177,6 +191,10 @@ class IDETabulationProblem : public FlowFunctions<AnalysisDomainTy, Container>,
177191

178192
[[nodiscard]] const db_t *getProjectIRDB() const noexcept { return IRDB; }
179193

194+
[[nodiscard]] llvm::ArrayRef<std::string> getEntryPoints() const noexcept {
195+
return EntryPoints;
196+
}
197+
180198
protected:
181199
typename FlowFunctions<AnalysisDomainTy, Container>::FlowFunctionPtrType
182200
generateFromZero(d_t FactToGenerate) {

include/phasar/DataFlow/IfdsIde/Solver/IdBasedSolverResults.h

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,13 @@ class IdBasedSolverResultsBase {
2828
class RowView {
2929
struct Transformator {
3030
const detail::IterativeIDESolverResults<n_t, d_t, l_t> *Results{};
31-
mutable std::optional<std::pair<d_t, l_t>> Cache{};
3231

33-
const std::pair<d_t, l_t> &
32+
// --v Needed for llvm::mapped_iterator
33+
// NOLINTNEXTLINE(readability-const-return-type)
34+
const std::pair<const d_t &, const l_t &>
3435
operator()(ByConstRef<typename row_map_t::value_type> Entry) const {
35-
Cache = std::make_pair(Results->FactCompressor[Entry.first],
36-
Results->ValCompressor[Entry.second]);
37-
return *Cache;
36+
return {Results->FactCompressor[Entry.first],
37+
Results->ValCompressor[Entry.second]};
3838
}
3939
};
4040

@@ -44,6 +44,10 @@ class IdBasedSolverResultsBase {
4444
using const_iterator = iterator;
4545
using difference_type = ptrdiff_t;
4646

47+
using key_type = d_t;
48+
using mapped_type = l_t;
49+
using value_type = std::pair<d_t, l_t>;
50+
4751
explicit RowView(
4852
const detail::IterativeIDESolverResults<n_t, d_t, l_t> *Results,
4953
const row_map_t *Row) noexcept

include/phasar/Domain/LatticeDomain.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "phasar/Utils/ByRef.h"
1414
#include "phasar/Utils/DebugOutput.h"
1515
#include "phasar/Utils/JoinLattice.h"
16+
#include "phasar/Utils/Macros.h"
1617
#include "phasar/Utils/TypeTraits.h"
1718

1819
#include "llvm/ADT/Hashing.h"
@@ -22,6 +23,7 @@
2223
#include "llvm/Support/raw_ostream.h"
2324

2425
#include <cstdint>
26+
#include <functional>
2527
#include <ostream>
2628
#include <variant>
2729

@@ -99,6 +101,13 @@ struct LatticeDomain : public std::variant<Top, L, Bottom> {
99101
assert(std::holds_alternative<L>(*this));
100102
return std::get<L>(*this);
101103
}
104+
105+
template <typename TransformFn, typename... ArgsT>
106+
void onValue(TransformFn Transform, ArgsT &&...Args) {
107+
if (auto *Val = getValueOrNull()) {
108+
std::invoke(std::move(Transform), *Val, PSR_FWD(Args)...);
109+
}
110+
}
102111
};
103112

104113
template <typename L>
@@ -213,6 +222,14 @@ template <typename L> struct JoinLatticeTraits<LatticeDomain<L>> {
213222
return LHS;
214223
}
215224

225+
if constexpr (has_adl_join<l_t>) {
226+
if (auto LhsPtr = LHS.getValueOrNull()) {
227+
if (auto RhsPtr = RHS.getValueOrNull()) {
228+
return psr::adl_join(*LhsPtr, *RhsPtr);
229+
}
230+
}
231+
}
232+
216233
return Bottom{};
217234
}
218235
};
@@ -243,7 +260,12 @@ template <typename L> struct hash<psr::LatticeDomain<L>> {
243260
return SIZE_MAX - 1;
244261
}
245262
assert(LD.getValueOrNull() != nullptr);
246-
return std::hash<L>{}(*LD.getValueOrNull());
263+
if constexpr (psr::is_std_hashable_v<L>) {
264+
return std::hash<L>{}(*LD.getValueOrNull());
265+
} else {
266+
using llvm::hash_value;
267+
return hash_value(*LD.getValueOrNull());
268+
}
247269
}
248270
};
249271
} // namespace std

0 commit comments

Comments
 (0)