Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,9 @@ class IFDSTaintAnalysis
const llvm::Function *Callee) const;

void populateWithMayAliases(container_type &Facts,
const llvm::Instruction *Context) const;
const llvm::Instruction *AliasQueryInst) const;
void populateWithMustAliases(container_type &Facts,
const llvm::Instruction *Context) const;
const llvm::Instruction *AliasQueryInst) const;
};
} // namespace psr

Expand Down
154 changes: 154 additions & 0 deletions include/phasar/PhasarLLVM/Pointer/FilteredLLVMAliasSet.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/******************************************************************************
* Copyright (c) 2020 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_PHASARLLVM_POINTER_FILTEREDLLVMALIASSET_H
#define PHASAR_PHASARLLVM_POINTER_FILTEREDLLVMALIASSET_H

#include "phasar/Pointer/AliasAnalysisType.h"
#include "phasar/Pointer/AliasInfoTraits.h"
#include "phasar/Pointer/AliasResult.h"
#include "phasar/Pointer/AliasSetOwner.h"
#include "phasar/Utils/AnalysisProperties.h"
#include "phasar/Utils/MaybeUniquePtr.h"

#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/IR/Function.h"
#include "llvm/Support/ErrorHandling.h"

#include "nlohmann/json_fwd.hpp"

#include <type_traits>
#include <utility>

namespace llvm {
class Value;
class Instruction;
} // namespace llvm

namespace psr {

class LLVMAliasSet;
class FilteredLLVMAliasSet;

template <>
struct AliasInfoTraits<FilteredLLVMAliasSet>
: DefaultAATraits<const llvm::Value *, const llvm::Instruction *> {};

class FilteredLLVMAliasSet {
public:
using alias_traits_t = AliasInfoTraits<FilteredLLVMAliasSet>;
using n_t = alias_traits_t::n_t;
using v_t = alias_traits_t::v_t;
using AliasSetTy = alias_traits_t::AliasSetTy;
using AliasSetPtrTy = alias_traits_t::AliasSetPtrTy;
using AllocationSiteSetPtrTy = alias_traits_t::AllocationSiteSetPtrTy;

FilteredLLVMAliasSet(LLVMAliasSet *AS) noexcept;

FilteredLLVMAliasSet(const FilteredLLVMAliasSet &) = delete;
FilteredLLVMAliasSet &operator=(const FilteredLLVMAliasSet &) = delete;
FilteredLLVMAliasSet &operator=(FilteredLLVMAliasSet &&) noexcept = delete;

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

FilteredLLVMAliasSet(FilteredLLVMAliasSet &&) noexcept = default;

~FilteredLLVMAliasSet();

template <typename... ArgsT,
typename = std::enable_if_t<
std::is_constructible_v<LLVMAliasSet, ArgsT...>>>
explicit FilteredLLVMAliasSet(ArgsT &&...Args)
: FilteredLLVMAliasSet(std::forward<ArgsT>(Args)...) {}

// --- API Functions:

[[nodiscard]] inline bool isInterProcedural() const noexcept {
return false;
};

[[nodiscard]] AliasAnalysisType getAliasAnalysisType() const noexcept;

[[nodiscard]] AliasResult alias(const llvm::Value *V1, const llvm::Value *V2,
const llvm::Instruction *I);
[[nodiscard]] AliasResult alias(const llvm::Value *V1, const llvm::Value *V2,
const llvm::Function *Fun);

[[nodiscard]] AliasSetPtrTy getAliasSet(const llvm::Value *V,
const llvm::Instruction *I);
[[nodiscard]] AliasSetPtrTy getAliasSet(const llvm::Value *V,
const llvm::Function *Fun);

[[nodiscard]] AllocationSiteSetPtrTy
getReachableAllocationSites(const llvm::Value *V, bool IntraProcOnly = false,
const llvm::Instruction *I = nullptr);

// Checks if PotentialValue is in the reachable allocation sites of V.
[[nodiscard]] bool isInReachableAllocationSites(
const llvm::Value *V, const llvm::Value *PotentialValue,
bool IntraProcOnly = false, const llvm::Instruction *I = nullptr);

void mergeWith(const FilteredLLVMAliasSet & /*OtherPTI*/) {
llvm::report_fatal_error("Not Supported");
}

void introduceAlias(const llvm::Value * /*V1*/, const llvm::Value * /*V2*/,
const llvm::Instruction * /*I*/ = nullptr,
AliasResult /*Kind*/ = AliasResult::MustAlias) {
llvm::report_fatal_error("Not Supported");
}

void print(llvm::raw_ostream &OS = llvm::outs()) const;

[[nodiscard]] nlohmann::json getAsJson() const;

void printAsJson(llvm::raw_ostream &OS = llvm::outs()) const;

[[nodiscard]] AnalysisProperties getAnalysisProperties() const noexcept {
return AnalysisProperties::None;
}

private:
struct ReachableAllocationSitesKey {
llvm::PointerIntPair<const llvm::Function *, 1, bool> FunAndIntraProcOnly;
v_t Value{};
};

struct ReachableAllocationSitesKeyDMI {
inline static ReachableAllocationSitesKey getEmptyKey() noexcept {
return {{}, llvm::DenseMapInfo<v_t>::getEmptyKey()};
}
inline static ReachableAllocationSitesKey getTombstoneKey() noexcept {
return {{}, llvm::DenseMapInfo<v_t>::getTombstoneKey()};
}
inline static auto getHashValue(ReachableAllocationSitesKey Key) noexcept {
return llvm::hash_combine(Key.FunAndIntraProcOnly.getOpaqueValue(),
Key.Value);
}
inline static bool isEqual(ReachableAllocationSitesKey Key1,
ReachableAllocationSitesKey Key2) noexcept {
return Key1.FunAndIntraProcOnly == Key2.FunAndIntraProcOnly &&
Key1.Value == Key2.Value;
}
};

FilteredLLVMAliasSet(MaybeUniquePtr<LLVMAliasSet, true> AS) noexcept;

MaybeUniquePtr<LLVMAliasSet, /*RequireAlignment=*/true> AS;
AliasSetOwner<AliasSetTy> Owner;
llvm::DenseMap<std::pair<const llvm::Function *, v_t>, AliasSetPtrTy>
AliasSetMap;
llvm::DenseMap<ReachableAllocationSitesKey, std::unique_ptr<AliasSetTy>,
ReachableAllocationSitesKeyDMI>
ReachableAllocationSitesMap;
};
} // namespace psr

#endif // PHASAR_PHASARLLVM_POINTER_FILTEREDLLVMALIASSET_H
2 changes: 2 additions & 0 deletions include/phasar/PhasarLLVM/Pointer/LLVMAliasSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ struct AliasInfoTraits<LLVMAliasSet>

class LLVMAliasSet : public AnalysisPropertiesMixin<LLVMAliasSet>,
public AliasInfoBaseUtils {
// For int*IsReachableAllocationSiteTy:
friend class FilteredLLVMAliasSet;

public:
using traits_t = AliasInfoTraits<LLVMAliasSet>;
Expand Down
5 changes: 2 additions & 3 deletions include/phasar/Pointer/AliasInfoTraits.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,10 @@
#define PHASAR_POINTER_ALIASINFOTRAITS_H

#include "phasar/Utils/BoxedPointer.h"
#include "phasar/Utils/MaybeUniquePtr.h"

#include "llvm/ADT/DenseSet.h"

#include <memory>

namespace psr {

template <typename T> struct AliasInfoTraits {
Expand All @@ -31,7 +30,7 @@ template <typename V, typename N> struct DefaultAATraits {
using v_t = V;
using AliasSetTy = llvm::DenseSet<v_t>;
using AliasSetPtrTy = BoxedConstPtr<AliasSetTy>;
using AllocationSiteSetPtrTy = std::unique_ptr<AliasSetTy>;
using AllocationSiteSetPtrTy = MaybeUniquePtr<const AliasSetTy>;
};
} // namespace psr

Expand Down
8 changes: 5 additions & 3 deletions include/phasar/Utils/MaybeUniquePtr.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ template <typename T> class MaybeUniquePtrBase<T, true> {
/// \tparam RequireAlignment If true, the datastructure only works if
/// alignof(T) > 1 holds. Enables incomplete T types
template <typename T, bool RequireAlignment = false>
class MaybeUniquePtr : detail::MaybeUniquePtrBase<T, RequireAlignment> {
class [[clang::trivial_abi]] MaybeUniquePtr
: detail::MaybeUniquePtrBase<T, RequireAlignment> {
using detail::MaybeUniquePtrBase<T, RequireAlignment>::Data;

public:
Expand All @@ -79,8 +80,9 @@ class MaybeUniquePtr : detail::MaybeUniquePtrBase<T, RequireAlignment> {
: MaybeUniquePtr(Owner.release(), true) {}

constexpr MaybeUniquePtr(MaybeUniquePtr &&Other) noexcept
: detail::MaybeUniquePtrBase<T, RequireAlignment>(
std::exchange(Other.Data, {})) {}
: detail::MaybeUniquePtrBase<T, RequireAlignment>(std::move(Other)) {
Other.Data = {};
}

constexpr void swap(MaybeUniquePtr &Other) noexcept {
std::swap(Data, Other.Data);
Expand Down
21 changes: 11 additions & 10 deletions lib/PhasarLLVM/DataFlow/IfdsIde/Problems/IFDSTaintAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,16 +116,17 @@ bool IFDSTaintAnalysis::isSanitizerCall(const llvm::CallBase * /*CB*/,
[this](const auto &Arg) { return Config->isSanitizer(&Arg); });
}

static bool canSkipAtContext(const llvm::Value *Val,
const llvm::Instruction *Context) noexcept {
static bool
canSkipAtQueryInst(const llvm::Value *Val,
const llvm::Instruction *AliasQueryInst) noexcept {
if (const auto *Inst = llvm::dyn_cast<llvm::Instruction>(Val)) {
/// Mapping instructions between functions is done via the call-FF and
/// ret-FF
if (Inst->getFunction() != Context->getFunction()) {
if (Inst->getFunction() != AliasQueryInst->getFunction()) {
return true;
}
if (Inst->getParent() == Context->getParent() &&
Context->comesBefore(Inst)) {
if (Inst->getParent() == AliasQueryInst->getParent() &&
AliasQueryInst->comesBefore(Inst)) {
// We will see that inst later
return true;
}
Expand All @@ -134,7 +135,7 @@ static bool canSkipAtContext(const llvm::Value *Val,

if (const auto *Arg = llvm::dyn_cast<llvm::Argument>(Val)) {
// An argument is only valid in the function it belongs to
if (Arg->getParent() != Context->getFunction()) {
if (Arg->getParent() != AliasQueryInst->getFunction()) {
return true;
}
}
Expand All @@ -151,12 +152,12 @@ static bool isCompiletimeConstantData(const llvm::Value *Val) noexcept {
}

void IFDSTaintAnalysis::populateWithMayAliases(
container_type &Facts, const llvm::Instruction *Context) const {
container_type &Facts, const llvm::Instruction *AliasQueryInst) const {
container_type Tmp = Facts;
for (const auto *Fact : Facts) {
auto Aliases = PT.getAliasSet(Fact);
auto Aliases = PT.getAliasSet(Fact, AliasQueryInst);
for (const auto *Alias : *Aliases) {
if (canSkipAtContext(Alias, Context)) {
if (canSkipAtQueryInst(Alias, AliasQueryInst)) {
continue;
}

Expand All @@ -178,7 +179,7 @@ void IFDSTaintAnalysis::populateWithMayAliases(
}

void IFDSTaintAnalysis::populateWithMustAliases(
container_type &Facts, const llvm::Instruction *Context) const {
container_type &Facts, const llvm::Instruction *AliasQueryInst) const {
/// TODO: Find must-aliases; Currently the AliasSet only contains
/// may-aliases
}
Expand Down
Loading
Loading