Skip to content

Commit b751241

Browse files
authored
[clang][ssaf] Add UnsafeBufferUsage summary extractor for functions (#182941)
The UnsafeBufferUsage summary extract reuses -Wunsafe-buffer-usage to find all unsafe pointers in functions and translates them to entity-based representation. rdar://169191570
1 parent 4fcdf52 commit b751241

5 files changed

Lines changed: 701 additions & 81 deletions

File tree

clang/include/clang/Analysis/Scalable/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h

Lines changed: 17 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
#include "clang/Analysis/Scalable/Model/EntityId.h"
1313
#include "clang/Analysis/Scalable/Model/SummaryName.h"
1414
#include "clang/Analysis/Scalable/TUSummary/EntitySummary.h"
15-
#include "llvm/ADT/iterator_range.h"
1615
#include <set>
1716

1817
namespace clang::ssaf {
@@ -26,23 +25,19 @@ namespace clang::ssaf {
2625
/// *' of 'p'.
2726
///
2827
/// An EntityPointerLevel can be identified by an EntityId and an unsigned
29-
/// integer indicating the pointer level: '(EntityId, PointerLevel)'. An
30-
/// EntityPointerLevel 'P' is valid iff
31-
/// - 'P.EntityId' has a pointer type with at least 'P.PointerLevel' levels
32-
/// (This implies 'P.PointerLevel > 0');
33-
/// - 'P.EntityId' identifies an lvalue object and 'P.PointerLevel == 0'.
34-
/// The latter case represents address-of expressions.
28+
/// integer indicating the pointer level: '(EntityId, PointerLevel)'.
29+
/// An EntityPointerLevel 'P' is valid iff 'P.EntityId' has a pointer type with
30+
/// at least 'P.PointerLevel' levels (This implies 'P.PointerLevel > 0').
3531
///
3632
/// For the same example 'int *p[10];', the EntityPointerLevels below are valid:
37-
/// '(p, 1)' is associated with 'int *[10]' of 'p';
38-
/// '(p, 2)' is associated with 'int *' of 'p';
39-
/// '(p, 0)' represents '&p'.
33+
/// - '(p, 2)' is associated with the 'int *' part of the declared type of 'p';
34+
/// - '(p, 1)' is associated with the 'int *[10]' part of the declared type of
35+
/// 'p'.
4036
class EntityPointerLevel {
4137
EntityId Entity;
4238
unsigned PointerLevel;
4339

44-
friend class UnsafeBufferUsageTUSummaryBuilder;
45-
friend class UnsafeBufferUsageEntitySummary;
40+
friend class UnsafeBufferUsageTUSummaryExtractor;
4641

4742
EntityPointerLevel(EntityId Entity, unsigned PointerLevel)
4843
: Entity(Entity), PointerLevel(PointerLevel) {}
@@ -52,7 +47,8 @@ class EntityPointerLevel {
5247
unsigned getPointerLevel() const { return PointerLevel; }
5348

5449
bool operator==(const EntityPointerLevel &Other) const {
55-
return Entity == Other.Entity && PointerLevel == Other.PointerLevel;
50+
return std::tie(Entity, PointerLevel) ==
51+
std::tie(Other.Entity, Other.PointerLevel);
5652
}
5753

5854
bool operator!=(const EntityPointerLevel &Other) const {
@@ -64,7 +60,8 @@ class EntityPointerLevel {
6460
std::tie(Other.Entity, Other.PointerLevel);
6561
}
6662

67-
// Comparator supporting partial comparison against EntityId:
63+
/// Compares `EntityPointerLevel`s; additionally, partially compares
64+
/// `EntityPointerLevel` with `EntityId`.
6865
struct Comparator {
6966
using is_transparent = void;
7067
bool operator()(const EntityPointerLevel &L,
@@ -88,32 +85,19 @@ using EntityPointerLevelSet =
8885
class UnsafeBufferUsageEntitySummary final : public EntitySummary {
8986
const EntityPointerLevelSet UnsafeBuffers;
9087

91-
friend class UnsafeBufferUsageTUSummaryBuilder;
88+
friend class UnsafeBufferUsageTUSummaryExtractor;
9289

93-
UnsafeBufferUsageEntitySummary(EntityPointerLevelSet &&UnsafeBuffers)
90+
UnsafeBufferUsageEntitySummary(EntityPointerLevelSet UnsafeBuffers)
9491
: EntitySummary(), UnsafeBuffers(std::move(UnsafeBuffers)) {}
9592

9693
public:
97-
using const_iterator = EntityPointerLevelSet::const_iterator;
98-
99-
const_iterator begin() const { return UnsafeBuffers.begin(); }
100-
const_iterator end() const { return UnsafeBuffers.end(); }
101-
102-
const_iterator find(const EntityPointerLevel &V) const {
103-
return UnsafeBuffers.find(V);
104-
}
105-
106-
llvm::iterator_range<const_iterator> getSubsetOf(EntityId Entity) const {
107-
return llvm::make_range(UnsafeBuffers.equal_range(Entity));
108-
}
109-
110-
/// \return the size of the set of EntityLevelPointers, which represents the
111-
/// set of unsafe buffers
112-
size_t getNumUnsafeBuffers() { return UnsafeBuffers.size(); }
113-
11494
SummaryName getSummaryName() const override {
11595
return SummaryName{"UnsafeBufferUsage"};
11696
};
97+
98+
bool operator==(const EntityPointerLevelSet &Other) const {
99+
return UnsafeBuffers == Other;
100+
}
117101
};
118102
} // namespace clang::ssaf
119103

clang/include/clang/Analysis/Scalable/Analyses/UnsafeBufferUsage/UnsafeBufferUsageBuilder.h renamed to clang/include/clang/Analysis/Scalable/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.h

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,40 @@
1-
//===- UnsafeBufferUsageBuilder.h -------------------------------*- C++ -*-===//
1+
//===- UnsafeBufferUsageExtractor.h -----------------------------*- C++ -*-===//
22
//
33
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
44
// See https://llvm.org/LICENSE.txt for license information.
55
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66
//
77
//===----------------------------------------------------------------------===//
8-
#ifndef LLVM_CLANG_ANALYSIS_SCALABLE_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEBUILDER_H
9-
#define LLVM_CLANG_ANALYSIS_SCALABLE_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEBUILDER_H
8+
#ifndef LLVM_CLANG_ANALYSIS_SCALABLE_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEEXTRACTOR_H
9+
#define LLVM_CLANG_ANALYSIS_SCALABLE_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEEXTRACTOR_H
1010

1111
#include "clang/Analysis/Scalable/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
12+
#include "clang/Analysis/Scalable/Model/EntityId.h"
13+
#include "clang/Analysis/Scalable/Model/EntityName.h"
1214
#include "clang/Analysis/Scalable/TUSummary/TUSummaryBuilder.h"
15+
#include "clang/Analysis/Scalable/TUSummary/TUSummaryExtractor.h"
16+
#include "llvm/Support/Error.h"
1317
#include <memory>
1418

1519
namespace clang::ssaf {
16-
class UnsafeBufferUsageTUSummaryBuilder : public TUSummaryBuilder {
20+
class UnsafeBufferUsageTUSummaryExtractor : public TUSummaryExtractor {
1721
public:
22+
UnsafeBufferUsageTUSummaryExtractor(TUSummaryBuilder &Builder)
23+
: TUSummaryExtractor(Builder) {}
24+
1825
static EntityPointerLevel buildEntityPointerLevel(EntityId Entity,
1926
unsigned PointerLevel) {
2027
return {Entity, PointerLevel};
2128
}
2229

23-
static std::unique_ptr<UnsafeBufferUsageEntitySummary>
24-
buildUnsafeBufferUsageEntitySummary(EntityPointerLevelSet &&UnsafeBuffers) {
25-
return std::make_unique<UnsafeBufferUsageEntitySummary>(
26-
UnsafeBufferUsageEntitySummary(std::move(UnsafeBuffers)));
27-
}
30+
EntityId addEntity(EntityName EN) { return SummaryBuilder.addEntity(EN); }
31+
32+
std::unique_ptr<UnsafeBufferUsageEntitySummary>
33+
extractEntitySummary(const Decl *Contributor, ASTContext &Ctx,
34+
llvm::Error &Error);
35+
36+
void HandleTranslationUnit(ASTContext &Ctx) override;
2837
};
2938
} // namespace clang::ssaf
3039

31-
#endif // LLVM_CLANG_ANALYSIS_SCALABLE_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEBUILDER_H
40+
#endif // LLVM_CLANG_ANALYSIS_SCALABLE_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEEXTRACTOR_H

0 commit comments

Comments
 (0)