[llvm-branch-commits] [clang] [ssaf][UnsafeBufferUsage] Add JSON serialization for UnsafeBufferUsage (PR #187156)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Mar 17 16:47:59 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Ziqing Luo (ziqingluo-90)
<details>
<summary>Changes</summary>
Implemented and registered a JSONFormat::FormatInfo for UnsafeBufferUsage analysis
rdar://171920065
---
Patch is 59.79 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/187156.diff
17 Files Affected:
- (modified) clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h (+8-1)
- (renamed) clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h (+40-32)
- (added) clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.h (+40)
- (removed) clang/include/clang/ScalableStaticAnalysisFramework/Core/Analyses/UnsafeBufferUsage/UnsafeBufferUsageBuilder.h (-32)
- (modified) clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h (+4)
- (modified) clang/lib/Analysis/UnsafeBufferUsage.cpp (+43-16)
- (added) clang/lib/ScalableStaticAnalysisFramework/Analyses/CMakeLists.txt (+16)
- (added) clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp (+89)
- (added) clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp (+369)
- (modified) clang/lib/ScalableStaticAnalysisFramework/CMakeLists.txt (+2)
- (modified) clang/lib/ScalableStaticAnalysisFramework/Frontend/CMakeLists.txt (+1)
- (added) clang/test/Analysis/Scalable/UnsafeBufferUsage/tu-summary-serialization.test (+4)
- (added) clang/test/Analysis/Scalable/UnsafeBufferUsage/tu-summary.json (+108)
- (modified) clang/test/Analysis/Scalable/ssaf-format/list.test (+2-1)
- (modified) clang/tools/clang-ssaf-format/CMakeLists.txt (+2-1)
- (modified) clang/tools/clang-ssaf-linker/CMakeLists.txt (+1)
- (modified) clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp (+638-39)
``````````diff
diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h
index 876682ad779d4..e0d583c735e61 100644
--- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h
+++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h
@@ -201,7 +201,14 @@ bool anyConflict(const llvm::SmallVectorImpl<FixItHint> &FixIts,
const SourceManager &SM);
} // namespace internal
-std::set<const Expr *> findUnsafePointers(const FunctionDecl *FD);
+/// Find unsafe pointers in body/initializer of `D`, if `D` is one of the
+/// followings:
+/// VarDecl
+/// FieldDecl
+/// FunctionDecl
+/// BlockDecl
+/// ObjCMethodDecl
+std::set<const Expr *> findUnsafePointers(const Decl *D);
} // end namespace clang
#endif /* LLVM_CLANG_ANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_H */
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
similarity index 56%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
index 5b58ed0684333..2b36c47fe67a5 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
@@ -6,13 +6,13 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
-#include "llvm/ADT/iterator_range.h"
#include <set>
namespace clang::ssaf {
@@ -26,22 +26,19 @@ namespace clang::ssaf {
/// *' of 'p'.
///
/// An EntityPointerLevel can be identified by an EntityId and an unsigned
-/// integer indicating the pointer level: '(EntityId, PointerLevel)'. An
-/// EntityPointerLevel 'P' is valid iff
-/// - 'P.EntityId' has a pointer type with at least 'P.PointerLevel' levels
-/// (This implies 'P.PointerLevel > 0');
-/// - 'P.EntityId' identifies an lvalue object and 'P.PointerLevel == 0'.
-/// The latter case represents address-of expressions.
+/// integer indicating the pointer level: '(EntityId, PointerLevel)'.
+/// An EntityPointerLevel 'P' is valid iff 'P.EntityId' has a pointer type with
+/// at least 'P.PointerLevel' levels (This implies 'P.PointerLevel > 0').
///
/// For the same example 'int *p[10];', the EntityPointerLevels below are valid:
-/// '(p, 1)' is associated with 'int *[10]' of 'p';
-/// '(p, 2)' is associated with 'int *' of 'p';
-/// '(p, 0)' represents '&p'.
+/// - '(p, 2)' is associated with the 'int *' part of the declared type of 'p';
+/// - '(p, 1)' is associated with the 'int *[10]' part of the declared type of
+/// 'p'.
class EntityPointerLevel {
EntityId Entity;
unsigned PointerLevel;
- friend class UnsafeBufferUsageTUSummaryBuilder;
+ friend class UnsafeBufferUsageTUSummaryExtractor;
friend class UnsafeBufferUsageEntitySummary;
EntityPointerLevel(EntityId Entity, unsigned PointerLevel)
@@ -52,7 +49,8 @@ class EntityPointerLevel {
unsigned getPointerLevel() const { return PointerLevel; }
bool operator==(const EntityPointerLevel &Other) const {
- return Entity == Other.Entity && PointerLevel == Other.PointerLevel;
+ return std::tie(Entity, PointerLevel) ==
+ std::tie(Other.Entity, Other.PointerLevel);
}
bool operator!=(const EntityPointerLevel &Other) const {
@@ -64,7 +62,8 @@ class EntityPointerLevel {
std::tie(Other.Entity, Other.PointerLevel);
}
- // Comparator supporting partial comparison against EntityId:
+ /// Compares `EntityPointerLevel`s; additionally, partially compares
+ /// `EntityPointerLevel` with `EntityId`.
struct Comparator {
using is_transparent = void;
bool operator()(const EntityPointerLevel &L,
@@ -88,33 +87,42 @@ using EntityPointerLevelSet =
class UnsafeBufferUsageEntitySummary final : public EntitySummary {
const EntityPointerLevelSet UnsafeBuffers;
- friend class UnsafeBufferUsageTUSummaryBuilder;
+ friend class UnsafeBufferUsageTUSummaryExtractor;
- UnsafeBufferUsageEntitySummary(EntityPointerLevelSet &&UnsafeBuffers)
+ UnsafeBufferUsageEntitySummary(EntityPointerLevelSet UnsafeBuffers)
: EntitySummary(), UnsafeBuffers(std::move(UnsafeBuffers)) {}
public:
- using const_iterator = EntityPointerLevelSet::const_iterator;
-
- const_iterator begin() const { return UnsafeBuffers.begin(); }
- const_iterator end() const { return UnsafeBuffers.end(); }
+ SummaryName getSummaryName() const override { return summaryName(); };
- const_iterator find(const EntityPointerLevel &V) const {
- return UnsafeBuffers.find(V);
+ bool operator==(const EntityPointerLevelSet &Other) const {
+ return UnsafeBuffers == Other;
}
- llvm::iterator_range<const_iterator> getSubsetOf(EntityId Entity) const {
- return llvm::make_range(UnsafeBuffers.equal_range(Entity));
+ bool operator==(const UnsafeBufferUsageEntitySummary &Other) const {
+ return UnsafeBuffers == Other.UnsafeBuffers;
}
- /// \return the size of the set of EntityLevelPointers, which represents the
- /// set of unsafe buffers
- size_t getNumUnsafeBuffers() { return UnsafeBuffers.size(); }
+ bool empty() const { return UnsafeBuffers.empty(); }
- SummaryName getSummaryName() const override {
- return SummaryName{"UnsafeBufferUsage"};
- };
+ static llvm::json::Object
+ jsonSerializeFn(const EntitySummary &ES,
+ JSONFormat::EntityIdToJSONFn EntityId2JSON);
+
+ static llvm::Expected<std::unique_ptr<EntitySummary>>
+ jsonDeserializeFn(const llvm::json::Object &Data, EntityIdTable &,
+ JSONFormat::EntityIdFromJSONFn EntityIdFromJSON);
+
+ static SummaryName summaryName() { return SummaryName{"UnsafeBufferUsage"}; }
+};
+
+struct UnsafeBufferUsageJSONFormatInfo : JSONFormat::FormatInfo {
+ UnsafeBufferUsageJSONFormatInfo()
+ : JSONFormat::FormatInfo(
+ UnsafeBufferUsageEntitySummary::summaryName(),
+ UnsafeBufferUsageEntitySummary::jsonSerializeFn,
+ UnsafeBufferUsageEntitySummary::jsonDeserializeFn) {}
};
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.h b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.h
new file mode 100644
index 0000000000000..765b2c37562ce
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.h
@@ -0,0 +1,40 @@
+//===- UnsafeBufferUsageExtractor.h -----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEBUILDER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEBUILDER_H
+
+#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
+#include "llvm/Support/Error.h"
+#include <memory>
+
+namespace clang::ssaf {
+class UnsafeBufferUsageTUSummaryExtractor : public TUSummaryExtractor {
+public:
+ UnsafeBufferUsageTUSummaryExtractor(TUSummaryBuilder &Builder)
+ : TUSummaryExtractor(Builder) {}
+
+ static EntityPointerLevel buildEntityPointerLevel(EntityId Entity,
+ unsigned PointerLevel) {
+ return {Entity, PointerLevel};
+ }
+
+ EntityId addEntity(EntityName EN) { return SummaryBuilder.addEntity(EN); }
+
+ std::unique_ptr<UnsafeBufferUsageEntitySummary>
+ extractEntitySummary(const Decl *Contributor, ASTContext &Ctx,
+ llvm::Error &Error);
+
+ void HandleTranslationUnit(ASTContext &Ctx) override;
+};
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEBUILDER_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Analyses/UnsafeBufferUsage/UnsafeBufferUsageBuilder.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Analyses/UnsafeBufferUsage/UnsafeBufferUsageBuilder.h
deleted file mode 100644
index db6c097510a57..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Analyses/UnsafeBufferUsage/UnsafeBufferUsageBuilder.h
+++ /dev/null
@@ -1,32 +0,0 @@
-//===- UnsafeBufferUsageBuilder.h -------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEBUILDER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEBUILDER_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
-#include <memory>
-
-namespace clang::ssaf {
-class UnsafeBufferUsageTUSummaryBuilder : public TUSummaryBuilder {
-public:
- static EntityPointerLevel buildEntityPointerLevel(EntityId Entity,
- unsigned PointerLevel) {
- return {Entity, PointerLevel};
- }
-
- static std::unique_ptr<UnsafeBufferUsageEntitySummary>
- buildUnsafeBufferUsageEntitySummary(EntityPointerLevelSet &&UnsafeBuffers) {
- return std::make_unique<UnsafeBufferUsageEntitySummary>(
- UnsafeBufferUsageEntitySummary(std::move(UnsafeBuffers)));
- }
-};
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEBUILDER_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h b/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
index 5f201487ca1fe..e0a394da1a921 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
@@ -25,4 +25,8 @@ extern volatile int SSAFJSONFormatAnchorSource;
[[maybe_unused]] static int SSAFJSONFormatAnchorDestination =
SSAFJSONFormatAnchorSource;
+extern volatile int UnsafeBufferUsageSSAFJSONFormatAnchorSource;
+[[maybe_unused]] static int UnsafeBufferUsageSSAFJSONFormatAnchorDestination =
+ UnsafeBufferUsageSSAFJSONFormatAnchorSource;
+
#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SSAFBUILTINFORCELINKER_H
diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index 133e39b8fac2b..5a9241acbee36 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -28,6 +28,7 @@
#include "clang/Lex/Preprocessor.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APSInt.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
@@ -36,6 +37,7 @@
#include <queue>
#include <set>
#include <sstream>
+#include <vector>
using namespace clang;
@@ -2942,7 +2944,37 @@ template <typename NodeTy> struct CompareNode {
}
};
-std::set<const Expr *> clang::findUnsafePointers(const FunctionDecl *FD) {
+// Populate `Stmts` with the body/initializer Stmt of `D`, if `D` is one of the
+// followings:
+// VarDecl
+// FieldDecl
+// FunctionDecl
+// BlockDecl
+// ObjCMethodDecl
+static void populateStmtsForFindingGadgets(SmallVector<const Stmt *> &Stmts,
+ const Decl *D) {
+ auto AddStmt = [&Stmts](const Stmt *S) {
+ if (S)
+ Stmts.push_back(S);
+ };
+ if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
+ AddStmt(FD->getBody());
+ for (const auto *PD : FD->parameters())
+ AddStmt(PD->getDefaultArg());
+ if (const auto *CtorD = dyn_cast<CXXConstructorDecl>(FD))
+ llvm::append_range(
+ Stmts, llvm::map_range(CtorD->inits(),
+ std::mem_fn(&CXXCtorInitializer::getInit)));
+ } else if (isa<BlockDecl>(D) || isa<ObjCMethodDecl>(D)) {
+ AddStmt(D->getBody());
+ } else if (const auto *VD = dyn_cast<VarDecl>(D)) {
+ AddStmt(VD->getInit()); // FIXME: default arg for ParmVarDecl?
+ } else if (const auto *FD = dyn_cast<FieldDecl>(D)) {
+ AddStmt(FD->getInClassInitializer());
+ }
+}
+
+std::set<const Expr *> clang::findUnsafePointers(const Decl *D) {
class MockReporter : public UnsafeBufferUsageHandler {
public:
MockReporter() {}
@@ -2981,9 +3013,13 @@ std::set<const Expr *> clang::findUnsafePointers(const FunctionDecl *FD) {
WarningGadgetList WarningGadgets;
DeclUseTracker Tracker;
MockReporter IgnoreHandler;
+ ASTContext &Ctx = D->getASTContext();
+ SmallVector<const Stmt *> Stmts;
- findGadgets(FD->getBody(), FD->getASTContext(), IgnoreHandler, false,
- FixableGadgets, WarningGadgets, Tracker);
+ populateStmtsForFindingGadgets(Stmts, D);
+ for (auto *Stmt : Stmts)
+ findGadgets(Stmt, Ctx, IgnoreHandler, false, FixableGadgets, WarningGadgets,
+ Tracker);
std::set<const Expr *> Result;
for (auto &G : WarningGadgets) {
@@ -4673,9 +4709,6 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
#endif
assert(D);
-
- SmallVector<Stmt *> Stmts;
-
if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
// Consteval functions are free of UB by the spec, so we don't need to
// visit them or produce diagnostics.
@@ -4697,24 +4730,18 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
break;
}
}
+ }
- Stmts.push_back(FD->getBody());
+ SmallVector<const Stmt *> Stmts;
- if (const auto *ID = dyn_cast<CXXConstructorDecl>(D)) {
- for (const CXXCtorInitializer *CI : ID->inits()) {
- Stmts.push_back(CI->getInit());
- }
- }
- } else if (isa<BlockDecl>(D) || isa<ObjCMethodDecl>(D)) {
- Stmts.push_back(D->getBody());
- }
+ populateStmtsForFindingGadgets(Stmts, D);
assert(!Stmts.empty());
FixableGadgetList FixableGadgets;
WarningGadgetList WarningGadgets;
DeclUseTracker Tracker;
- for (Stmt *S : Stmts) {
+ for (const Stmt *S : Stmts) {
findGadgets(S, D->getASTContext(), Handler, EmitSuggestions, FixableGadgets,
WarningGadgets, Tracker);
}
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CMakeLists.txt b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CMakeLists.txt
new file mode 100644
index 0000000000000..c85fa044c1e9f
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CMakeLists.txt
@@ -0,0 +1,16 @@
+set(LLVM_LINK_COMPONENTS
+ Support
+ )
+
+add_clang_library(clangScalableStaticAnalysisFrameworkAnalyses
+ UnsafeBufferUsage/UnsafeBufferUsage.cpp
+ UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
+
+ LINK_LIBS
+ clangAST
+ clangAnalysis
+ clangBasic
+ clangScalableStaticAnalysisFrameworkCore
+
+ DEPENDS
+ )
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp
new file mode 100644
index 0000000000000..44eaa20c74236
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp
@@ -0,0 +1,89 @@
+//===---------- UnsafeBufferUsage.cpp -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
+#include "clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h" // IWYU pragma: keep
+
+namespace {
+constexpr const char *const UnsafeBuffersKey = "UnsafeBuffers";
+} // namespace
+
+namespace clang::ssaf {
+using Object = llvm::json::Object;
+using Array = llvm::json::Array;
+using Value = llvm::json::Value;
+
+llvm::json::Object UnsafeBufferUsageEntitySummary::jsonSerializeFn(
+ const EntitySummary &ES, JSONFormat::EntityIdToJSONFn EntityId2JSON) {
+ // Writes a EntityPointerLevel as
+ // Array {
+ // Object {
+ // "@" : [entity-id]
+ // },
+ // [pointer-level]
+ // }
+ Array UnsafeBuffersData;
+
+ for (const auto &EPL :
+ static_cast<const UnsafeBufferUsageEntitySummary &>(ES).UnsafeBuffers)
+ UnsafeBuffersData.push_back(
+ Value(Array{// EntityId:
+ Value(EntityId2JSON(EPL.getEntity())),
+ // PointerLevel:
+ Value(EPL.getPointerLevel())}));
+
+ Object Data;
+
+ Data[UnsafeBuffersKey] = Value(std::move(UnsafeBuffersData));
+ return Data;
+}
+
+llvm::Expected<std::unique_ptr<EntitySummary>>
+UnsafeBufferUsageEntitySummary::jsonDeserializeFn(
+ const llvm::json::Object &Data, EntityIdTable &,
+ JSONFormat::EntityIdFromJSONFn EntityIdFromJSON) {
+ const Array *UnsafeBuffersData = Data.getArray(UnsafeBuffersKey);
+ constexpr const char *const ErrMsg = "unrecognized UnsafeBufferUsageEntitySummary data";
+
+ if (!UnsafeBuffersData)
+ return llvm::createStringError(ErrMsg);
+
+ EntityPointerLevelSet UnsafeBuffers;
+
+ for (auto &EltData : *UnsafeBuffersData) {
+ const Array *EltDataAsArr = EltData.getAsArray();
+
+ if (!EltDataAsArr || EltDataAsArr->size() != 2)
+ return llvm::createStringError(ErrMsg);
+
+ const Object *IdData = (*EltDataAsArr)[0].getAsObject();
+ std::optional<uint64_t> PtrLvData = (*EltDataAsArr)[1].getAsInteger();
+
+ if (!IdData || !PtrLvData)
+ return llvm::createStringError(ErrMsg);
+
+ llvm::Expected<EntityId> Id = EntityIdFromJSON(*IdData);
+
+ if (!Id)
+ return Id.takeError();
+ UnsafeBuffers.insert(EntityPointerLevel(Id.get(), *PtrLvData));
+ }
+ return std::make_unique<UnsafeBufferUsageEntitySummary>(
+ UnsafeBufferUsageEntitySummary(std::move(UnsafeBuffers)));
+}
+
+static llvm::Registry<JSONFormat::FormatInfo>::Add<
+ UnsafeBufferUsageJSONFormatInfo>
+ RegisterUnsafeBufferUsageJSONFormatInfo(
+ "UnsafeBufferUsage",
+ "JSON Format info for UnsafeBufferUsageEntitySummary");
+
+} // namespace clang::ssaf
+
+// NOLINTNEXTLINE(misc-use-internal-linkage)
+volatile int UnsafeBufferUsageSSAFJSONFormatAnchorSource = 0;
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/Unsaf...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/187156
More information about the llvm-branch-commits
mailing list