blob: 0798a296438d3e1a65fc7f006110d2e841f82032 [file] [log] [blame]
Ted Kremenekdbfb5f82009-07-23 01:07:19 +00001//==- CheckSecuritySyntaxOnly.cpp - Basic security checks --------*- C++ -*-==//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines a set of flow-insensitive security checks.
11//
12//===----------------------------------------------------------------------===//
13
Argyrios Kyrtzidis7dd445e2011-02-17 21:39:33 +000014#include "ClangSACheckers.h"
Anna Zaks590dd8e2011-09-20 21:38:35 +000015#include "clang/Analysis/AnalysisContext.h"
16#include "clang/AST/StmtVisitor.h"
17#include "clang/Basic/TargetInfo.h"
Argyrios Kyrtzidisec8605f2011-03-01 01:16:21 +000018#include "clang/StaticAnalyzer/Core/Checker.h"
Ted Kremenek9b663712011-02-10 01:03:03 +000019#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
Anna Zaks590dd8e2011-09-20 21:38:35 +000020#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
Lenny Maioranic2dace12011-04-03 05:07:11 +000021#include "llvm/ADT/StringSwitch.h"
Anna Zaks590dd8e2011-09-20 21:38:35 +000022#include "llvm/Support/raw_ostream.h"
Ted Kremenekdbfb5f82009-07-23 01:07:19 +000023
24using namespace clang;
Ted Kremenek9ef65372010-12-23 07:20:52 +000025using namespace ento;
Ted Kremenekdbfb5f82009-07-23 01:07:19 +000026
Ted Kremenek88c8bc82010-01-15 08:20:31 +000027static bool isArc4RandomAvailable(const ASTContext &Ctx) {
Douglas Gregorbcfd1f52011-09-02 00:18:52 +000028 const llvm::Triple &T = Ctx.getTargetInfo().getTriple();
Ted Kremenek88c8bc82010-01-15 08:20:31 +000029 return T.getVendor() == llvm::Triple::Apple ||
Douglas Gregor0f565592011-01-17 19:16:24 +000030 T.getOS() == llvm::Triple::FreeBSD ||
31 T.getOS() == llvm::Triple::NetBSD ||
32 T.getOS() == llvm::Triple::OpenBSD ||
33 T.getOS() == llvm::Triple::DragonFly;
Ted Kremenek88c8bc82010-01-15 08:20:31 +000034}
35
Ted Kremenekdbfb5f82009-07-23 01:07:19 +000036namespace {
Ted Kremenek76a54242012-01-20 01:44:29 +000037struct DefaultBool {
38 bool val;
39 DefaultBool() : val(false) {}
40 operator bool() const { return val; }
41 DefaultBool &operator=(bool b) { val = b; return *this; }
42};
43
44struct ChecksFilter {
45 DefaultBool check_gets;
46 DefaultBool check_getpw;
47 DefaultBool check_mktemp;
Ted Kremenekb63d8d82012-01-20 05:35:06 +000048 DefaultBool check_mkstemp;
Ted Kremenek76a54242012-01-20 01:44:29 +000049 DefaultBool check_strcpy;
50 DefaultBool check_rand;
51 DefaultBool check_vfork;
52 DefaultBool check_FloatLoopCounter;
Ted Kremenekb63d8d82012-01-20 05:35:06 +000053 DefaultBool check_UncheckedReturn;
Ted Kremenek76a54242012-01-20 01:44:29 +000054};
55
Kovarththanan Rajaratnamba5fb5a2009-11-28 06:07:30 +000056class WalkAST : public StmtVisitor<WalkAST> {
Mike Stump1eb44332009-09-09 15:08:12 +000057 BugReporter &BR;
Ted Kremenek1d26f482011-10-24 01:32:45 +000058 AnalysisDeclContext* AC;
Ted Kremenek24650472009-09-02 02:47:41 +000059 enum { num_setids = 6 };
60 IdentifierInfo *II_setid[num_setids];
Ted Kremenek2c016762010-03-24 22:39:47 +000061
Ted Kremenek88c8bc82010-01-15 08:20:31 +000062 const bool CheckRand;
Ted Kremenek76a54242012-01-20 01:44:29 +000063 const ChecksFilter &filter;
Mike Stump1eb44332009-09-09 15:08:12 +000064
Ted Kremenekdbfb5f82009-07-23 01:07:19 +000065public:
Ted Kremenek76a54242012-01-20 01:44:29 +000066 WalkAST(BugReporter &br, AnalysisDeclContext* ac,
67 const ChecksFilter &f)
Anna Zaks590dd8e2011-09-20 21:38:35 +000068 : BR(br), AC(ac), II_setid(),
Ted Kremenek76a54242012-01-20 01:44:29 +000069 CheckRand(isArc4RandomAvailable(BR.getContext())),
70 filter(f) {}
Mike Stump1eb44332009-09-09 15:08:12 +000071
Ted Kremenekdbfb5f82009-07-23 01:07:19 +000072 // Statement visitor methods.
Ted Kremenekefcbb152009-07-23 22:29:41 +000073 void VisitCallExpr(CallExpr *CE);
Ted Kremenekdbfb5f82009-07-23 01:07:19 +000074 void VisitForStmt(ForStmt *S);
Ted Kremenek65a81a92009-08-28 00:08:09 +000075 void VisitCompoundStmt (CompoundStmt *S);
Ted Kremenek8baf86d2009-07-23 21:34:35 +000076 void VisitStmt(Stmt *S) { VisitChildren(S); }
Ted Kremenekdbfb5f82009-07-23 01:07:19 +000077
78 void VisitChildren(Stmt *S);
Mike Stump1eb44332009-09-09 15:08:12 +000079
Ted Kremenekefcbb152009-07-23 22:29:41 +000080 // Helpers.
Lenny Maiorani9cb677e2011-04-05 20:18:46 +000081 bool checkCall_strCommon(const CallExpr *CE, const FunctionDecl *FD);
Mike Stump1eb44332009-09-09 15:08:12 +000082
Lenny Maioranic2dace12011-04-03 05:07:11 +000083 typedef void (WalkAST::*FnCheck)(const CallExpr *,
84 const FunctionDecl *);
85
Ted Kremenekdbfb5f82009-07-23 01:07:19 +000086 // Checker-specific methods.
Lenny Maiorani9cb677e2011-04-05 20:18:46 +000087 void checkLoopConditionForFloat(const ForStmt *FS);
88 void checkCall_gets(const CallExpr *CE, const FunctionDecl *FD);
89 void checkCall_getpw(const CallExpr *CE, const FunctionDecl *FD);
90 void checkCall_mktemp(const CallExpr *CE, const FunctionDecl *FD);
Ted Kremenekb63d8d82012-01-20 05:35:06 +000091 void checkCall_mkstemp(const CallExpr *CE, const FunctionDecl *FD);
Lenny Maiorani9cb677e2011-04-05 20:18:46 +000092 void checkCall_strcpy(const CallExpr *CE, const FunctionDecl *FD);
93 void checkCall_strcat(const CallExpr *CE, const FunctionDecl *FD);
94 void checkCall_rand(const CallExpr *CE, const FunctionDecl *FD);
95 void checkCall_random(const CallExpr *CE, const FunctionDecl *FD);
Anna Zaksa7957ff2011-10-11 04:34:54 +000096 void checkCall_vfork(const CallExpr *CE, const FunctionDecl *FD);
Lenny Maiorani9cb677e2011-04-05 20:18:46 +000097 void checkUncheckedReturnValue(CallExpr *CE);
Ted Kremenekdbfb5f82009-07-23 01:07:19 +000098};
99} // end anonymous namespace
100
101//===----------------------------------------------------------------------===//
102// AST walking.
103//===----------------------------------------------------------------------===//
104
105void WalkAST::VisitChildren(Stmt *S) {
106 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
107 if (Stmt *child = *I)
108 Visit(child);
109}
110
Ted Kremenekefcbb152009-07-23 22:29:41 +0000111void WalkAST::VisitCallExpr(CallExpr *CE) {
Lenny Maioranic2dace12011-04-03 05:07:11 +0000112 // Get the callee.
113 const FunctionDecl *FD = CE->getDirectCallee();
114
115 if (!FD)
116 return;
117
118 // Get the name of the callee. If it's a builtin, strip off the prefix.
119 IdentifierInfo *II = FD->getIdentifier();
120 if (!II) // if no identifier, not a simple C function
121 return;
Chris Lattner5f9e2722011-07-23 10:55:15 +0000122 StringRef Name = II->getName();
Lenny Maioranic2dace12011-04-03 05:07:11 +0000123 if (Name.startswith("__builtin_"))
124 Name = Name.substr(10);
125
126 // Set the evaluation function by switching on the callee name.
127 FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
Lenny Maiorani9cb677e2011-04-05 20:18:46 +0000128 .Case("gets", &WalkAST::checkCall_gets)
129 .Case("getpw", &WalkAST::checkCall_getpw)
130 .Case("mktemp", &WalkAST::checkCall_mktemp)
Ted Kremenekb63d8d82012-01-20 05:35:06 +0000131 .Case("mkstemp", &WalkAST::checkCall_mkstemp)
132 .Case("mkdtemp", &WalkAST::checkCall_mkstemp)
133 .Case("mkstemps", &WalkAST::checkCall_mkstemp)
Lenny Maiorani9cb677e2011-04-05 20:18:46 +0000134 .Cases("strcpy", "__strcpy_chk", &WalkAST::checkCall_strcpy)
135 .Cases("strcat", "__strcat_chk", &WalkAST::checkCall_strcat)
136 .Case("drand48", &WalkAST::checkCall_rand)
137 .Case("erand48", &WalkAST::checkCall_rand)
138 .Case("jrand48", &WalkAST::checkCall_rand)
139 .Case("lrand48", &WalkAST::checkCall_rand)
140 .Case("mrand48", &WalkAST::checkCall_rand)
141 .Case("nrand48", &WalkAST::checkCall_rand)
142 .Case("lcong48", &WalkAST::checkCall_rand)
143 .Case("rand", &WalkAST::checkCall_rand)
144 .Case("rand_r", &WalkAST::checkCall_rand)
145 .Case("random", &WalkAST::checkCall_random)
Anna Zaksa7957ff2011-10-11 04:34:54 +0000146 .Case("vfork", &WalkAST::checkCall_vfork)
Lenny Maioranic2dace12011-04-03 05:07:11 +0000147 .Default(NULL);
148
149 // If the callee isn't defined, it is not of security concern.
150 // Check and evaluate the call.
151 if (evalFunction)
152 (this->*evalFunction)(CE, FD);
Mike Stump1eb44332009-09-09 15:08:12 +0000153
Ted Kremenekefcbb152009-07-23 22:29:41 +0000154 // Recurse and check children.
155 VisitChildren(CE);
156}
157
Ted Kremenek65a81a92009-08-28 00:08:09 +0000158void WalkAST::VisitCompoundStmt(CompoundStmt *S) {
159 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I)
Mike Stump1eb44332009-09-09 15:08:12 +0000160 if (Stmt *child = *I) {
161 if (CallExpr *CE = dyn_cast<CallExpr>(child))
Lenny Maiorani9cb677e2011-04-05 20:18:46 +0000162 checkUncheckedReturnValue(CE);
Mike Stump1eb44332009-09-09 15:08:12 +0000163 Visit(child);
164 }
Ted Kremenek65a81a92009-08-28 00:08:09 +0000165}
166
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000167void WalkAST::VisitForStmt(ForStmt *FS) {
Lenny Maiorani9cb677e2011-04-05 20:18:46 +0000168 checkLoopConditionForFloat(FS);
Ted Kremenekdbfb5f82009-07-23 01:07:19 +0000169
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000170 // Recurse and check children.
171 VisitChildren(FS);
Ted Kremenekdbfb5f82009-07-23 01:07:19 +0000172}
173
174//===----------------------------------------------------------------------===//
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000175// Check: floating poing variable used as loop counter.
Ted Kremenek5abeb522009-07-23 21:44:18 +0000176// Originally: <rdar://problem/6336718>
177// Implements: CERT security coding advisory FLP-30.
Ted Kremenekdbfb5f82009-07-23 01:07:19 +0000178//===----------------------------------------------------------------------===//
179
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000180static const DeclRefExpr*
Lenny Maiorani9cb677e2011-04-05 20:18:46 +0000181getIncrementedVar(const Expr *expr, const VarDecl *x, const VarDecl *y) {
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000182 expr = expr->IgnoreParenCasts();
Mike Stump1eb44332009-09-09 15:08:12 +0000183
184 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(expr)) {
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000185 if (!(B->isAssignmentOp() || B->isCompoundAssignmentOp() ||
John McCall2de56d12010-08-25 11:45:40 +0000186 B->getOpcode() == BO_Comma))
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000187 return NULL;
Mike Stump1eb44332009-09-09 15:08:12 +0000188
Lenny Maiorani9cb677e2011-04-05 20:18:46 +0000189 if (const DeclRefExpr *lhs = getIncrementedVar(B->getLHS(), x, y))
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000190 return lhs;
Mike Stump1eb44332009-09-09 15:08:12 +0000191
Lenny Maiorani9cb677e2011-04-05 20:18:46 +0000192 if (const DeclRefExpr *rhs = getIncrementedVar(B->getRHS(), x, y))
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000193 return rhs;
Mike Stump1eb44332009-09-09 15:08:12 +0000194
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000195 return NULL;
Ted Kremenekdbfb5f82009-07-23 01:07:19 +0000196 }
Mike Stump1eb44332009-09-09 15:08:12 +0000197
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000198 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(expr)) {
199 const NamedDecl *ND = DR->getDecl();
200 return ND == x || ND == y ? DR : NULL;
201 }
Mike Stump1eb44332009-09-09 15:08:12 +0000202
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000203 if (const UnaryOperator *U = dyn_cast<UnaryOperator>(expr))
204 return U->isIncrementDecrementOp()
Lenny Maiorani9cb677e2011-04-05 20:18:46 +0000205 ? getIncrementedVar(U->getSubExpr(), x, y) : NULL;
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000206
Ted Kremenekdbfb5f82009-07-23 01:07:19 +0000207 return NULL;
208}
209
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000210/// CheckLoopConditionForFloat - This check looks for 'for' statements that
211/// use a floating point variable as a loop counter.
212/// CERT: FLP30-C, FLP30-CPP.
213///
Lenny Maiorani9cb677e2011-04-05 20:18:46 +0000214void WalkAST::checkLoopConditionForFloat(const ForStmt *FS) {
Ted Kremenek76a54242012-01-20 01:44:29 +0000215 if (!filter.check_FloatLoopCounter)
216 return;
217
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000218 // Does the loop have a condition?
219 const Expr *condition = FS->getCond();
Mike Stump1eb44332009-09-09 15:08:12 +0000220
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000221 if (!condition)
222 return;
223
224 // Does the loop have an increment?
225 const Expr *increment = FS->getInc();
Mike Stump1eb44332009-09-09 15:08:12 +0000226
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000227 if (!increment)
228 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000229
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000230 // Strip away '()' and casts.
231 condition = condition->IgnoreParenCasts();
232 increment = increment->IgnoreParenCasts();
Mike Stump1eb44332009-09-09 15:08:12 +0000233
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000234 // Is the loop condition a comparison?
235 const BinaryOperator *B = dyn_cast<BinaryOperator>(condition);
236
237 if (!B)
238 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000239
Ted Kremenekcad9f412009-07-24 20:26:31 +0000240 // Is this a comparison?
241 if (!(B->isRelationalOp() || B->isEqualityOp()))
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000242 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000243
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000244 // Are we comparing variables?
John McCallf6a16482010-12-04 03:47:34 +0000245 const DeclRefExpr *drLHS =
246 dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParenLValueCasts());
247 const DeclRefExpr *drRHS =
248 dyn_cast<DeclRefExpr>(B->getRHS()->IgnoreParenLValueCasts());
Mike Stump1eb44332009-09-09 15:08:12 +0000249
Ted Kremenekcad9f412009-07-24 20:26:31 +0000250 // Does at least one of the variables have a floating point type?
Douglas Gregor0c293ea2010-06-22 23:07:26 +0000251 drLHS = drLHS && drLHS->getType()->isRealFloatingType() ? drLHS : NULL;
252 drRHS = drRHS && drRHS->getType()->isRealFloatingType() ? drRHS : NULL;
Mike Stump1eb44332009-09-09 15:08:12 +0000253
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000254 if (!drLHS && !drRHS)
255 return;
256
257 const VarDecl *vdLHS = drLHS ? dyn_cast<VarDecl>(drLHS->getDecl()) : NULL;
258 const VarDecl *vdRHS = drRHS ? dyn_cast<VarDecl>(drRHS->getDecl()) : NULL;
Mike Stump1eb44332009-09-09 15:08:12 +0000259
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000260 if (!vdLHS && !vdRHS)
Mike Stump1eb44332009-09-09 15:08:12 +0000261 return;
262
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000263 // Does either variable appear in increment?
Lenny Maiorani9cb677e2011-04-05 20:18:46 +0000264 const DeclRefExpr *drInc = getIncrementedVar(increment, vdLHS, vdRHS);
Mike Stump1eb44332009-09-09 15:08:12 +0000265
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000266 if (!drInc)
267 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000268
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000269 // Emit the error. First figure out which DeclRefExpr in the condition
270 // referenced the compared variable.
271 const DeclRefExpr *drCond = vdLHS == drInc->getDecl() ? drLHS : drRHS;
272
Chris Lattner5f9e2722011-07-23 10:55:15 +0000273 SmallVector<SourceRange, 2> ranges;
Ted Kremenek2c016762010-03-24 22:39:47 +0000274 llvm::SmallString<256> sbuf;
275 llvm::raw_svector_ostream os(sbuf);
Mike Stump1eb44332009-09-09 15:08:12 +0000276
Daniel Dunbar4087f272010-08-17 22:39:59 +0000277 os << "Variable '" << drCond->getDecl()->getName()
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000278 << "' with floating point type '" << drCond->getType().getAsString()
279 << "' should not be used as a loop counter";
280
281 ranges.push_back(drCond->getSourceRange());
282 ranges.push_back(drInc->getSourceRange());
Mike Stump1eb44332009-09-09 15:08:12 +0000283
Ted Kremenek8baf86d2009-07-23 21:34:35 +0000284 const char *bugType = "Floating point variable used as loop counter";
Anna Zaks590dd8e2011-09-20 21:38:35 +0000285
286 PathDiagnosticLocation FSLoc =
287 PathDiagnosticLocation::createBegin(FS, BR.getSourceManager(), AC);
Benjamin Kramerf0171732009-11-29 18:27:55 +0000288 BR.EmitBasicReport(bugType, "Security", os.str(),
Anna Zaks590dd8e2011-09-20 21:38:35 +0000289 FSLoc, ranges.data(), ranges.size());
Ted Kremenekdbfb5f82009-07-23 01:07:19 +0000290}
291
292//===----------------------------------------------------------------------===//
Ted Kremenekefcbb152009-07-23 22:29:41 +0000293// Check: Any use of 'gets' is insecure.
294// Originally: <rdar://problem/6335715>
295// Implements (part of): 300-BSI (buildsecurityin.us-cert.gov)
Zhongxing Xuaa30b3b2009-11-09 08:13:04 +0000296// CWE-242: Use of Inherently Dangerous Function
Ted Kremenekefcbb152009-07-23 22:29:41 +0000297//===----------------------------------------------------------------------===//
298
Lenny Maiorani9cb677e2011-04-05 20:18:46 +0000299void WalkAST::checkCall_gets(const CallExpr *CE, const FunctionDecl *FD) {
Ted Kremenek76a54242012-01-20 01:44:29 +0000300 if (!filter.check_gets)
301 return;
302
Abramo Bagnara723df242010-12-14 22:11:44 +0000303 const FunctionProtoType *FPT
304 = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
Zhongxing Xubd842e32009-11-09 12:19:26 +0000305 if (!FPT)
Ted Kremenekefcbb152009-07-23 22:29:41 +0000306 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000307
Ted Kremenekefcbb152009-07-23 22:29:41 +0000308 // Verify that the function takes a single argument.
Zhongxing Xubd842e32009-11-09 12:19:26 +0000309 if (FPT->getNumArgs() != 1)
Ted Kremenekefcbb152009-07-23 22:29:41 +0000310 return;
311
312 // Is the argument a 'char*'?
Zhongxing Xubd842e32009-11-09 12:19:26 +0000313 const PointerType *PT = dyn_cast<PointerType>(FPT->getArgType(0));
Ted Kremenekefcbb152009-07-23 22:29:41 +0000314 if (!PT)
315 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000316
Ted Kremenekefcbb152009-07-23 22:29:41 +0000317 if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
318 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000319
Ted Kremenekefcbb152009-07-23 22:29:41 +0000320 // Issue a warning.
321 SourceRange R = CE->getCallee()->getSourceRange();
Anna Zaks590dd8e2011-09-20 21:38:35 +0000322 PathDiagnosticLocation CELoc =
323 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
Ted Kremenekefcbb152009-07-23 22:29:41 +0000324 BR.EmitBasicReport("Potential buffer overflow in call to 'gets'",
325 "Security",
326 "Call to function 'gets' is extremely insecure as it can "
327 "always result in a buffer overflow",
Anna Zaks590dd8e2011-09-20 21:38:35 +0000328 CELoc, &R, 1);
Ted Kremenekefcbb152009-07-23 22:29:41 +0000329}
330
331//===----------------------------------------------------------------------===//
Zhongxing Xubd842e32009-11-09 12:19:26 +0000332// Check: Any use of 'getpwd' is insecure.
333// CWE-477: Use of Obsolete Functions
334//===----------------------------------------------------------------------===//
335
Lenny Maiorani9cb677e2011-04-05 20:18:46 +0000336void WalkAST::checkCall_getpw(const CallExpr *CE, const FunctionDecl *FD) {
Ted Kremenek76a54242012-01-20 01:44:29 +0000337 if (!filter.check_getpw)
338 return;
339
Abramo Bagnara723df242010-12-14 22:11:44 +0000340 const FunctionProtoType *FPT
341 = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
Zhongxing Xubd842e32009-11-09 12:19:26 +0000342 if (!FPT)
343 return;
344
345 // Verify that the function takes two arguments.
346 if (FPT->getNumArgs() != 2)
347 return;
348
349 // Verify the first argument type is integer.
350 if (!FPT->getArgType(0)->isIntegerType())
351 return;
352
353 // Verify the second argument type is char*.
354 const PointerType *PT = dyn_cast<PointerType>(FPT->getArgType(1));
355 if (!PT)
356 return;
357
358 if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
359 return;
360
361 // Issue a warning.
362 SourceRange R = CE->getCallee()->getSourceRange();
Anna Zaks590dd8e2011-09-20 21:38:35 +0000363 PathDiagnosticLocation CELoc =
364 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
Zhongxing Xubd842e32009-11-09 12:19:26 +0000365 BR.EmitBasicReport("Potential buffer overflow in call to 'getpw'",
366 "Security",
367 "The getpw() function is dangerous as it may overflow the "
368 "provided buffer. It is obsoleted by getpwuid().",
Anna Zaks590dd8e2011-09-20 21:38:35 +0000369 CELoc, &R, 1);
Zhongxing Xubd842e32009-11-09 12:19:26 +0000370}
371
372//===----------------------------------------------------------------------===//
Ted Kremenekb63d8d82012-01-20 05:35:06 +0000373// Check: Any use of 'mktemp' is insecure. It is obsoleted by mkstemp().
Zhongxing Xu1bf40562009-12-03 09:15:23 +0000374// CWE-377: Insecure Temporary File
375//===----------------------------------------------------------------------===//
376
Lenny Maiorani9cb677e2011-04-05 20:18:46 +0000377void WalkAST::checkCall_mktemp(const CallExpr *CE, const FunctionDecl *FD) {
Ted Kremenekb63d8d82012-01-20 05:35:06 +0000378 if (!filter.check_mktemp) {
379 // Fall back to the security check of looking for enough 'X's in the
380 // format string, since that is a less severe warning.
381 checkCall_mkstemp(CE, FD);
Ted Kremenek76a54242012-01-20 01:44:29 +0000382 return;
Ted Kremenekb63d8d82012-01-20 05:35:06 +0000383 }
Ted Kremenek76a54242012-01-20 01:44:29 +0000384
Abramo Bagnara723df242010-12-14 22:11:44 +0000385 const FunctionProtoType *FPT
386 = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
Zhongxing Xu1bf40562009-12-03 09:15:23 +0000387 if(!FPT)
388 return;
Ted Kremenek2c016762010-03-24 22:39:47 +0000389
Lenny Maioraniea4411e2011-03-31 21:26:55 +0000390 // Verify that the function takes a single argument.
Zhongxing Xu1bf40562009-12-03 09:15:23 +0000391 if (FPT->getNumArgs() != 1)
392 return;
393
394 // Verify that the argument is Pointer Type.
395 const PointerType *PT = dyn_cast<PointerType>(FPT->getArgType(0));
396 if (!PT)
397 return;
398
399 // Verify that the argument is a 'char*'.
400 if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
401 return;
Ted Kremenek431a2cb2010-03-24 22:39:45 +0000402
Zhongxing Xu1bf40562009-12-03 09:15:23 +0000403 // Issue a waring.
404 SourceRange R = CE->getCallee()->getSourceRange();
Anna Zaks590dd8e2011-09-20 21:38:35 +0000405 PathDiagnosticLocation CELoc =
406 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
Zhongxing Xu1bf40562009-12-03 09:15:23 +0000407 BR.EmitBasicReport("Potential insecure temporary file in call 'mktemp'",
Eli Friedmana7e68452010-08-22 01:00:03 +0000408 "Security",
409 "Call to function 'mktemp' is insecure as it always "
410 "creates or uses insecure temporary file. Use 'mkstemp' instead",
Anna Zaks590dd8e2011-09-20 21:38:35 +0000411 CELoc, &R, 1);
Zhongxing Xu1bf40562009-12-03 09:15:23 +0000412}
413
Ted Kremenekb63d8d82012-01-20 05:35:06 +0000414
415//===----------------------------------------------------------------------===//
416// Check: Use of 'mkstemp', 'mktemp', 'mkdtemp' should contain at least 6 X's.
417//===----------------------------------------------------------------------===//
418
419void WalkAST::checkCall_mkstemp(const CallExpr *CE, const FunctionDecl *FD) {
420 if (!filter.check_mkstemp)
421 return;
422
423 StringRef Name = FD->getIdentifier()->getName();
424 std::pair<signed, signed> ArgSuffix =
425 llvm::StringSwitch<std::pair<signed, signed> >(Name)
426 .Case("mktemp", std::make_pair(0,-1))
427 .Case("mkstemp", std::make_pair(0,-1))
428 .Case("mkdtemp", std::make_pair(0,-1))
429 .Case("mkstemps", std::make_pair(0,1))
430 .Default(std::make_pair(-1, -1));
431
432 assert(ArgSuffix.first >= 0 && "Unsupported function");
433
434 // Check if the number of arguments is consistent with out expectations.
435 unsigned numArgs = CE->getNumArgs();
436 if ((signed) numArgs <= ArgSuffix.first)
437 return;
438
439 const StringLiteral *strArg =
440 dyn_cast<StringLiteral>(CE->getArg((unsigned)ArgSuffix.first)
441 ->IgnoreParenImpCasts());
442
443 // Currently we only handle string literals. It is possible to do better,
444 // either by looking at references to const variables, or by doing real
445 // flow analysis.
446 if (!strArg || strArg->getCharByteWidth() != 1)
447 return;
448
449 // Count the number of X's, taking into account a possible cutoff suffix.
450 StringRef str = strArg->getString();
451 unsigned numX = 0;
452 unsigned n = str.size();
453
454 // Take into account the suffix.
455 unsigned suffix = 0;
456 if (ArgSuffix.second >= 0) {
457 const Expr *suffixEx = CE->getArg((unsigned)ArgSuffix.second);
458 llvm::APSInt Result;
459 if (!suffixEx->EvaluateAsInt(Result, BR.getContext()))
460 return;
461 // FIXME: Issue a warning.
462 if (Result.isNegative())
463 return;
464 suffix = (unsigned) Result.getZExtValue();
465 n = (n > suffix) ? n - suffix : 0;
466 }
467
468 for (unsigned i = 0; i < n; ++i)
469 if (str[i] == 'X') ++numX;
470
471 if (numX >= 6)
472 return;
473
474 // Issue a warning.
475 SourceRange R = strArg->getSourceRange();
476 PathDiagnosticLocation CELoc =
477 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
478 llvm::SmallString<512> buf;
479 llvm::raw_svector_ostream out(buf);
480 out << "Call to '" << Name << "' should have at least 6 'X's in the"
481 " format string to be secure (" << numX << " 'X'";
482 if (numX != 1)
483 out << 's';
484 out << " seen";
485 if (suffix) {
486 out << ", " << suffix << " character";
487 if (suffix > 1)
488 out << 's';
489 out << " used as a suffix";
490 }
491 out << ')';
492 BR.EmitBasicReport("Insecure temporary file creation", "Security",
493 out.str(), CELoc, &R, 1);
494}
495
Zhongxing Xu1bf40562009-12-03 09:15:23 +0000496//===----------------------------------------------------------------------===//
Lenny Maiorani5b67a822011-03-31 22:09:14 +0000497// Check: Any use of 'strcpy' is insecure.
498//
499// CWE-119: Improper Restriction of Operations within
500// the Bounds of a Memory Buffer
501//===----------------------------------------------------------------------===//
Lenny Maiorani9cb677e2011-04-05 20:18:46 +0000502void WalkAST::checkCall_strcpy(const CallExpr *CE, const FunctionDecl *FD) {
Ted Kremenek76a54242012-01-20 01:44:29 +0000503 if (!filter.check_strcpy)
504 return;
505
Lenny Maiorani9cb677e2011-04-05 20:18:46 +0000506 if (!checkCall_strCommon(CE, FD))
Lenny Maiorani5b67a822011-03-31 22:09:14 +0000507 return;
508
Lenny Maiorani9cb677e2011-04-05 20:18:46 +0000509 // Issue a warning.
Lenny Maiorani5b67a822011-03-31 22:09:14 +0000510 SourceRange R = CE->getCallee()->getSourceRange();
Anna Zaks590dd8e2011-09-20 21:38:35 +0000511 PathDiagnosticLocation CELoc =
512 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
Lenny Maiorani5b67a822011-03-31 22:09:14 +0000513 BR.EmitBasicReport("Potential insecure memory buffer bounds restriction in "
Lenny Maiorani9cb677e2011-04-05 20:18:46 +0000514 "call 'strcpy'",
515 "Security",
516 "Call to function 'strcpy' is insecure as it does not "
Lenny Maiorani5b67a822011-03-31 22:09:14 +0000517 "provide bounding of the memory buffer. Replace "
518 "unbounded copy functions with analogous functions that "
519 "support length arguments such as 'strncpy'. CWE-119.",
Anna Zaks590dd8e2011-09-20 21:38:35 +0000520 CELoc, &R, 1);
Lenny Maiorani5b67a822011-03-31 22:09:14 +0000521}
522
523//===----------------------------------------------------------------------===//
Lenny Maiorani9cb677e2011-04-05 20:18:46 +0000524// Check: Any use of 'strcat' is insecure.
525//
526// CWE-119: Improper Restriction of Operations within
527// the Bounds of a Memory Buffer
528//===----------------------------------------------------------------------===//
529void WalkAST::checkCall_strcat(const CallExpr *CE, const FunctionDecl *FD) {
Ted Kremenek76a54242012-01-20 01:44:29 +0000530 if (!filter.check_strcpy)
531 return;
532
Lenny Maiorani9cb677e2011-04-05 20:18:46 +0000533 if (!checkCall_strCommon(CE, FD))
534 return;
535
536 // Issue a warning.
537 SourceRange R = CE->getCallee()->getSourceRange();
Anna Zaks590dd8e2011-09-20 21:38:35 +0000538 PathDiagnosticLocation CELoc =
539 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
Lenny Maiorani9cb677e2011-04-05 20:18:46 +0000540 BR.EmitBasicReport("Potential insecure memory buffer bounds restriction in "
541 "call 'strcat'",
542 "Security",
543 "Call to function 'strcat' is insecure as it does not "
544 "provide bounding of the memory buffer. Replace "
545 "unbounded copy functions with analogous functions that "
546 "support length arguments such as 'strncat'. CWE-119.",
Anna Zaks590dd8e2011-09-20 21:38:35 +0000547 CELoc, &R, 1);
Lenny Maiorani9cb677e2011-04-05 20:18:46 +0000548}
549
550//===----------------------------------------------------------------------===//
551// Common check for str* functions with no bounds parameters.
552//===----------------------------------------------------------------------===//
553bool WalkAST::checkCall_strCommon(const CallExpr *CE, const FunctionDecl *FD) {
554 const FunctionProtoType *FPT
555 = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
556 if (!FPT)
557 return false;
558
559 // Verify the function takes two arguments, three in the _chk version.
560 int numArgs = FPT->getNumArgs();
561 if (numArgs != 2 && numArgs != 3)
562 return false;
563
564 // Verify the type for both arguments.
565 for (int i = 0; i < 2; i++) {
566 // Verify that the arguments are pointers.
567 const PointerType *PT = dyn_cast<PointerType>(FPT->getArgType(i));
568 if (!PT)
569 return false;
570
571 // Verify that the argument is a 'char*'.
572 if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
573 return false;
574 }
575
576 return true;
577}
578
579//===----------------------------------------------------------------------===//
Ted Kremenek24650472009-09-02 02:47:41 +0000580// Check: Linear congruent random number generators should not be used
581// Originally: <rdar://problem/63371000>
582// CWE-338: Use of cryptographically weak prng
583//===----------------------------------------------------------------------===//
584
Lenny Maiorani9cb677e2011-04-05 20:18:46 +0000585void WalkAST::checkCall_rand(const CallExpr *CE, const FunctionDecl *FD) {
Ted Kremenek76a54242012-01-20 01:44:29 +0000586 if (!filter.check_rand || !CheckRand)
Ted Kremenek24650472009-09-02 02:47:41 +0000587 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000588
Abramo Bagnara723df242010-12-14 22:11:44 +0000589 const FunctionProtoType *FTP
590 = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
Ted Kremenek24650472009-09-02 02:47:41 +0000591 if (!FTP)
592 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000593
Ted Kremenek24650472009-09-02 02:47:41 +0000594 if (FTP->getNumArgs() == 1) {
595 // Is the argument an 'unsigned short *'?
596 // (Actually any integer type is allowed.)
597 const PointerType *PT = dyn_cast<PointerType>(FTP->getArgType(0));
598 if (!PT)
599 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000600
Ted Kremenek24650472009-09-02 02:47:41 +0000601 if (! PT->getPointeeType()->isIntegerType())
602 return;
603 }
Mike Stump1eb44332009-09-09 15:08:12 +0000604 else if (FTP->getNumArgs() != 0)
Ted Kremenek24650472009-09-02 02:47:41 +0000605 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000606
Ted Kremenek24650472009-09-02 02:47:41 +0000607 // Issue a warning.
Ted Kremenek2c016762010-03-24 22:39:47 +0000608 llvm::SmallString<256> buf1;
609 llvm::raw_svector_ostream os1(buf1);
Benjamin Kramerb8989f22011-10-14 18:45:37 +0000610 os1 << '\'' << *FD << "' is a poor random number generator";
Ted Kremenek24650472009-09-02 02:47:41 +0000611
Ted Kremenek2c016762010-03-24 22:39:47 +0000612 llvm::SmallString<256> buf2;
613 llvm::raw_svector_ostream os2(buf2);
Benjamin Kramerb8989f22011-10-14 18:45:37 +0000614 os2 << "Function '" << *FD
Ted Kremenek24650472009-09-02 02:47:41 +0000615 << "' is obsolete because it implements a poor random number generator."
616 << " Use 'arc4random' instead";
617
618 SourceRange R = CE->getCallee()->getSourceRange();
Anna Zaks590dd8e2011-09-20 21:38:35 +0000619 PathDiagnosticLocation CELoc =
620 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
621 BR.EmitBasicReport(os1.str(), "Security", os2.str(), CELoc, &R, 1);
Ted Kremenek24650472009-09-02 02:47:41 +0000622}
623
624//===----------------------------------------------------------------------===//
625// Check: 'random' should not be used
626// Originally: <rdar://problem/63371000>
627//===----------------------------------------------------------------------===//
628
Lenny Maiorani9cb677e2011-04-05 20:18:46 +0000629void WalkAST::checkCall_random(const CallExpr *CE, const FunctionDecl *FD) {
Ted Kremenekb63d8d82012-01-20 05:35:06 +0000630 if (!CheckRand || !filter.check_rand)
Ted Kremenek24650472009-09-02 02:47:41 +0000631 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000632
Abramo Bagnara723df242010-12-14 22:11:44 +0000633 const FunctionProtoType *FTP
634 = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
Ted Kremenek24650472009-09-02 02:47:41 +0000635 if (!FTP)
636 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000637
Ted Kremenek24650472009-09-02 02:47:41 +0000638 // Verify that the function takes no argument.
639 if (FTP->getNumArgs() != 0)
640 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000641
Ted Kremenek24650472009-09-02 02:47:41 +0000642 // Issue a warning.
643 SourceRange R = CE->getCallee()->getSourceRange();
Anna Zaks590dd8e2011-09-20 21:38:35 +0000644 PathDiagnosticLocation CELoc =
645 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
Ted Kremenek24650472009-09-02 02:47:41 +0000646 BR.EmitBasicReport("'random' is not a secure random number generator",
647 "Security",
648 "The 'random' function produces a sequence of values that "
649 "an adversary may be able to predict. Use 'arc4random' "
Anna Zaks590dd8e2011-09-20 21:38:35 +0000650 "instead", CELoc, &R, 1);
Ted Kremenek24650472009-09-02 02:47:41 +0000651}
652
653//===----------------------------------------------------------------------===//
Anna Zaksa7957ff2011-10-11 04:34:54 +0000654// Check: 'vfork' should not be used.
655// POS33-C: Do not use vfork().
656//===----------------------------------------------------------------------===//
657
658void WalkAST::checkCall_vfork(const CallExpr *CE, const FunctionDecl *FD) {
Ted Kremenek76a54242012-01-20 01:44:29 +0000659 if (!filter.check_vfork)
660 return;
661
Anna Zaksa7957ff2011-10-11 04:34:54 +0000662 // All calls to vfork() are insecure, issue a warning.
663 SourceRange R = CE->getCallee()->getSourceRange();
664 PathDiagnosticLocation CELoc =
665 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
666 BR.EmitBasicReport("Potential insecure implementation-specific behavior in "
667 "call 'vfork'",
668 "Security",
669 "Call to function 'vfork' is insecure as it can lead to "
670 "denial of service situations in the parent process. "
671 "Replace calls to vfork with calls to the safer "
672 "'posix_spawn' function",
673 CELoc, &R, 1);
674}
675
676//===----------------------------------------------------------------------===//
Ted Kremenek65a81a92009-08-28 00:08:09 +0000677// Check: Should check whether privileges are dropped successfully.
678// Originally: <rdar://problem/6337132>
679//===----------------------------------------------------------------------===//
680
Lenny Maiorani9cb677e2011-04-05 20:18:46 +0000681void WalkAST::checkUncheckedReturnValue(CallExpr *CE) {
Ted Kremenekb63d8d82012-01-20 05:35:06 +0000682 if (!filter.check_UncheckedReturn)
683 return;
684
Ted Kremenek65a81a92009-08-28 00:08:09 +0000685 const FunctionDecl *FD = CE->getDirectCallee();
686 if (!FD)
687 return;
688
689 if (II_setid[0] == NULL) {
Ted Kremenek24650472009-09-02 02:47:41 +0000690 static const char * const identifiers[num_setids] = {
Ted Kremenek65a81a92009-08-28 00:08:09 +0000691 "setuid", "setgid", "seteuid", "setegid",
692 "setreuid", "setregid"
693 };
Mike Stump1eb44332009-09-09 15:08:12 +0000694
Ted Kremenek24650472009-09-02 02:47:41 +0000695 for (size_t i = 0; i < num_setids; i++)
Mike Stump1eb44332009-09-09 15:08:12 +0000696 II_setid[i] = &BR.getContext().Idents.get(identifiers[i]);
Ted Kremenek65a81a92009-08-28 00:08:09 +0000697 }
Mike Stump1eb44332009-09-09 15:08:12 +0000698
Ted Kremenek65a81a92009-08-28 00:08:09 +0000699 const IdentifierInfo *id = FD->getIdentifier();
700 size_t identifierid;
701
Ted Kremenek24650472009-09-02 02:47:41 +0000702 for (identifierid = 0; identifierid < num_setids; identifierid++)
Ted Kremenek65a81a92009-08-28 00:08:09 +0000703 if (id == II_setid[identifierid])
704 break;
705
Ted Kremenek24650472009-09-02 02:47:41 +0000706 if (identifierid >= num_setids)
Ted Kremenek65a81a92009-08-28 00:08:09 +0000707 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000708
Abramo Bagnara723df242010-12-14 22:11:44 +0000709 const FunctionProtoType *FTP
710 = dyn_cast<FunctionProtoType>(FD->getType().IgnoreParens());
Ted Kremenek65a81a92009-08-28 00:08:09 +0000711 if (!FTP)
712 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000713
Ted Kremeneka8187832009-08-28 00:24:55 +0000714 // Verify that the function takes one or two arguments (depending on
715 // the function).
Ted Kremenek65a81a92009-08-28 00:08:09 +0000716 if (FTP->getNumArgs() != (identifierid < 4 ? 1 : 2))
717 return;
718
719 // The arguments must be integers.
720 for (unsigned i = 0; i < FTP->getNumArgs(); i++)
721 if (! FTP->getArgType(i)->isIntegerType())
722 return;
723
724 // Issue a warning.
Ted Kremenek2c016762010-03-24 22:39:47 +0000725 llvm::SmallString<256> buf1;
726 llvm::raw_svector_ostream os1(buf1);
Benjamin Kramerb8989f22011-10-14 18:45:37 +0000727 os1 << "Return value is not checked in call to '" << *FD << '\'';
Ted Kremenek65a81a92009-08-28 00:08:09 +0000728
Ted Kremenek2c016762010-03-24 22:39:47 +0000729 llvm::SmallString<256> buf2;
730 llvm::raw_svector_ostream os2(buf2);
Benjamin Kramerb8989f22011-10-14 18:45:37 +0000731 os2 << "The return value from the call to '" << *FD
732 << "' is not checked. If an error occurs in '" << *FD
Ted Kremenek65a81a92009-08-28 00:08:09 +0000733 << "', the following code may execute with unexpected privileges";
734
735 SourceRange R = CE->getCallee()->getSourceRange();
Anna Zaks590dd8e2011-09-20 21:38:35 +0000736 PathDiagnosticLocation CELoc =
737 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
738 BR.EmitBasicReport(os1.str(), "Security", os2.str(), CELoc, &R, 1);
Ted Kremenek65a81a92009-08-28 00:08:09 +0000739}
740
741//===----------------------------------------------------------------------===//
Argyrios Kyrtzidis7dd445e2011-02-17 21:39:33 +0000742// SecuritySyntaxChecker
Ted Kremenekdbfb5f82009-07-23 01:07:19 +0000743//===----------------------------------------------------------------------===//
744
Argyrios Kyrtzidis7dd445e2011-02-17 21:39:33 +0000745namespace {
Argyrios Kyrtzidisec8605f2011-03-01 01:16:21 +0000746class SecuritySyntaxChecker : public Checker<check::ASTCodeBody> {
Argyrios Kyrtzidis7dd445e2011-02-17 21:39:33 +0000747public:
Ted Kremenek76a54242012-01-20 01:44:29 +0000748 ChecksFilter filter;
749
Argyrios Kyrtzidis7dd445e2011-02-17 21:39:33 +0000750 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
751 BugReporter &BR) const {
Ted Kremenek76a54242012-01-20 01:44:29 +0000752 WalkAST walker(BR, mgr.getAnalysisDeclContext(D), filter);
Argyrios Kyrtzidis7dd445e2011-02-17 21:39:33 +0000753 walker.Visit(D->getBody());
754 }
755};
756}
757
Ted Kremenek76a54242012-01-20 01:44:29 +0000758#define REGISTER_CHECKER(name) \
759void ento::register##name(CheckerManager &mgr) {\
760 mgr.registerChecker<SecuritySyntaxChecker>()->filter.check_##name = true;\
Ted Kremenekdbfb5f82009-07-23 01:07:19 +0000761}
Ted Kremenek76a54242012-01-20 01:44:29 +0000762
763REGISTER_CHECKER(gets)
764REGISTER_CHECKER(getpw)
Ted Kremenekb63d8d82012-01-20 05:35:06 +0000765REGISTER_CHECKER(mkstemp)
Ted Kremenek76a54242012-01-20 01:44:29 +0000766REGISTER_CHECKER(mktemp)
767REGISTER_CHECKER(strcpy)
768REGISTER_CHECKER(rand)
769REGISTER_CHECKER(vfork)
770REGISTER_CHECKER(FloatLoopCounter)
Ted Kremenekb63d8d82012-01-20 05:35:06 +0000771REGISTER_CHECKER(UncheckedReturn)
772
Ted Kremenek76a54242012-01-20 01:44:29 +0000773