Skip to content

Commit 644ac2a

Browse files
[-Wunsafe-buffer-usage] Introduce std::array fixits (llvm#80084)
Array subscript on a const size array is not bounds-checked. The idiomatic replacement is std::array which is bounds-safe in hardened mode of libc++. This commit extends the fixit-producing machine to consider std::array as a transformation target type and teaches it to handle the array subscript on const size arrays with a trivial (empty) fixit.
1 parent fac6d3d commit 644ac2a

File tree

8 files changed

+536
-157
lines changed

8 files changed

+536
-157
lines changed

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

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,43 @@ class VariableGroupsManager {
4242
virtual VarGrpRef getGroupOfParms() const =0;
4343
};
4444

45+
// FixitStrategy is a map from variables to the way we plan to emit fixes for
46+
// these variables. It is figured out gradually by trying different fixes
47+
// for different variables depending on gadgets in which these variables
48+
// participate.
49+
class FixitStrategy {
50+
public:
51+
enum class Kind {
52+
Wontfix, // We don't plan to emit a fixit for this variable.
53+
Span, // We recommend replacing the variable with std::span.
54+
Iterator, // We recommend replacing the variable with std::span::iterator.
55+
Array, // We recommend replacing the variable with std::array.
56+
Vector // We recommend replacing the variable with std::vector.
57+
};
58+
59+
private:
60+
using MapTy = llvm::DenseMap<const VarDecl *, Kind>;
61+
62+
MapTy Map;
63+
64+
public:
65+
FixitStrategy() = default;
66+
FixitStrategy(const FixitStrategy &) = delete; // Let's avoid copies.
67+
FixitStrategy &operator=(const FixitStrategy &) = delete;
68+
FixitStrategy(FixitStrategy &&) = default;
69+
FixitStrategy &operator=(FixitStrategy &&) = default;
70+
71+
void set(const VarDecl *VD, Kind K) { Map[VD] = K; }
72+
73+
Kind lookup(const VarDecl *VD) const {
74+
auto I = Map.find(VD);
75+
if (I == Map.end())
76+
return Kind::Wontfix;
77+
78+
return I->second;
79+
}
80+
};
81+
4582
/// The interface that lets the caller handle unsafe buffer usage analysis
4683
/// results by overriding this class's handle... methods.
4784
class UnsafeBufferUsageHandler {
@@ -75,9 +112,11 @@ class UnsafeBufferUsageHandler {
75112
///
76113
/// `D` is the declaration of the callable under analysis that owns `Variable`
77114
/// and all of its group mates.
78-
virtual void handleUnsafeVariableGroup(const VarDecl *Variable,
79-
const VariableGroupsManager &VarGrpMgr,
80-
FixItList &&Fixes, const Decl *D) = 0;
115+
virtual void
116+
handleUnsafeVariableGroup(const VarDecl *Variable,
117+
const VariableGroupsManager &VarGrpMgr,
118+
FixItList &&Fixes, const Decl *D,
119+
const FixitStrategy &VarTargetTypes) = 0;
81120

82121
#ifndef NDEBUG
83122
public:

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12128,9 +12128,9 @@ def warn_unsafe_buffer_operation : Warning<
1212812128
def note_unsafe_buffer_operation : Note<
1212912129
"used%select{| in pointer arithmetic| in buffer access}0 here">;
1213012130
def note_unsafe_buffer_variable_fixit_group : Note<
12131-
"change type of %0 to '%select{std::span|std::array|std::span::iterator}1' to preserve bounds information%select{|, and change %2 to '%select{std::span|std::array|std::span::iterator}1' to propagate bounds information between them}3">;
12131+
"change type of %0 to '%select{std::span' to preserve bounds information|std::array' to label it for hardening|std::span::iterator' to preserve bounds information}1%select{|, and change %2 to '%select{std::span|std::array|std::span::iterator}1' to propagate bounds information between them}3">;
1213212132
def note_unsafe_buffer_variable_fixit_together : Note<
12133-
"change type of %0 to '%select{std::span|std::array|std::span::iterator}1' to preserve bounds information"
12133+
"change type of %0 to '%select{std::span' to preserve bounds information|std::array' to label it for hardening|std::span::iterator' to preserve bounds information}1"
1213412134
"%select{|, and change %2 to safe types to make function %4 bounds-safe}3">;
1213512135
def note_safe_buffer_usage_suggestions_disabled : Note<
1213612136
"pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions">;

0 commit comments

Comments
 (0)