29#include "llvm/ADT/STLExtras.h"
30#include "llvm/ADT/iterator_range.h"
31#include "llvm/Support/Error.h"
32#include "llvm/Support/JSON.h"
40json::Object serializeUnsafeBufferUsageAnalysisResult(
51deserializeUnsafeBufferUsageAnalysisResult(
53 const json::Array *Content =
63 return UnsafeBuffers.takeError();
65 auto Ret = std::make_unique<UnsafeBufferUsageAnalysisResult>();
67 Ret->UnsafeBuffers = std::move(*UnsafeBuffers);
68 return std::move(Ret);
71JSONFormat::AnalysisResultRegistry::Add<UnsafeBufferUsageAnalysisResult>
72 RegisterUnsafeBufferUsageResultForJSON(
73 serializeUnsafeBufferUsageAnalysisResult,
74 deserializeUnsafeBufferUsageAnalysisResult);
76class UnsafeBufferUsageAnalysis final
78 UnsafeBufferUsageEntitySummary> {
80 llvm::Error add(EntityId Id,
81 const UnsafeBufferUsageEntitySummary &Summary)
override {
82 auto UnsafeBuffersOfEntity = getUnsafeBuffers(Summary);
84 getResult().UnsafeBuffers[Id] = EntityPointerLevelSet(
85 UnsafeBuffersOfEntity.begin(), UnsafeBuffersOfEntity.end());
86 return llvm::Error::success();
90AnalysisRegistry::Add<UnsafeBufferUsageAnalysis>
91 RegisterUnsafeBufferUsageAnalysis(
92 "Whole-program unsafe buffer usage analysis");
98json::Object serializeUnsafeBufferReachableAnalysisResult(
109deserializeUnsafeBufferReachableAnalysisResult(
111 const json::Array *Content =
116 Obj,
"an object with a key %s",
122 return Reachables.takeError();
124 auto Ret = std::make_unique<UnsafeBufferReachableAnalysisResult>();
126 Ret->Reachables = std::move(*Reachables);
127 return std::move(Ret);
130JSONFormat::AnalysisResultRegistry::Add<UnsafeBufferReachableAnalysisResult>
131 RegisterUnsafeBufferReachableResultForJSON(
132 serializeUnsafeBufferReachableAnalysisResult,
133 deserializeUnsafeBufferReachableAnalysisResult);
145class UnsafeBufferReachableAnalysis
147 PointerFlowAnalysisResult,
148 TypeConstrainedPointersAnalysisResult,
149 UnsafeBufferUsageAnalysisResult> {
151 struct BoundsPropagationGraph {
156 EntityPointerLevelSet getDestNodes(
const EntityPointerLevel &Src)
const {
157 auto I = PointerFlows.find(Src);
158 if (I == PointerFlows.end())
164 std::map<EntityId, BoundsPropagationGraph> BPG;
168 using EPLPtr =
const EntityPointerLevel *;
173 void updateReachablesWithOutgoings(EPLPtr EPL,
174 std::vector<EPLPtr> &WorkList) {
175 for (
auto &[Id, SubGraph] : BPG) {
176 auto R = SubGraph.getDestNodes(*EPL);
178 for (
const auto &Dst : R) {
179 auto [It, Inserted] = getResult().Reachables.insert(Dst);
181 WorkList.push_back(&*It);
188 void computeReachableUnsafePointers() {
189 auto &Reachables = getResult().Reachables;
191 std::vector<EPLPtr> Worklist;
193 for (
auto &EPL : Reachables)
194 Worklist.push_back(&EPL);
196 while (!Worklist.empty()) {
197 EPLPtr Node = Worklist.back();
200 updateReachablesWithOutgoings(Node, Worklist);
206 initialize(
const PointerFlowAnalysisResult &PtrFlowGraph,
207 const TypeConstrainedPointersAnalysisResult &TypeConstraints,
208 const UnsafeBufferUsageAnalysisResult &UnsafePtrs)
override {
209 auto HasNoTypeConstraint =
210 [&TypeConstraints](
const EntityPointerLevel &EPL) {
211 return !TypeConstraints.
contains(EPL.getEntity());
215 for (
auto &[Id, SubGraph] : PtrFlowGraph.
Edges) {
218 for (
const auto &[Src, Dsts] : SubGraph) {
219 if (TypeConstraints.
contains(Src.getEntity()))
222 auto FilteredDstRange =
223 llvm::make_filter_range(Dsts, HasNoTypeConstraint);
225 if (!FilteredDstRange.empty())
226 FilteredSubGraph[Src].insert(FilteredDstRange.begin(),
227 FilteredDstRange.end());
229 if (!FilteredSubGraph.empty())
231 BoundsPropagationGraph{std::move(FilteredSubGraph)});
235 for (
auto &[Contributor, EPLs] : UnsafePtrs) {
236 auto FilteredRange = llvm::make_filter_range(EPLs, HasNoTypeConstraint);
238 getResult().Reachables.insert(FilteredRange.begin(), FilteredRange.end());
240 return llvm::Error::success();
243 llvm::Expected<bool>
step()
override {
247 computeReachableUnsafePointers();
253AnalysisRegistry::Add<UnsafeBufferReachableAnalysis>
254 RegisterUnsafeBufferReachableAnalysis(
255 "Reachable pointers from unsafe buffer usage in pointer flow graph");
Result
Implement __builtin_bit_cast and related operations.
Typed intermediate that concrete derived analyses inherit from.
Typed intermediate that concrete summary analyses inherit from.
PRESERVE_NONE bool Ret(InterpState &S)
Expected< std::map< EntityId, EntityPointerLevelSet > > entityPointerLevelMapFromJSON(const llvm::json::Array &Content, JSONFormat::EntityIdFromJSONFn IdFromJSON)
Deserialize a flat array of alternating [EntityId, EntityPointerLevelSet, ...] pairs into a map.
llvm::json::Array entityPointerLevelSetToJSON(llvm::iterator_range< EntityPointerLevelSet::const_iterator > EPLs, JSONFormat::EntityIdToJSONFn EntityId2JSON)
std::map< EntityPointerLevel, EntityPointerLevelSet > EdgeSet
Maps each LHS pointer (source / assignee) to the set of RHS pointers (destinations / assigned values)...
volatile int UnsafeBufferUsageAnalysisAnchorSource
llvm::Error makeSawButExpectedError(const JSONTy &Saw, llvm::StringRef Expected, const Ts &...ExpectedArgs)
constexpr llvm::StringLiteral UnsafeBufferUsageAnalysisResultName
Expected< EntityPointerLevelSet > entityPointerLevelSetFromJSON(const llvm::json::Array &EPLsData, JSONFormat::EntityIdFromJSONFn EntityIdFromJSON)
constexpr llvm::StringLiteral UnsafeBufferReachableAnalysisResultName
llvm::json::Array entityPointerLevelMapToJSON(const std::map< EntityId, EntityPointerLevelSet > &Map, JSONFormat::EntityIdToJSONFn IdToJSON)
Serialize a map<EntityId, EntityPointerLevelSet> as a flat array of alternating [EntityId,...
Diagnostic wrappers for TextAPI types for error reporting.
float __ovld __cnfn step(float, float)
Returns 0.0 if x < edge, otherwise it returns 1.0.
std::map< EntityId, EdgeSet > Edges
bool contains(const EntityId &Id) const