Bug Summary

File:tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
Warning:line 305, column 25
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name CheckSecuritySyntaxOnly.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mthread-model posix -relaxed-aliasing -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -momit-leaf-frame-pointer -ffunction-sections -fdata-sections -resource-dir /usr/lib/llvm-9/lib/clang/9.0.0 -D CLANG_VENDOR="Debian " -D _DEBUG -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-9~svn362543/build-llvm/tools/clang/lib/StaticAnalyzer/Checkers -I /build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Checkers -I /build/llvm-toolchain-snapshot-9~svn362543/tools/clang/include -I /build/llvm-toolchain-snapshot-9~svn362543/build-llvm/tools/clang/include -I /build/llvm-toolchain-snapshot-9~svn362543/build-llvm/include -I /build/llvm-toolchain-snapshot-9~svn362543/include -U NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/x86_64-linux-gnu/c++/6.3.0 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/backward -internal-isystem /usr/include/clang/9.0.0/include/ -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-9/lib/clang/9.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-comment -std=c++11 -fdeprecated-macro -fdebug-compilation-dir /build/llvm-toolchain-snapshot-9~svn362543/build-llvm/tools/clang/lib/StaticAnalyzer/Checkers -fdebug-prefix-map=/build/llvm-toolchain-snapshot-9~svn362543=. -ferror-limit 19 -fmessage-length 0 -fvisibility-inlines-hidden -stack-protector 2 -fobjc-runtime=gcc -fno-common -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -o /tmp/scan-build-2019-06-05-060531-1271-1 -x c++ /build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp -faddrsig
1//==- CheckSecuritySyntaxOnly.cpp - Basic security checks --------*- C++ -*-==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines a set of flow-insensitive security checks.
10//
11//===----------------------------------------------------------------------===//
12
13#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
14#include "clang/AST/StmtVisitor.h"
15#include "clang/Analysis/AnalysisDeclContext.h"
16#include "clang/Basic/TargetInfo.h"
17#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
18#include "clang/StaticAnalyzer/Core/Checker.h"
19#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
20#include "llvm/ADT/SmallString.h"
21#include "llvm/ADT/StringSwitch.h"
22#include "llvm/Support/raw_ostream.h"
23
24using namespace clang;
25using namespace ento;
26
27static bool isArc4RandomAvailable(const ASTContext &Ctx) {
28 const llvm::Triple &T = Ctx.getTargetInfo().getTriple();
29 return T.getVendor() == llvm::Triple::Apple ||
30 T.getOS() == llvm::Triple::CloudABI ||
31 T.isOSFreeBSD() ||
32 T.isOSNetBSD() ||
33 T.isOSOpenBSD() ||
34 T.isOSDragonFly();
35}
36
37namespace {
38struct ChecksFilter {
39 DefaultBool check_bcmp;
40 DefaultBool check_bcopy;
41 DefaultBool check_bzero;
42 DefaultBool check_gets;
43 DefaultBool check_getpw;
44 DefaultBool check_mktemp;
45 DefaultBool check_mkstemp;
46 DefaultBool check_strcpy;
47 DefaultBool check_DeprecatedOrUnsafeBufferHandling;
48 DefaultBool check_rand;
49 DefaultBool check_vfork;
50 DefaultBool check_FloatLoopCounter;
51 DefaultBool check_UncheckedReturn;
52
53 CheckName checkName_bcmp;
54 CheckName checkName_bcopy;
55 CheckName checkName_bzero;
56 CheckName checkName_gets;
57 CheckName checkName_getpw;
58 CheckName checkName_mktemp;
59 CheckName checkName_mkstemp;
60 CheckName checkName_strcpy;
61 CheckName checkName_DeprecatedOrUnsafeBufferHandling;
62 CheckName checkName_rand;
63 CheckName checkName_vfork;
64 CheckName checkName_FloatLoopCounter;
65 CheckName checkName_UncheckedReturn;
66};
67
68class WalkAST : public StmtVisitor<WalkAST> {
69 BugReporter &BR;
70 AnalysisDeclContext* AC;
71 enum { num_setids = 6 };
72 IdentifierInfo *II_setid[num_setids];
73
74 const bool CheckRand;
75 const ChecksFilter &filter;
76
77public:
78 WalkAST(BugReporter &br, AnalysisDeclContext* ac,
79 const ChecksFilter &f)
80 : BR(br), AC(ac), II_setid(),
81 CheckRand(isArc4RandomAvailable(BR.getContext())),
82 filter(f) {}
83
84 // Statement visitor methods.
85 void VisitCallExpr(CallExpr *CE);
86 void VisitForStmt(ForStmt *S);
87 void VisitCompoundStmt (CompoundStmt *S);
88 void VisitStmt(Stmt *S) { VisitChildren(S); }
89
90 void VisitChildren(Stmt *S);
91
92 // Helpers.
93 bool checkCall_strCommon(const CallExpr *CE, const FunctionDecl *FD);
94
95 typedef void (WalkAST::*FnCheck)(const CallExpr *, const FunctionDecl *);
96
97 // Checker-specific methods.
98 void checkLoopConditionForFloat(const ForStmt *FS);
99 void checkCall_bcmp(const CallExpr *CE, const FunctionDecl *FD);
100 void checkCall_bcopy(const CallExpr *CE, const FunctionDecl *FD);
101 void checkCall_bzero(const CallExpr *CE, const FunctionDecl *FD);
102 void checkCall_gets(const CallExpr *CE, const FunctionDecl *FD);
103 void checkCall_getpw(const CallExpr *CE, const FunctionDecl *FD);
104 void checkCall_mktemp(const CallExpr *CE, const FunctionDecl *FD);
105 void checkCall_mkstemp(const CallExpr *CE, const FunctionDecl *FD);
106 void checkCall_strcpy(const CallExpr *CE, const FunctionDecl *FD);
107 void checkCall_strcat(const CallExpr *CE, const FunctionDecl *FD);
108 void checkDeprecatedOrUnsafeBufferHandling(const CallExpr *CE,
109 const FunctionDecl *FD);
110 void checkCall_rand(const CallExpr *CE, const FunctionDecl *FD);
111 void checkCall_random(const CallExpr *CE, const FunctionDecl *FD);
112 void checkCall_vfork(const CallExpr *CE, const FunctionDecl *FD);
113 void checkUncheckedReturnValue(CallExpr *CE);
114};
115} // end anonymous namespace
116
117//===----------------------------------------------------------------------===//
118// AST walking.
119//===----------------------------------------------------------------------===//
120
121void WalkAST::VisitChildren(Stmt *S) {
122 for (Stmt *Child : S->children())
123 if (Child)
124 Visit(Child);
125}
126
127void WalkAST::VisitCallExpr(CallExpr *CE) {
128 // Get the callee.
129 const FunctionDecl *FD = CE->getDirectCallee();
130
131 if (!FD)
132 return;
133
134 // Get the name of the callee. If it's a builtin, strip off the prefix.
135 IdentifierInfo *II = FD->getIdentifier();
136 if (!II) // if no identifier, not a simple C function
137 return;
138 StringRef Name = II->getName();
139 if (Name.startswith("__builtin_"))
140 Name = Name.substr(10);
141
142 // Set the evaluation function by switching on the callee name.
143 FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
144 .Case("bcmp", &WalkAST::checkCall_bcmp)
145 .Case("bcopy", &WalkAST::checkCall_bcopy)
146 .Case("bzero", &WalkAST::checkCall_bzero)
147 .Case("gets", &WalkAST::checkCall_gets)
148 .Case("getpw", &WalkAST::checkCall_getpw)
149 .Case("mktemp", &WalkAST::checkCall_mktemp)
150 .Case("mkstemp", &WalkAST::checkCall_mkstemp)
151 .Case("mkdtemp", &WalkAST::checkCall_mkstemp)
152 .Case("mkstemps", &WalkAST::checkCall_mkstemp)
153 .Cases("strcpy", "__strcpy_chk", &WalkAST::checkCall_strcpy)
154 .Cases("strcat", "__strcat_chk", &WalkAST::checkCall_strcat)
155 .Cases("sprintf", "vsprintf", "scanf", "wscanf", "fscanf", "fwscanf",
156 "vscanf", "vwscanf", "vfscanf", "vfwscanf",
157 &WalkAST::checkDeprecatedOrUnsafeBufferHandling)
158 .Cases("sscanf", "swscanf", "vsscanf", "vswscanf", "swprintf",
159 "snprintf", "vswprintf", "vsnprintf", "memcpy", "memmove",
160 &WalkAST::checkDeprecatedOrUnsafeBufferHandling)
161 .Cases("strncpy", "strncat", "memset",
162 &WalkAST::checkDeprecatedOrUnsafeBufferHandling)
163 .Case("drand48", &WalkAST::checkCall_rand)
164 .Case("erand48", &WalkAST::checkCall_rand)
165 .Case("jrand48", &WalkAST::checkCall_rand)
166 .Case("lrand48", &WalkAST::checkCall_rand)
167 .Case("mrand48", &WalkAST::checkCall_rand)
168 .Case("nrand48", &WalkAST::checkCall_rand)
169 .Case("lcong48", &WalkAST::checkCall_rand)
170 .Case("rand", &WalkAST::checkCall_rand)
171 .Case("rand_r", &WalkAST::checkCall_rand)
172 .Case("random", &WalkAST::checkCall_random)
173 .Case("vfork", &WalkAST::checkCall_vfork)
174 .Default(nullptr);
175
176 // If the callee isn't defined, it is not of security concern.
177 // Check and evaluate the call.
178 if (evalFunction)
179 (this->*evalFunction)(CE, FD);
180
181 // Recurse and check children.
182 VisitChildren(CE);
183}
184
185void WalkAST::VisitCompoundStmt(CompoundStmt *S) {
186 for (Stmt *Child : S->children())
187 if (Child) {
188 if (CallExpr *CE = dyn_cast<CallExpr>(Child))
189 checkUncheckedReturnValue(CE);
190 Visit(Child);
191 }
192}
193
194void WalkAST::VisitForStmt(ForStmt *FS) {
195 checkLoopConditionForFloat(FS);
1
Calling 'WalkAST::checkLoopConditionForFloat'
196
197 // Recurse and check children.
198 VisitChildren(FS);
199}
200
201//===----------------------------------------------------------------------===//
202// Check: floating point variable used as loop counter.
203// Originally: <rdar://problem/6336718>
204// Implements: CERT security coding advisory FLP-30.
205//===----------------------------------------------------------------------===//
206
207static const DeclRefExpr*
208getIncrementedVar(const Expr *expr, const VarDecl *x, const VarDecl *y) {
209 expr = expr->IgnoreParenCasts();
210
211 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(expr)) {
212 if (!(B->isAssignmentOp() || B->isCompoundAssignmentOp() ||
213 B->getOpcode() == BO_Comma))
214 return nullptr;
215
216 if (const DeclRefExpr *lhs = getIncrementedVar(B->getLHS(), x, y))
217 return lhs;
218
219 if (const DeclRefExpr *rhs = getIncrementedVar(B->getRHS(), x, y))
220 return rhs;
221
222 return nullptr;
223 }
224
225 if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(expr)) {
226 const NamedDecl *ND = DR->getDecl();
227 return ND == x || ND == y ? DR : nullptr;
228 }
229
230 if (const UnaryOperator *U = dyn_cast<UnaryOperator>(expr))
231 return U->isIncrementDecrementOp()
232 ? getIncrementedVar(U->getSubExpr(), x, y) : nullptr;
233
234 return nullptr;
235}
236
237/// CheckLoopConditionForFloat - This check looks for 'for' statements that
238/// use a floating point variable as a loop counter.
239/// CERT: FLP30-C, FLP30-CPP.
240///
241void WalkAST::checkLoopConditionForFloat(const ForStmt *FS) {
242 if (!filter.check_FloatLoopCounter)
2
Assuming the condition is false
3
Taking false branch
243 return;
244
245 // Does the loop have a condition?
246 const Expr *condition = FS->getCond();
247
248 if (!condition)
4
Assuming 'condition' is non-null
5
Taking false branch
249 return;
250
251 // Does the loop have an increment?
252 const Expr *increment = FS->getInc();
253
254 if (!increment)
6
Assuming 'increment' is non-null
7
Taking false branch
255 return;
256
257 // Strip away '()' and casts.
258 condition = condition->IgnoreParenCasts();
259 increment = increment->IgnoreParenCasts();
260
261 // Is the loop condition a comparison?
262 const BinaryOperator *B = dyn_cast<BinaryOperator>(condition);
263
264 if (!B)
8
Taking false branch
265 return;
266
267 // Is this a comparison?
268 if (!(B->isRelationalOp() || B->isEqualityOp()))
9
Taking false branch
269 return;
270
271 // Are we comparing variables?
272 const DeclRefExpr *drLHS =
273 dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParenLValueCasts());
274 const DeclRefExpr *drRHS =
275 dyn_cast<DeclRefExpr>(B->getRHS()->IgnoreParenLValueCasts());
276
277 // Does at least one of the variables have a floating point type?
278 drLHS = drLHS && drLHS->getType()->isRealFloatingType() ? drLHS : nullptr;
10
Assuming the condition is true
11
'?' condition is true
279 drRHS = drRHS && drRHS->getType()->isRealFloatingType() ? drRHS : nullptr;
12
Null pointer value stored to 'drRHS'
280
281 if (!drLHS && !drRHS)
282 return;
283
284 const VarDecl *vdLHS = drLHS ? dyn_cast<VarDecl>(drLHS->getDecl()) : nullptr;
13
'?' condition is true
285 const VarDecl *vdRHS = drRHS ? dyn_cast<VarDecl>(drRHS->getDecl()) : nullptr;
14
'?' condition is false
286
287 if (!vdLHS && !vdRHS)
288 return;
289
290 // Does either variable appear in increment?
291 const DeclRefExpr *drInc = getIncrementedVar(increment, vdLHS, vdRHS);
292
293 if (!drInc)
15
Assuming 'drInc' is non-null
16
Taking false branch
294 return;
295
296 // Emit the error. First figure out which DeclRefExpr in the condition
297 // referenced the compared variable.
298 assert(drInc->getDecl())((drInc->getDecl()) ? static_cast<void> (0) : __assert_fail
("drInc->getDecl()", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp"
, 298, __PRETTY_FUNCTION__))
;
17
Assuming the condition is true
18
'?' condition is true
299 const DeclRefExpr *drCond = vdLHS == drInc->getDecl() ? drLHS : drRHS;
19
Assuming the condition is false
20
'?' condition is false
21
'drCond' initialized to a null pointer value
300
301 SmallVector<SourceRange, 2> ranges;
302 SmallString<256> sbuf;
303 llvm::raw_svector_ostream os(sbuf);
304
305 os << "Variable '" << drCond->getDecl()->getName()
22
Called C++ object pointer is null
306 << "' with floating point type '" << drCond->getType().getAsString()
307 << "' should not be used as a loop counter";
308
309 ranges.push_back(drCond->getSourceRange());
310 ranges.push_back(drInc->getSourceRange());
311
312 const char *bugType = "Floating point variable used as loop counter";
313
314 PathDiagnosticLocation FSLoc =
315 PathDiagnosticLocation::createBegin(FS, BR.getSourceManager(), AC);
316 BR.EmitBasicReport(AC->getDecl(), filter.checkName_FloatLoopCounter,
317 bugType, "Security", os.str(),
318 FSLoc, ranges);
319}
320
321//===----------------------------------------------------------------------===//
322// Check: Any use of bcmp.
323// CWE-477: Use of Obsolete Functions
324// bcmp was deprecated in POSIX.1-2008
325//===----------------------------------------------------------------------===//
326
327void WalkAST::checkCall_bcmp(const CallExpr *CE, const FunctionDecl *FD) {
328 if (!filter.check_bcmp)
329 return;
330
331 const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
332 if (!FPT)
333 return;
334
335 // Verify that the function takes three arguments.
336 if (FPT->getNumParams() != 3)
337 return;
338
339 for (int i = 0; i < 2; i++) {
340 // Verify the first and second argument type is void*.
341 const PointerType *PT = FPT->getParamType(i)->getAs<PointerType>();
342 if (!PT)
343 return;
344
345 if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().VoidTy)
346 return;
347 }
348
349 // Verify the third argument type is integer.
350 if (!FPT->getParamType(2)->isIntegralOrUnscopedEnumerationType())
351 return;
352
353 // Issue a warning.
354 PathDiagnosticLocation CELoc =
355 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
356 BR.EmitBasicReport(AC->getDecl(), filter.checkName_bcmp,
357 "Use of deprecated function in call to 'bcmp()'",
358 "Security",
359 "The bcmp() function is obsoleted by memcmp().",
360 CELoc, CE->getCallee()->getSourceRange());
361}
362
363//===----------------------------------------------------------------------===//
364// Check: Any use of bcopy.
365// CWE-477: Use of Obsolete Functions
366// bcopy was deprecated in POSIX.1-2008
367//===----------------------------------------------------------------------===//
368
369void WalkAST::checkCall_bcopy(const CallExpr *CE, const FunctionDecl *FD) {
370 if (!filter.check_bcopy)
371 return;
372
373 const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
374 if (!FPT)
375 return;
376
377 // Verify that the function takes three arguments.
378 if (FPT->getNumParams() != 3)
379 return;
380
381 for (int i = 0; i < 2; i++) {
382 // Verify the first and second argument type is void*.
383 const PointerType *PT = FPT->getParamType(i)->getAs<PointerType>();
384 if (!PT)
385 return;
386
387 if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().VoidTy)
388 return;
389 }
390
391 // Verify the third argument type is integer.
392 if (!FPT->getParamType(2)->isIntegralOrUnscopedEnumerationType())
393 return;
394
395 // Issue a warning.
396 PathDiagnosticLocation CELoc =
397 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
398 BR.EmitBasicReport(AC->getDecl(), filter.checkName_bcopy,
399 "Use of deprecated function in call to 'bcopy()'",
400 "Security",
401 "The bcopy() function is obsoleted by memcpy() "
402 "or memmove().",
403 CELoc, CE->getCallee()->getSourceRange());
404}
405
406//===----------------------------------------------------------------------===//
407// Check: Any use of bzero.
408// CWE-477: Use of Obsolete Functions
409// bzero was deprecated in POSIX.1-2008
410//===----------------------------------------------------------------------===//
411
412void WalkAST::checkCall_bzero(const CallExpr *CE, const FunctionDecl *FD) {
413 if (!filter.check_bzero)
414 return;
415
416 const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
417 if (!FPT)
418 return;
419
420 // Verify that the function takes two arguments.
421 if (FPT->getNumParams() != 2)
422 return;
423
424 // Verify the first argument type is void*.
425 const PointerType *PT = FPT->getParamType(0)->getAs<PointerType>();
426 if (!PT)
427 return;
428
429 if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().VoidTy)
430 return;
431
432 // Verify the second argument type is integer.
433 if (!FPT->getParamType(1)->isIntegralOrUnscopedEnumerationType())
434 return;
435
436 // Issue a warning.
437 PathDiagnosticLocation CELoc =
438 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
439 BR.EmitBasicReport(AC->getDecl(), filter.checkName_bzero,
440 "Use of deprecated function in call to 'bzero()'",
441 "Security",
442 "The bzero() function is obsoleted by memset().",
443 CELoc, CE->getCallee()->getSourceRange());
444}
445
446
447//===----------------------------------------------------------------------===//
448// Check: Any use of 'gets' is insecure.
449// Originally: <rdar://problem/6335715>
450// Implements (part of): 300-BSI (buildsecurityin.us-cert.gov)
451// CWE-242: Use of Inherently Dangerous Function
452//===----------------------------------------------------------------------===//
453
454void WalkAST::checkCall_gets(const CallExpr *CE, const FunctionDecl *FD) {
455 if (!filter.check_gets)
456 return;
457
458 const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
459 if (!FPT)
460 return;
461
462 // Verify that the function takes a single argument.
463 if (FPT->getNumParams() != 1)
464 return;
465
466 // Is the argument a 'char*'?
467 const PointerType *PT = FPT->getParamType(0)->getAs<PointerType>();
468 if (!PT)
469 return;
470
471 if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
472 return;
473
474 // Issue a warning.
475 PathDiagnosticLocation CELoc =
476 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
477 BR.EmitBasicReport(AC->getDecl(), filter.checkName_gets,
478 "Potential buffer overflow in call to 'gets'",
479 "Security",
480 "Call to function 'gets' is extremely insecure as it can "
481 "always result in a buffer overflow",
482 CELoc, CE->getCallee()->getSourceRange());
483}
484
485//===----------------------------------------------------------------------===//
486// Check: Any use of 'getpwd' is insecure.
487// CWE-477: Use of Obsolete Functions
488//===----------------------------------------------------------------------===//
489
490void WalkAST::checkCall_getpw(const CallExpr *CE, const FunctionDecl *FD) {
491 if (!filter.check_getpw)
492 return;
493
494 const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
495 if (!FPT)
496 return;
497
498 // Verify that the function takes two arguments.
499 if (FPT->getNumParams() != 2)
500 return;
501
502 // Verify the first argument type is integer.
503 if (!FPT->getParamType(0)->isIntegralOrUnscopedEnumerationType())
504 return;
505
506 // Verify the second argument type is char*.
507 const PointerType *PT = FPT->getParamType(1)->getAs<PointerType>();
508 if (!PT)
509 return;
510
511 if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
512 return;
513
514 // Issue a warning.
515 PathDiagnosticLocation CELoc =
516 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
517 BR.EmitBasicReport(AC->getDecl(), filter.checkName_getpw,
518 "Potential buffer overflow in call to 'getpw'",
519 "Security",
520 "The getpw() function is dangerous as it may overflow the "
521 "provided buffer. It is obsoleted by getpwuid().",
522 CELoc, CE->getCallee()->getSourceRange());
523}
524
525//===----------------------------------------------------------------------===//
526// Check: Any use of 'mktemp' is insecure. It is obsoleted by mkstemp().
527// CWE-377: Insecure Temporary File
528//===----------------------------------------------------------------------===//
529
530void WalkAST::checkCall_mktemp(const CallExpr *CE, const FunctionDecl *FD) {
531 if (!filter.check_mktemp) {
532 // Fall back to the security check of looking for enough 'X's in the
533 // format string, since that is a less severe warning.
534 checkCall_mkstemp(CE, FD);
535 return;
536 }
537
538 const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
539 if(!FPT)
540 return;
541
542 // Verify that the function takes a single argument.
543 if (FPT->getNumParams() != 1)
544 return;
545
546 // Verify that the argument is Pointer Type.
547 const PointerType *PT = FPT->getParamType(0)->getAs<PointerType>();
548 if (!PT)
549 return;
550
551 // Verify that the argument is a 'char*'.
552 if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
553 return;
554
555 // Issue a warning.
556 PathDiagnosticLocation CELoc =
557 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
558 BR.EmitBasicReport(AC->getDecl(), filter.checkName_mktemp,
559 "Potential insecure temporary file in call 'mktemp'",
560 "Security",
561 "Call to function 'mktemp' is insecure as it always "
562 "creates or uses insecure temporary file. Use 'mkstemp' "
563 "instead",
564 CELoc, CE->getCallee()->getSourceRange());
565}
566
567//===----------------------------------------------------------------------===//
568// Check: Use of 'mkstemp', 'mktemp', 'mkdtemp' should contain at least 6 X's.
569//===----------------------------------------------------------------------===//
570
571void WalkAST::checkCall_mkstemp(const CallExpr *CE, const FunctionDecl *FD) {
572 if (!filter.check_mkstemp)
573 return;
574
575 StringRef Name = FD->getIdentifier()->getName();
576 std::pair<signed, signed> ArgSuffix =
577 llvm::StringSwitch<std::pair<signed, signed> >(Name)
578 .Case("mktemp", std::make_pair(0,-1))
579 .Case("mkstemp", std::make_pair(0,-1))
580 .Case("mkdtemp", std::make_pair(0,-1))
581 .Case("mkstemps", std::make_pair(0,1))
582 .Default(std::make_pair(-1, -1));
583
584 assert(ArgSuffix.first >= 0 && "Unsupported function")((ArgSuffix.first >= 0 && "Unsupported function") ?
static_cast<void> (0) : __assert_fail ("ArgSuffix.first >= 0 && \"Unsupported function\""
, "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp"
, 584, __PRETTY_FUNCTION__))
;
585
586 // Check if the number of arguments is consistent with out expectations.
587 unsigned numArgs = CE->getNumArgs();
588 if ((signed) numArgs <= ArgSuffix.first)
589 return;
590
591 const StringLiteral *strArg =
592 dyn_cast<StringLiteral>(CE->getArg((unsigned)ArgSuffix.first)
593 ->IgnoreParenImpCasts());
594
595 // Currently we only handle string literals. It is possible to do better,
596 // either by looking at references to const variables, or by doing real
597 // flow analysis.
598 if (!strArg || strArg->getCharByteWidth() != 1)
599 return;
600
601 // Count the number of X's, taking into account a possible cutoff suffix.
602 StringRef str = strArg->getString();
603 unsigned numX = 0;
604 unsigned n = str.size();
605
606 // Take into account the suffix.
607 unsigned suffix = 0;
608 if (ArgSuffix.second >= 0) {
609 const Expr *suffixEx = CE->getArg((unsigned)ArgSuffix.second);
610 Expr::EvalResult EVResult;
611 if (!suffixEx->EvaluateAsInt(EVResult, BR.getContext()))
612 return;
613 llvm::APSInt Result = EVResult.Val.getInt();
614 // FIXME: Issue a warning.
615 if (Result.isNegative())
616 return;
617 suffix = (unsigned) Result.getZExtValue();
618 n = (n > suffix) ? n - suffix : 0;
619 }
620
621 for (unsigned i = 0; i < n; ++i)
622 if (str[i] == 'X') ++numX;
623
624 if (numX >= 6)
625 return;
626
627 // Issue a warning.
628 PathDiagnosticLocation CELoc =
629 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
630 SmallString<512> buf;
631 llvm::raw_svector_ostream out(buf);
632 out << "Call to '" << Name << "' should have at least 6 'X's in the"
633 " format string to be secure (" << numX << " 'X'";
634 if (numX != 1)
635 out << 's';
636 out << " seen";
637 if (suffix) {
638 out << ", " << suffix << " character";
639 if (suffix > 1)
640 out << 's';
641 out << " used as a suffix";
642 }
643 out << ')';
644 BR.EmitBasicReport(AC->getDecl(), filter.checkName_mkstemp,
645 "Insecure temporary file creation", "Security",
646 out.str(), CELoc, strArg->getSourceRange());
647}
648
649//===----------------------------------------------------------------------===//
650// Check: Any use of 'strcpy' is insecure.
651//
652// CWE-119: Improper Restriction of Operations within
653// the Bounds of a Memory Buffer
654//===----------------------------------------------------------------------===//
655
656void WalkAST::checkCall_strcpy(const CallExpr *CE, const FunctionDecl *FD) {
657 if (!filter.check_strcpy)
658 return;
659
660 if (!checkCall_strCommon(CE, FD))
661 return;
662
663 const auto *Target = CE->getArg(0)->IgnoreImpCasts(),
664 *Source = CE->getArg(1)->IgnoreImpCasts();
665
666 if (const auto *Array = dyn_cast<ConstantArrayType>(Target->getType())) {
667 uint64_t ArraySize = BR.getContext().getTypeSize(Array) / 8;
668 if (const auto *String = dyn_cast<StringLiteral>(Source)) {
669 if (ArraySize >= String->getLength() + 1)
670 return;
671 }
672 }
673
674 // Issue a warning.
675 PathDiagnosticLocation CELoc =
676 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
677 BR.EmitBasicReport(AC->getDecl(), filter.checkName_strcpy,
678 "Potential insecure memory buffer bounds restriction in "
679 "call 'strcpy'",
680 "Security",
681 "Call to function 'strcpy' is insecure as it does not "
682 "provide bounding of the memory buffer. Replace "
683 "unbounded copy functions with analogous functions that "
684 "support length arguments such as 'strlcpy'. CWE-119.",
685 CELoc, CE->getCallee()->getSourceRange());
686}
687
688//===----------------------------------------------------------------------===//
689// Check: Any use of 'strcat' is insecure.
690//
691// CWE-119: Improper Restriction of Operations within
692// the Bounds of a Memory Buffer
693//===----------------------------------------------------------------------===//
694
695void WalkAST::checkCall_strcat(const CallExpr *CE, const FunctionDecl *FD) {
696 if (!filter.check_strcpy)
697 return;
698
699 if (!checkCall_strCommon(CE, FD))
700 return;
701
702 // Issue a warning.
703 PathDiagnosticLocation CELoc =
704 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
705 BR.EmitBasicReport(AC->getDecl(), filter.checkName_strcpy,
706 "Potential insecure memory buffer bounds restriction in "
707 "call 'strcat'",
708 "Security",
709 "Call to function 'strcat' is insecure as it does not "
710 "provide bounding of the memory buffer. Replace "
711 "unbounded copy functions with analogous functions that "
712 "support length arguments such as 'strlcat'. CWE-119.",
713 CELoc, CE->getCallee()->getSourceRange());
714}
715
716//===----------------------------------------------------------------------===//
717// Check: Any use of 'sprintf', 'vsprintf', 'scanf', 'wscanf', 'fscanf',
718// 'fwscanf', 'vscanf', 'vwscanf', 'vfscanf', 'vfwscanf', 'sscanf',
719// 'swscanf', 'vsscanf', 'vswscanf', 'swprintf', 'snprintf', 'vswprintf',
720// 'vsnprintf', 'memcpy', 'memmove', 'strncpy', 'strncat', 'memset'
721// is deprecated since C11.
722//
723// Use of 'sprintf', 'vsprintf', 'scanf', 'wscanf','fscanf',
724// 'fwscanf', 'vscanf', 'vwscanf', 'vfscanf', 'vfwscanf', 'sscanf',
725// 'swscanf', 'vsscanf', 'vswscanf' without buffer limitations
726// is insecure.
727//
728// CWE-119: Improper Restriction of Operations within
729// the Bounds of a Memory Buffer
730//===----------------------------------------------------------------------===//
731
732void WalkAST::checkDeprecatedOrUnsafeBufferHandling(const CallExpr *CE,
733 const FunctionDecl *FD) {
734 if (!filter.check_DeprecatedOrUnsafeBufferHandling)
735 return;
736
737 if (!BR.getContext().getLangOpts().C11)
738 return;
739
740 // Issue a warning. ArgIndex == -1: Deprecated but not unsafe (has size
741 // restrictions).
742 enum { DEPR_ONLY = -1, UNKNOWN_CALL = -2 };
743
744 StringRef Name = FD->getIdentifier()->getName();
745 if (Name.startswith("__builtin_"))
746 Name = Name.substr(10);
747
748 int ArgIndex =
749 llvm::StringSwitch<int>(Name)
750 .Cases("scanf", "wscanf", "vscanf", "vwscanf", 0)
751 .Cases("sprintf", "vsprintf", "fscanf", "fwscanf", "vfscanf",
752 "vfwscanf", "sscanf", "swscanf", "vsscanf", "vswscanf", 1)
753 .Cases("swprintf", "snprintf", "vswprintf", "vsnprintf", "memcpy",
754 "memmove", "memset", "strncpy", "strncat", DEPR_ONLY)
755 .Default(UNKNOWN_CALL);
756
757 assert(ArgIndex != UNKNOWN_CALL && "Unsupported function")((ArgIndex != UNKNOWN_CALL && "Unsupported function")
? static_cast<void> (0) : __assert_fail ("ArgIndex != UNKNOWN_CALL && \"Unsupported function\""
, "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp"
, 757, __PRETTY_FUNCTION__))
;
758 bool BoundsProvided = ArgIndex == DEPR_ONLY;
759
760 if (!BoundsProvided) {
761 // Currently we only handle (not wide) string literals. It is possible to do
762 // better, either by looking at references to const variables, or by doing
763 // real flow analysis.
764 auto FormatString =
765 dyn_cast<StringLiteral>(CE->getArg(ArgIndex)->IgnoreParenImpCasts());
766 if (FormatString &&
767 FormatString->getString().find("%s") == StringRef::npos &&
768 FormatString->getString().find("%[") == StringRef::npos)
769 BoundsProvided = true;
770 }
771
772 SmallString<128> Buf1;
773 SmallString<512> Buf2;
774 llvm::raw_svector_ostream Out1(Buf1);
775 llvm::raw_svector_ostream Out2(Buf2);
776
777 Out1 << "Potential insecure memory buffer bounds restriction in call '"
778 << Name << "'";
779 Out2 << "Call to function '" << Name
780 << "' is insecure as it does not provide ";
781
782 if (!BoundsProvided) {
783 Out2 << "bounding of the memory buffer or ";
784 }
785
786 Out2 << "security checks introduced "
787 "in the C11 standard. Replace with analogous functions that "
788 "support length arguments or provides boundary checks such as '"
789 << Name << "_s' in case of C11";
790
791 PathDiagnosticLocation CELoc =
792 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
793 BR.EmitBasicReport(AC->getDecl(),
794 filter.checkName_DeprecatedOrUnsafeBufferHandling,
795 Out1.str(), "Security", Out2.str(), CELoc,
796 CE->getCallee()->getSourceRange());
797}
798
799//===----------------------------------------------------------------------===//
800// Common check for str* functions with no bounds parameters.
801//===----------------------------------------------------------------------===//
802
803bool WalkAST::checkCall_strCommon(const CallExpr *CE, const FunctionDecl *FD) {
804 const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
805 if (!FPT)
806 return false;
807
808 // Verify the function takes two arguments, three in the _chk version.
809 int numArgs = FPT->getNumParams();
810 if (numArgs != 2 && numArgs != 3)
811 return false;
812
813 // Verify the type for both arguments.
814 for (int i = 0; i < 2; i++) {
815 // Verify that the arguments are pointers.
816 const PointerType *PT = FPT->getParamType(i)->getAs<PointerType>();
817 if (!PT)
818 return false;
819
820 // Verify that the argument is a 'char*'.
821 if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
822 return false;
823 }
824
825 return true;
826}
827
828//===----------------------------------------------------------------------===//
829// Check: Linear congruent random number generators should not be used
830// Originally: <rdar://problem/63371000>
831// CWE-338: Use of cryptographically weak prng
832//===----------------------------------------------------------------------===//
833
834void WalkAST::checkCall_rand(const CallExpr *CE, const FunctionDecl *FD) {
835 if (!filter.check_rand || !CheckRand)
836 return;
837
838 const FunctionProtoType *FTP = FD->getType()->getAs<FunctionProtoType>();
839 if (!FTP)
840 return;
841
842 if (FTP->getNumParams() == 1) {
843 // Is the argument an 'unsigned short *'?
844 // (Actually any integer type is allowed.)
845 const PointerType *PT = FTP->getParamType(0)->getAs<PointerType>();
846 if (!PT)
847 return;
848
849 if (! PT->getPointeeType()->isIntegralOrUnscopedEnumerationType())
850 return;
851 } else if (FTP->getNumParams() != 0)
852 return;
853
854 // Issue a warning.
855 SmallString<256> buf1;
856 llvm::raw_svector_ostream os1(buf1);
857 os1 << '\'' << *FD << "' is a poor random number generator";
858
859 SmallString<256> buf2;
860 llvm::raw_svector_ostream os2(buf2);
861 os2 << "Function '" << *FD
862 << "' is obsolete because it implements a poor random number generator."
863 << " Use 'arc4random' instead";
864
865 PathDiagnosticLocation CELoc =
866 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
867 BR.EmitBasicReport(AC->getDecl(), filter.checkName_rand, os1.str(),
868 "Security", os2.str(), CELoc,
869 CE->getCallee()->getSourceRange());
870}
871
872//===----------------------------------------------------------------------===//
873// Check: 'random' should not be used
874// Originally: <rdar://problem/63371000>
875//===----------------------------------------------------------------------===//
876
877void WalkAST::checkCall_random(const CallExpr *CE, const FunctionDecl *FD) {
878 if (!CheckRand || !filter.check_rand)
879 return;
880
881 const FunctionProtoType *FTP = FD->getType()->getAs<FunctionProtoType>();
882 if (!FTP)
883 return;
884
885 // Verify that the function takes no argument.
886 if (FTP->getNumParams() != 0)
887 return;
888
889 // Issue a warning.
890 PathDiagnosticLocation CELoc =
891 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
892 BR.EmitBasicReport(AC->getDecl(), filter.checkName_rand,
893 "'random' is not a secure random number generator",
894 "Security",
895 "The 'random' function produces a sequence of values that "
896 "an adversary may be able to predict. Use 'arc4random' "
897 "instead", CELoc, CE->getCallee()->getSourceRange());
898}
899
900//===----------------------------------------------------------------------===//
901// Check: 'vfork' should not be used.
902// POS33-C: Do not use vfork().
903//===----------------------------------------------------------------------===//
904
905void WalkAST::checkCall_vfork(const CallExpr *CE, const FunctionDecl *FD) {
906 if (!filter.check_vfork)
907 return;
908
909 // All calls to vfork() are insecure, issue a warning.
910 PathDiagnosticLocation CELoc =
911 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
912 BR.EmitBasicReport(AC->getDecl(), filter.checkName_vfork,
913 "Potential insecure implementation-specific behavior in "
914 "call 'vfork'",
915 "Security",
916 "Call to function 'vfork' is insecure as it can lead to "
917 "denial of service situations in the parent process. "
918 "Replace calls to vfork with calls to the safer "
919 "'posix_spawn' function",
920 CELoc, CE->getCallee()->getSourceRange());
921}
922
923//===----------------------------------------------------------------------===//
924// Check: Should check whether privileges are dropped successfully.
925// Originally: <rdar://problem/6337132>
926//===----------------------------------------------------------------------===//
927
928void WalkAST::checkUncheckedReturnValue(CallExpr *CE) {
929 if (!filter.check_UncheckedReturn)
930 return;
931
932 const FunctionDecl *FD = CE->getDirectCallee();
933 if (!FD)
934 return;
935
936 if (II_setid[0] == nullptr) {
937 static const char * const identifiers[num_setids] = {
938 "setuid", "setgid", "seteuid", "setegid",
939 "setreuid", "setregid"
940 };
941
942 for (size_t i = 0; i < num_setids; i++)
943 II_setid[i] = &BR.getContext().Idents.get(identifiers[i]);
944 }
945
946 const IdentifierInfo *id = FD->getIdentifier();
947 size_t identifierid;
948
949 for (identifierid = 0; identifierid < num_setids; identifierid++)
950 if (id == II_setid[identifierid])
951 break;
952
953 if (identifierid >= num_setids)
954 return;
955
956 const FunctionProtoType *FTP = FD->getType()->getAs<FunctionProtoType>();
957 if (!FTP)
958 return;
959
960 // Verify that the function takes one or two arguments (depending on
961 // the function).
962 if (FTP->getNumParams() != (identifierid < 4 ? 1 : 2))
963 return;
964
965 // The arguments must be integers.
966 for (unsigned i = 0; i < FTP->getNumParams(); i++)
967 if (!FTP->getParamType(i)->isIntegralOrUnscopedEnumerationType())
968 return;
969
970 // Issue a warning.
971 SmallString<256> buf1;
972 llvm::raw_svector_ostream os1(buf1);
973 os1 << "Return value is not checked in call to '" << *FD << '\'';
974
975 SmallString<256> buf2;
976 llvm::raw_svector_ostream os2(buf2);
977 os2 << "The return value from the call to '" << *FD
978 << "' is not checked. If an error occurs in '" << *FD
979 << "', the following code may execute with unexpected privileges";
980
981 PathDiagnosticLocation CELoc =
982 PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
983 BR.EmitBasicReport(AC->getDecl(), filter.checkName_UncheckedReturn, os1.str(),
984 "Security", os2.str(), CELoc,
985 CE->getCallee()->getSourceRange());
986}
987
988//===----------------------------------------------------------------------===//
989// SecuritySyntaxChecker
990//===----------------------------------------------------------------------===//
991
992namespace {
993class SecuritySyntaxChecker : public Checker<check::ASTCodeBody> {
994public:
995 ChecksFilter filter;
996
997 void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
998 BugReporter &BR) const {
999 WalkAST walker(BR, mgr.getAnalysisDeclContext(D), filter);
1000 walker.Visit(D->getBody());
1001 }
1002};
1003}
1004
1005void ento::registerSecuritySyntaxChecker(CheckerManager &mgr) {
1006 mgr.registerChecker<SecuritySyntaxChecker>();
1007}
1008
1009bool ento::shouldRegisterSecuritySyntaxChecker(const LangOptions &LO) {
1010 return true;
1011}
1012
1013#define REGISTER_CHECKER(name)void ento::registername(CheckerManager &mgr) { SecuritySyntaxChecker
*checker = mgr.getChecker<SecuritySyntaxChecker>(); checker
->filter.check_name = true; checker->filter.checkName_name
= mgr.getCurrentCheckName(); } bool ento::shouldRegistername
(const LangOptions &LO) { return true; }
\
1014 void ento::register##name(CheckerManager &mgr) { \
1015 SecuritySyntaxChecker *checker = mgr.getChecker<SecuritySyntaxChecker>(); \
1016 checker->filter.check_##name = true; \
1017 checker->filter.checkName_##name = mgr.getCurrentCheckName(); \
1018 } \
1019 \
1020 bool ento::shouldRegister##name(const LangOptions &LO) { \
1021 return true; \
1022 }
1023
1024REGISTER_CHECKER(bcmp)void ento::registerbcmp(CheckerManager &mgr) { SecuritySyntaxChecker
*checker = mgr.getChecker<SecuritySyntaxChecker>(); checker
->filter.check_bcmp = true; checker->filter.checkName_bcmp
= mgr.getCurrentCheckName(); } bool ento::shouldRegisterbcmp
(const LangOptions &LO) { return true; }
1025REGISTER_CHECKER(bcopy)void ento::registerbcopy(CheckerManager &mgr) { SecuritySyntaxChecker
*checker = mgr.getChecker<SecuritySyntaxChecker>(); checker
->filter.check_bcopy = true; checker->filter.checkName_bcopy
= mgr.getCurrentCheckName(); } bool ento::shouldRegisterbcopy
(const LangOptions &LO) { return true; }
1026REGISTER_CHECKER(bzero)void ento::registerbzero(CheckerManager &mgr) { SecuritySyntaxChecker
*checker = mgr.getChecker<SecuritySyntaxChecker>(); checker
->filter.check_bzero = true; checker->filter.checkName_bzero
= mgr.getCurrentCheckName(); } bool ento::shouldRegisterbzero
(const LangOptions &LO) { return true; }
1027REGISTER_CHECKER(gets)void ento::registergets(CheckerManager &mgr) { SecuritySyntaxChecker
*checker = mgr.getChecker<SecuritySyntaxChecker>(); checker
->filter.check_gets = true; checker->filter.checkName_gets
= mgr.getCurrentCheckName(); } bool ento::shouldRegistergets
(const LangOptions &LO) { return true; }
1028REGISTER_CHECKER(getpw)void ento::registergetpw(CheckerManager &mgr) { SecuritySyntaxChecker
*checker = mgr.getChecker<SecuritySyntaxChecker>(); checker
->filter.check_getpw = true; checker->filter.checkName_getpw
= mgr.getCurrentCheckName(); } bool ento::shouldRegistergetpw
(const LangOptions &LO) { return true; }
1029REGISTER_CHECKER(mkstemp)void ento::registermkstemp(CheckerManager &mgr) { SecuritySyntaxChecker
*checker = mgr.getChecker<SecuritySyntaxChecker>(); checker
->filter.check_mkstemp = true; checker->filter.checkName_mkstemp
= mgr.getCurrentCheckName(); } bool ento::shouldRegistermkstemp
(const LangOptions &LO) { return true; }
1030REGISTER_CHECKER(mktemp)void ento::registermktemp(CheckerManager &mgr) { SecuritySyntaxChecker
*checker = mgr.getChecker<SecuritySyntaxChecker>(); checker
->filter.check_mktemp = true; checker->filter.checkName_mktemp
= mgr.getCurrentCheckName(); } bool ento::shouldRegistermktemp
(const LangOptions &LO) { return true; }
1031REGISTER_CHECKER(strcpy)void ento::registerstrcpy(CheckerManager &mgr) { SecuritySyntaxChecker
*checker = mgr.getChecker<SecuritySyntaxChecker>(); checker
->filter.check_strcpy = true; checker->filter.checkName_strcpy
= mgr.getCurrentCheckName(); } bool ento::shouldRegisterstrcpy
(const LangOptions &LO) { return true; }
1032REGISTER_CHECKER(rand)void ento::registerrand(CheckerManager &mgr) { SecuritySyntaxChecker
*checker = mgr.getChecker<SecuritySyntaxChecker>(); checker
->filter.check_rand = true; checker->filter.checkName_rand
= mgr.getCurrentCheckName(); } bool ento::shouldRegisterrand
(const LangOptions &LO) { return true; }
1033REGISTER_CHECKER(vfork)void ento::registervfork(CheckerManager &mgr) { SecuritySyntaxChecker
*checker = mgr.getChecker<SecuritySyntaxChecker>(); checker
->filter.check_vfork = true; checker->filter.checkName_vfork
= mgr.getCurrentCheckName(); } bool ento::shouldRegistervfork
(const LangOptions &LO) { return true; }
1034REGISTER_CHECKER(FloatLoopCounter)void ento::registerFloatLoopCounter(CheckerManager &mgr) {
SecuritySyntaxChecker *checker = mgr.getChecker<SecuritySyntaxChecker
>(); checker->filter.check_FloatLoopCounter = true; checker
->filter.checkName_FloatLoopCounter = mgr.getCurrentCheckName
(); } bool ento::shouldRegisterFloatLoopCounter(const LangOptions
&LO) { return true; }
1035REGISTER_CHECKER(UncheckedReturn)void ento::registerUncheckedReturn(CheckerManager &mgr) {
SecuritySyntaxChecker *checker = mgr.getChecker<SecuritySyntaxChecker
>(); checker->filter.check_UncheckedReturn = true; checker
->filter.checkName_UncheckedReturn = mgr.getCurrentCheckName
(); } bool ento::shouldRegisterUncheckedReturn(const LangOptions
&LO) { return true; }
1036REGISTER_CHECKER(DeprecatedOrUnsafeBufferHandling)void ento::registerDeprecatedOrUnsafeBufferHandling(CheckerManager
&mgr) { SecuritySyntaxChecker *checker = mgr.getChecker<
SecuritySyntaxChecker>(); checker->filter.check_DeprecatedOrUnsafeBufferHandling
= true; checker->filter.checkName_DeprecatedOrUnsafeBufferHandling
= mgr.getCurrentCheckName(); } bool ento::shouldRegisterDeprecatedOrUnsafeBufferHandling
(const LangOptions &LO) { return true; }