Skip to content

Commit c9ad94f

Browse files
[-Wunsafe-buffer-usage] Add findUnsafePointers (llvm#135421) (#10492)
Co-authored-by: Jan Korous <[email protected]>
1 parent 5a4e5d9 commit c9ad94f

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "clang/AST/Stmt.h"
2020
#include "clang/Basic/SourceLocation.h"
2121
#include "llvm/Support/Debug.h"
22+
#include <set>
2223

2324
namespace clang {
2425

@@ -203,6 +204,8 @@ namespace internal {
203204
bool anyConflict(const llvm::SmallVectorImpl<FixItHint> &FixIts,
204205
const SourceManager &SM);
205206
} // namespace internal
207+
208+
std::set<const Expr *> findUnsafePointers(const FunctionDecl *FD);
206209
} // end namespace clang
207210

208211
#endif /* LLVM_CLANG_ANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_H */

clang/lib/Analysis/UnsafeBufferUsage.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1957,6 +1957,8 @@ class WarningGadget : public Gadget {
19571957
virtual void handleUnsafeOperation(UnsafeBufferUsageHandler &Handler,
19581958
bool IsRelatedToDecl,
19591959
ASTContext &Ctx) const = 0;
1960+
1961+
virtual SmallVector<const Expr *, 1> getUnsafePtrs() const = 0;
19601962
};
19611963

19621964
/// Fixable gadgets correspond to code patterns that aren't always unsafe but
@@ -2039,6 +2041,10 @@ class IncrementGadget : public WarningGadget {
20392041

20402042
return std::move(Uses);
20412043
}
2044+
2045+
SmallVector<const Expr *, 1> getUnsafePtrs() const override {
2046+
return {Op->getSubExpr()->IgnoreParenImpCasts()};
2047+
}
20422048
};
20432049

20442050
/// A decrement of a pointer-type value is unsafe as it may run the pointer
@@ -2082,6 +2088,10 @@ class DecrementGadget : public WarningGadget {
20822088

20832089
return {};
20842090
}
2091+
2092+
SmallVector<const Expr *, 1> getUnsafePtrs() const override {
2093+
return {Op->getSubExpr()->IgnoreParenImpCasts()};
2094+
}
20852095
};
20862096

20872097
/// Array subscript expressions on raw pointers as if they're arrays. Unsafe as
@@ -2131,6 +2141,10 @@ class ArraySubscriptGadget : public WarningGadget {
21312141

21322142
return {};
21332143
}
2144+
2145+
SmallVector<const Expr *, 1> getUnsafePtrs() const override {
2146+
return {ASE->getBase()->IgnoreParenImpCasts()};
2147+
}
21342148
};
21352149

21362150
/// A pointer arithmetic expression of one of the forms:
@@ -2194,6 +2208,11 @@ class PointerArithmeticGadget : public WarningGadget {
21942208

21952209
return {};
21962210
}
2211+
2212+
SmallVector<const Expr *, 1> getUnsafePtrs() const override {
2213+
return {Ptr->IgnoreParenImpCasts()};
2214+
}
2215+
21972216
// FIXME: pointer adding zero should be fine
21982217
// FIXME: this gadge will need a fix-it
21992218
};
@@ -2251,6 +2270,8 @@ class SpanTwoParamConstructorGadget : public WarningGadget {
22512270
}
22522271
return {};
22532272
}
2273+
2274+
SmallVector<const Expr *, 1> getUnsafePtrs() const override { return {}; }
22542275
};
22552276

22562277
/// A pointer initialization expression of the form:
@@ -2483,6 +2504,8 @@ class UnsafeBufferUsageAttrGadget : public WarningGadget {
24832504
SourceLocation getSourceLoc() const override { return Op->getBeginLoc(); }
24842505

24852506
DeclUseList getClaimedVarUseSites() const override { return {}; }
2507+
2508+
SmallVector<const Expr *, 1> getUnsafePtrs() const override { return {}; }
24862509
};
24872510

24882511
/// A call of a constructor that performs unchecked buffer operations
@@ -2521,6 +2544,8 @@ class UnsafeBufferUsageCtorAttrGadget : public WarningGadget {
25212544
SourceLocation getSourceLoc() const override { return Op->getBeginLoc(); }
25222545

25232546
DeclUseList getClaimedVarUseSites() const override { return {}; }
2547+
2548+
SmallVector<const Expr *, 1> getUnsafePtrs() const override { return {}; }
25242549
};
25252550

25262551
// Warning gadget for unsafe invocation of span::data method.
@@ -2587,6 +2612,8 @@ class DataInvocationGadget : public WarningGadget {
25872612
return true;
25882613
return false;
25892614
}
2615+
2616+
SmallVector<const Expr *, 1> getUnsafePtrs() const override { return {}; }
25902617
};
25912618

25922619
class UnsafeLibcFunctionCallGadget : public WarningGadget {
@@ -2714,6 +2741,8 @@ class UnsafeLibcFunctionCallGadget : public WarningGadget {
27142741
}
27152742

27162743
DeclUseList getClaimedVarUseSites() const override { return {}; }
2744+
2745+
SmallVector<const Expr *, 1> getUnsafePtrs() const override { return {}; }
27172746
};
27182747

27192748
// Represents expressions of the form `DRE[*]` in the Unspecified Lvalue
@@ -3216,6 +3245,10 @@ class CountAttributedPointerArgumentGadget : public WarningGadget {
32163245
}
32173246
return {};
32183247
}
3248+
3249+
SmallVector<const Expr *, 1> getUnsafePtrs() const override {
3250+
return {};
3251+
}
32193252
};
32203253

32213254
// Represents an argument that is being passed to a __single pointer.
@@ -3266,6 +3299,10 @@ class SinglePointerArgumentGadget : public WarningGadget {
32663299
}
32673300
return {};
32683301
}
3302+
3303+
SmallVector<const Expr *, 1> getUnsafePtrs() const override {
3304+
return {};
3305+
}
32693306
};
32703307

32713308
/// Scan the function and return a list of gadgets found with provided kits.
@@ -3395,6 +3432,52 @@ template <typename NodeTy> struct CompareNode {
33953432
}
33963433
};
33973434

3435+
std::set<const Expr *> clang::findUnsafePointers(const FunctionDecl *FD) {
3436+
class MockReporter : public UnsafeBufferUsageHandler {
3437+
public:
3438+
MockReporter() {}
3439+
void handleUnsafeOperation(const Stmt *, bool, ASTContext &) override {}
3440+
void handleUnsafeLibcCall(const CallExpr *, unsigned, ASTContext &,
3441+
const Expr *UnsafeArg = nullptr) override {}
3442+
void handleUnsafeOperationInContainer(const Stmt *, bool,
3443+
ASTContext &) override {}
3444+
void handleUnsafeVariableGroup(const VarDecl *,
3445+
const VariableGroupsManager &, FixItList &&,
3446+
const Decl *,
3447+
const FixitStrategy &) override {}
3448+
bool isSafeBufferOptOut(const SourceLocation &) const override {
3449+
return false;
3450+
}
3451+
bool ignoreUnsafeBufferInContainer(const SourceLocation &) const override {
3452+
return false;
3453+
}
3454+
bool ignoreUnsafeBufferInLibcCall(const SourceLocation &) const override {
3455+
return false;
3456+
}
3457+
std::string getUnsafeBufferUsageAttributeTextAt(
3458+
SourceLocation, StringRef WSSuffix = "") const override {
3459+
return "";
3460+
}
3461+
};
3462+
3463+
FixableGadgetList FixableGadgets;
3464+
WarningGadgetList WarningGadgets;
3465+
DeclUseTracker Tracker;
3466+
MockReporter IgnoreHandler;
3467+
3468+
findGadgets(FD->getBody(), FD->getASTContext(), IgnoreHandler, false,
3469+
FixableGadgets, WarningGadgets, Tracker);
3470+
3471+
std::set<const Expr *> Result;
3472+
for (auto &G : WarningGadgets) {
3473+
for (const Expr *E : G->getUnsafePtrs()) {
3474+
Result.insert(E);
3475+
}
3476+
}
3477+
3478+
return Result;
3479+
}
3480+
33983481
struct WarningGadgetSets {
33993482
std::map<const VarDecl *, std::set<const WarningGadget *>,
34003483
// To keep keys sorted by their locations in the map so that the

0 commit comments

Comments
 (0)