26 #include "llvm/ADT/SmallString.h"
27 #include "llvm/Support/raw_ostream.h"
29 using namespace clang;
39 inline bool sameDecl(
const Expr *A1,
const Expr *A2) {
42 return D1->
getDecl() == D2->getDecl();
47 inline bool isSizeof(
const Expr *E,
const Expr *WithArg) {
49 dyn_cast<UnaryExprOrTypeTraitExpr>(E))
51 return sameDecl(UE->getArgumentExpr(), WithArg);
56 inline bool isStrlen(
const Expr *E,
const Expr *WithArg) {
57 if (
const CallExpr *CE = dyn_cast<CallExpr>(E)) {
62 sameDecl(CE->getArg(0), WithArg));
68 inline bool isOne(
const Expr *E) {
70 return (IL->getValue().isIntN(1));
74 inline StringRef getPrintableName(
const Expr *E) {
82 bool containsBadStrncatPattern(
const CallExpr *CE);
86 :
Checker(checker), BR(br), AC(ac) {}
89 void VisitChildren(
Stmt *
S);
90 void VisitStmt(
Stmt *
S) {
103 bool WalkAST::containsBadStrncatPattern(
const CallExpr *CE) {
114 if (BE->getOpcode() ==
BO_Sub) {
115 const Expr *L = BE->getLHS();
116 const Expr *R = BE->getRHS();
117 if (isSizeof(L, DstArg) && isStrlen(R, DstArg))
126 if (isSizeof(LenArg, DstArg))
130 if (isSizeof(LenArg, SrcArg))
135 void WalkAST::VisitCallExpr(
CallExpr *CE) {
141 if (containsBadStrncatPattern(CE)) {
147 StringRef DstName = getPrintableName(DstArg);
150 llvm::raw_svector_ostream os(S);
151 os <<
"Potential buffer overflow. ";
152 if (!DstName.empty()) {
153 os <<
"Replace with 'sizeof(" << DstName <<
") "
154 "- strlen(" << DstName <<
") - 1'";
158 os <<
"se a safer 'strlcat' API";
160 BR.EmitBasicReport(FD,
Checker,
"Anti-pattern in the argument",
161 "C String API", os.str(), Loc,
162 LenArg->getSourceRange());
170 void WalkAST::VisitChildren(
Stmt *S) {
171 for (
Stmt *Child : S->children())
177 class CStringSyntaxChecker:
public Checker<check::ASTCodeBody> {
StringRef getName() const
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Defines enumerations for the type traits support.
A builtin binary operation expression such as "x + y" or "x <= y".
Expr * IgnoreParenCasts() LLVM_READONLY
const Decl * getDecl() const
AnalysisDeclContext * getAnalysisDeclContext(const Decl *D)
static bool isCLibraryFunction(const FunctionDecl *FD, StringRef Name=StringRef())
Returns true if the callee is an externally-visible function in the top-level namespace, such as malloc.
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
CHECKER * registerChecker()
Used to register checkers.
virtual Stmt * getBody() const
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return 0.
unsigned getNumArgs() const
Defines the clang::TargetInfo interface.
A reference to a declared variable, function, enum, etc. [C99 6.5.1p2].