23#include "llvm/Support/Error.h"
24#include "llvm/Support/JSON.h"
32json::Object serializeUnsafeBufferUsageAnalysisResult(
43deserializeUnsafeBufferUsageAnalysisResult(
45 const json::Array *Content =
55 return UnsafeBuffers.takeError();
57 auto Ret = std::make_unique<UnsafeBufferUsageAnalysisResult>();
59 Ret->UnsafeBuffers = std::move(*UnsafeBuffers);
63JSONFormat::AnalysisResultRegistry::Add<UnsafeBufferUsageAnalysisResult>
64 RegisterUnsafeBufferUsageResultForJSON(
65 serializeUnsafeBufferUsageAnalysisResult,
66 deserializeUnsafeBufferUsageAnalysisResult);
68class UnsafeBufferUsageAnalysis final
70 UnsafeBufferUsageEntitySummary> {
72 llvm::Error add(EntityId Id,
73 const UnsafeBufferUsageEntitySummary &Summary)
override {
74 auto UnsafeBuffersOfEntity = getUnsafeBuffers(Summary);
76 getResult().UnsafeBuffers[Id] = EntityPointerLevelSet(
77 UnsafeBuffersOfEntity.begin(), UnsafeBuffersOfEntity.end());
78 return llvm::Error::success();
83 RegisterUnsafeBufferUsageAnalysis(
84 "Whole-program unsafe buffer usage analysis");
90json::Object serializeUnsafeBufferReachableAnalysisResult(
101deserializeUnsafeBufferReachableAnalysisResult(
103 const json::Array *Content =
108 Obj,
"an object with a key %s",
114 return Reachables.takeError();
116 auto Ret = std::make_unique<UnsafeBufferReachableAnalysisResult>();
118 Ret->Reachables = std::move(*Reachables);
122JSONFormat::AnalysisResultRegistry::Add<UnsafeBufferReachableAnalysisResult>
123 RegisterUnsafeBufferReachableResultForJSON(
124 serializeUnsafeBufferReachableAnalysisResult,
125 deserializeUnsafeBufferReachableAnalysisResult);
130class UnsafeBufferReachableAnalysis
132 PointerFlowAnalysisResult,
133 UnsafeBufferUsageAnalysisResult> {
160 struct BoundsPropagationGraph {
162 const std::map<EntityPointerLevel, EntityPointerLevelSet> &PointerFlows;
165 BoundsPropagationGraph(
const EdgeSet &PointerFlows)
166 : PointerFlows(PointerFlows) {}
170 EntityPointerLevelSet getDestNodes(
const EntityPointerLevel &Src)
const {
171 unsigned SrcPtrLv = Src.getPointerLevel();
172 EntityPointerLevelSet
Result;
174 for (
unsigned P = 1; P <= SrcPtrLv; ++P) {
175 auto I = PointerFlows.find(buildEntityPointerLevel(Src.getEntity(), P));
177 if (I != PointerFlows.end()) {
178 unsigned Delta = SrcPtrLv - P;
179 for (
const auto &EPL : I->second)
180 Result.insert(buildEntityPointerLevel(
181 EPL.getEntity(), EPL.getPointerLevel() + Delta));
188 std::map<EntityId, BoundsPropagationGraph> BPG;
192 using EPLPtr =
const EntityPointerLevel *;
197 void updateReachablesWithOutgoings(EPLPtr EPL,
198 std::vector<EPLPtr> &WorkList) {
199 for (
auto &[Id, SubGraph] : BPG) {
200 auto R = SubGraph.getDestNodes(*EPL);
202 for (
const auto &Dst : R) {
203 auto [It, Inserted] = getResult().Reachables[Id].insert(Dst);
205 WorkList.push_back(&*It);
212 initialize(
const PointerFlowAnalysisResult &PtrFlowGraph,
213 const UnsafeBufferUsageAnalysisResult &Starter)
override {
214 for (
auto &[Id, SubGraph] : PtrFlowGraph.
Edges)
215 BPG.try_emplace(Id, BoundsPropagationGraph(SubGraph));
216 assert(getResult().Reachables.empty());
217 getResult().Reachables.insert(Starter.
begin(), Starter.
end());
218 return llvm::Error::success();
221 llvm::Expected<bool>
step()
override {
222 auto &Reachables = getResult().Reachables;
224 std::vector<EPLPtr> Worklist;
226 for (
auto &[Id, EPLs] : Reachables)
227 for (
auto &EPL : EPLs)
228 Worklist.push_back(&EPL);
230 while (!Worklist.empty()) {
231 EPLPtr Node = Worklist.back();
234 updateReachablesWithOutgoings(Node, Worklist);
242 RegisterUnsafeBufferReachableAnalysis(
243 "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, CodePtr &PC)
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.
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
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,...
void initialize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)
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.
Registers AnalysisT with the unified registry.
std::map< EntityId, EdgeSet > Edges