Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
Line
Count
Source (jump to first uncovered line)
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
24
using namespace clang;
25
using namespace ento;
26
27
174
static bool isArc4RandomAvailable(const ASTContext &Ctx) {
28
174
  const llvm::Triple &T = Ctx.getTargetInfo().getTriple();
29
174
  return T.getVendor() == llvm::Triple::Apple ||
30
174
         
T.getOS() == llvm::Triple::CloudABI77
||
31
174
         
T.isOSFreeBSD()1
||
32
174
         
T.isOSNetBSD()1
||
33
174
         
T.isOSOpenBSD()1
||
34
174
         
T.isOSDragonFly()1
;
35
174
}
36
37
namespace {
38
struct 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
68
class 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
77
public:
78
  WalkAST(BugReporter &br, AnalysisDeclContext* ac,
79
          const ChecksFilter &f)
80
  : BR(br), AC(ac), II_setid(),
81
    CheckRand(isArc4RandomAvailable(BR.getContext())),
82
174
    filter(f) {}
83
84
  // Statement visitor methods.
85
  void VisitCallExpr(CallExpr *CE);
86
  void VisitForStmt(ForStmt *S);
87
  void VisitCompoundStmt (CompoundStmt *S);
88
5.04k
  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
121
5.73k
void WalkAST::VisitChildren(Stmt *S) {
122
5.73k
  for (Stmt *Child : S->children())
123
4.95k
    if (Child)
124
4.88k
      Visit(Child);
125
5.73k
}
126
127
631
void WalkAST::VisitCallExpr(CallExpr *CE) {
128
631
  // Get the callee.
129
631
  const FunctionDecl *FD = CE->getDirectCallee();
130
631
131
631
  if (!FD)
132
0
    return;
133
631
134
631
  // Get the name of the callee. If it's a builtin, strip off the prefix.
135
631
  IdentifierInfo *II = FD->getIdentifier();
136
631
  if (!II)   // if no identifier, not a simple C function
137
0
    return;
138
631
  StringRef Name = II->getName();
139
631
  if (Name.startswith("__builtin_"))
140
45
    Name = Name.substr(10);
141
631
142
631
  // Set the evaluation function by switching on the callee name.
143
631
  FnCheck evalFunction = llvm::StringSwitch<FnCheck>(Name)
144
631
    .Case("bcmp", &WalkAST::checkCall_bcmp)
145
631
    .Case("bcopy", &WalkAST::checkCall_bcopy)
146
631
    .Case("bzero", &WalkAST::checkCall_bzero)
147
631
    .Case("gets", &WalkAST::checkCall_gets)
148
631
    .Case("getpw", &WalkAST::checkCall_getpw)
149
631
    .Case("mktemp", &WalkAST::checkCall_mktemp)
150
631
    .Case("mkstemp", &WalkAST::checkCall_mkstemp)
151
631
    .Case("mkdtemp", &WalkAST::checkCall_mkstemp)
152
631
    .Case("mkstemps", &WalkAST::checkCall_mkstemp)
153
631
    .Cases("strcpy", "__strcpy_chk", &WalkAST::checkCall_strcpy)
154
631
    .Cases("strcat", "__strcat_chk", &WalkAST::checkCall_strcat)
155
631
    .Cases("sprintf", "vsprintf", "scanf", "wscanf", "fscanf", "fwscanf",
156
631
           "vscanf", "vwscanf", "vfscanf", "vfwscanf",
157
631
           &WalkAST::checkDeprecatedOrUnsafeBufferHandling)
158
631
    .Cases("sscanf", "swscanf", "vsscanf", "vswscanf", "swprintf",
159
631
           "snprintf", "vswprintf", "vsnprintf", "memcpy", "memmove",
160
631
           &WalkAST::checkDeprecatedOrUnsafeBufferHandling)
161
631
    .Cases("strncpy", "strncat", "memset",
162
631
           &WalkAST::checkDeprecatedOrUnsafeBufferHandling)
163
631
    .Case("drand48", &WalkAST::checkCall_rand)
164
631
    .Case("erand48", &WalkAST::checkCall_rand)
165
631
    .Case("jrand48", &WalkAST::checkCall_rand)
166
631
    .Case("lrand48", &WalkAST::checkCall_rand)
167
631
    .Case("mrand48", &WalkAST::checkCall_rand)
168
631
    .Case("nrand48", &WalkAST::checkCall_rand)
169
631
    .Case("lcong48", &WalkAST::checkCall_rand)
170
631
    .Case("rand", &WalkAST::checkCall_rand)
171
631
    .Case("rand_r", &WalkAST::checkCall_rand)
172
631
    .Case("random", &WalkAST::checkCall_random)
173
631
    .Case("vfork", &WalkAST::checkCall_vfork)
174
631
    .Default(nullptr);
175
631
176
631
  // If the callee isn't defined, it is not of security concern.
177
631
  // Check and evaluate the call.
178
631
  if (evalFunction)
179
513
    (this->*evalFunction)(CE, FD);
180
631
181
631
  // Recurse and check children.
182
631
  VisitChildren(CE);
183
631
}
184
185
256
void WalkAST::VisitCompoundStmt(CompoundStmt *S) {
186
256
  for (Stmt *Child : S->children())
187
931
    if (Child) {
188
931
      if (CallExpr *CE = dyn_cast<CallExpr>(Child))
189
555
        checkUncheckedReturnValue(CE);
190
931
      Visit(Child);
191
931
    }
192
256
}
193
194
64
void WalkAST::VisitForStmt(ForStmt *FS) {
195
64
  checkLoopConditionForFloat(FS);
196
64
197
64
  // Recurse and check children.
198
64
  VisitChildren(FS);
199
64
}
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
207
static const DeclRefExpr*
208
136
getIncrementedVar(const Expr *expr, const VarDecl *x, const VarDecl *y) {
209
136
  expr = expr->IgnoreParenCasts();
210
136
211
136
  if (const BinaryOperator *B = dyn_cast<BinaryOperator>(expr)) {
212
32
    if (!(B->isAssignmentOp() || 
B->isCompoundAssignmentOp()8
||
213
32
          
B->getOpcode() == BO_Comma8
))
214
0
      return nullptr;
215
32
216
32
    if (const DeclRefExpr *lhs = getIncrementedVar(B->getLHS(), x, y))
217
32
      return lhs;
218
0
219
0
    if (const DeclRefExpr *rhs = getIncrementedVar(B->getRHS(), x, y))
220
0
      return rhs;
221
0
222
0
    return nullptr;
223
0
  }
224
104
225
104
  if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(expr)) {
226
64
    const NamedDecl *ND = DR->getDecl();
227
64
    return ND == x || 
ND == y8
? DR :
nullptr0
;
228
64
  }
229
40
230
40
  if (const UnaryOperator *U = dyn_cast<UnaryOperator>(expr))
231
40
    return U->isIncrementDecrementOp()
232
40
      ? getIncrementedVar(U->getSubExpr(), x, y) : 
nullptr0
;
233
0
234
0
  return nullptr;
235
0
}
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
///
241
64
void WalkAST::checkLoopConditionForFloat(const ForStmt *FS) {
242
64
  if (!filter.check_FloatLoopCounter)
243
0
    return;
244
64
245
64
  // Does the loop have a condition?
246
64
  const Expr *condition = FS->getCond();
247
64
248
64
  if (!condition)
249
0
    return;
250
64
251
64
  // Does the loop have an increment?
252
64
  const Expr *increment = FS->getInc();
253
64
254
64
  if (!increment)
255
0
    return;
256
64
257
64
  // Strip away '()' and casts.
258
64
  condition = condition->IgnoreParenCasts();
259
64
  increment = increment->IgnoreParenCasts();
260
64
261
64
  // Is the loop condition a comparison?
262
64
  const BinaryOperator *B = dyn_cast<BinaryOperator>(condition);
263
64
264
64
  if (!B)
265
0
    return;
266
64
267
64
  // Is this a comparison?
268
64
  if (!(B->isRelationalOp() || 
B->isEqualityOp()0
))
269
0
    return;
270
64
271
64
  // Are we comparing variables?
272
64
  const DeclRefExpr *drLHS =
273
64
    dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParenLValueCasts());
274
64
  const DeclRefExpr *drRHS =
275
64
    dyn_cast<DeclRefExpr>(B->getRHS()->IgnoreParenLValueCasts());
276
64
277
64
  // Does at least one of the variables have a floating point type?
278
64
  drLHS = drLHS && 
drLHS->getType()->isRealFloatingType()56
?
drLHS56
:
nullptr8
;
279
64
  drRHS = drRHS && 
drRHS->getType()->isRealFloatingType()8
?
drRHS8
:
nullptr56
;
280
64
281
64
  if (!drLHS && 
!drRHS8
)
282
0
    return;
283
64
284
64
  const VarDecl *vdLHS = drLHS ? 
dyn_cast<VarDecl>(drLHS->getDecl())56
:
nullptr8
;
285
64
  const VarDecl *vdRHS = drRHS ? 
dyn_cast<VarDecl>(drRHS->getDecl())8
:
nullptr56
;
286
64
287
64
  if (!vdLHS && 
!vdRHS8
)
288
0
    return;
289
64
290
64
  // Does either variable appear in increment?
291
64
  const DeclRefExpr *drInc = getIncrementedVar(increment, vdLHS, vdRHS);
292
64
293
64
  if (!drInc)
294
0
    return;
295
64
296
64
  // Emit the error.  First figure out which DeclRefExpr in the condition
297
64
  // referenced the compared variable.
298
64
  assert(drInc->getDecl());
299
64
  const DeclRefExpr *drCond = vdLHS == drInc->getDecl() ? 
drLHS56
:
drRHS8
;
300
64
301
64
  SmallVector<SourceRange, 2> ranges;
302
64
  SmallString<256> sbuf;
303
64
  llvm::raw_svector_ostream os(sbuf);
304
64
305
64
  os << "Variable '" << drCond->getDecl()->getName()
306
64
     << "' with floating point type '" << drCond->getType().getAsString()
307
64
     << "' should not be used as a loop counter";
308
64
309
64
  ranges.push_back(drCond->getSourceRange());
310
64
  ranges.push_back(drInc->getSourceRange());
311
64
312
64
  const char *bugType = "Floating point variable used as loop counter";
313
64
314
64
  PathDiagnosticLocation FSLoc =
315
64
    PathDiagnosticLocation::createBegin(FS, BR.getSourceManager(), AC);
316
64
  BR.EmitBasicReport(AC->getDecl(), filter.checkName_FloatLoopCounter,
317
64
                     bugType, "Security", os.str(),
318
64
                     FSLoc, ranges);
319
64
}
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
327
8
void WalkAST::checkCall_bcmp(const CallExpr *CE, const FunctionDecl *FD) {
328
8
  if (!filter.check_bcmp)
329
0
    return;
330
8
331
8
  const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
332
8
  if (!FPT)
333
0
    return;
334
8
335
8
  // Verify that the function takes three arguments.
336
8
  if (FPT->getNumParams() != 3)
337
0
    return;
338
8
339
24
  
for (int i = 0; 8
i < 2;
i++16
) {
340
16
    // Verify the first and second argument type is void*.
341
16
    const PointerType *PT = FPT->getParamType(i)->getAs<PointerType>();
342
16
    if (!PT)
343
0
      return;
344
16
345
16
    if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().VoidTy)
346
0
      return;
347
16
  }
348
8
349
8
  // Verify the third argument type is integer.
350
8
  if (!FPT->getParamType(2)->isIntegralOrUnscopedEnumerationType())
351
0
    return;
352
8
353
8
  // Issue a warning.
354
8
  PathDiagnosticLocation CELoc =
355
8
    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
356
8
  BR.EmitBasicReport(AC->getDecl(), filter.checkName_bcmp,
357
8
                     "Use of deprecated function in call to 'bcmp()'",
358
8
                     "Security",
359
8
                     "The bcmp() function is obsoleted by memcmp().",
360
8
                     CELoc, CE->getCallee()->getSourceRange());
361
8
}
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
369
8
void WalkAST::checkCall_bcopy(const CallExpr *CE, const FunctionDecl *FD) {
370
8
  if (!filter.check_bcopy)
371
0
    return;
372
8
373
8
  const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
374
8
  if (!FPT)
375
0
    return;
376
8
377
8
  // Verify that the function takes three arguments.
378
8
  if (FPT->getNumParams() != 3)
379
0
    return;
380
8
381
24
  
for (int i = 0; 8
i < 2;
i++16
) {
382
16
    // Verify the first and second argument type is void*.
383
16
    const PointerType *PT = FPT->getParamType(i)->getAs<PointerType>();
384
16
    if (!PT)
385
0
      return;
386
16
387
16
    if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().VoidTy)
388
0
      return;
389
16
  }
390
8
391
8
  // Verify the third argument type is integer.
392
8
  if (!FPT->getParamType(2)->isIntegralOrUnscopedEnumerationType())
393
0
    return;
394
8
395
8
  // Issue a warning.
396
8
  PathDiagnosticLocation CELoc =
397
8
    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
398
8
  BR.EmitBasicReport(AC->getDecl(), filter.checkName_bcopy,
399
8
                     "Use of deprecated function in call to 'bcopy()'",
400
8
                     "Security",
401
8
                     "The bcopy() function is obsoleted by memcpy() "
402
8
                     "or memmove().",
403
8
                     CELoc, CE->getCallee()->getSourceRange());
404
8
}
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
412
8
void WalkAST::checkCall_bzero(const CallExpr *CE, const FunctionDecl *FD) {
413
8
  if (!filter.check_bzero)
414
0
    return;
415
8
416
8
  const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
417
8
  if (!FPT)
418
0
    return;
419
8
420
8
  // Verify that the function takes two arguments.
421
8
  if (FPT->getNumParams() != 2)
422
0
    return;
423
8
424
8
  // Verify the first argument type is void*.
425
8
  const PointerType *PT = FPT->getParamType(0)->getAs<PointerType>();
426
8
  if (!PT)
427
0
    return;
428
8
429
8
  if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().VoidTy)
430
0
    return;
431
8
432
8
  // Verify the second argument type is integer.
433
8
  if (!FPT->getParamType(1)->isIntegralOrUnscopedEnumerationType())
434
0
    return;
435
8
436
8
  // Issue a warning.
437
8
  PathDiagnosticLocation CELoc =
438
8
    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
439
8
  BR.EmitBasicReport(AC->getDecl(), filter.checkName_bzero,
440
8
                     "Use of deprecated function in call to 'bzero()'",
441
8
                     "Security",
442
8
                     "The bzero() function is obsoleted by memset().",
443
8
                     CELoc, CE->getCallee()->getSourceRange());
444
8
}
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
454
8
void WalkAST::checkCall_gets(const CallExpr *CE, const FunctionDecl *FD) {
455
8
  if (!filter.check_gets)
456
0
    return;
457
8
458
8
  const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
459
8
  if (!FPT)
460
0
    return;
461
8
462
8
  // Verify that the function takes a single argument.
463
8
  if (FPT->getNumParams() != 1)
464
0
    return;
465
8
466
8
  // Is the argument a 'char*'?
467
8
  const PointerType *PT = FPT->getParamType(0)->getAs<PointerType>();
468
8
  if (!PT)
469
0
    return;
470
8
471
8
  if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
472
0
    return;
473
8
474
8
  // Issue a warning.
475
8
  PathDiagnosticLocation CELoc =
476
8
    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
477
8
  BR.EmitBasicReport(AC->getDecl(), filter.checkName_gets,
478
8
                     "Potential buffer overflow in call to 'gets'",
479
8
                     "Security",
480
8
                     "Call to function 'gets' is extremely insecure as it can "
481
8
                     "always result in a buffer overflow",
482
8
                     CELoc, CE->getCallee()->getSourceRange());
483
8
}
484
485
//===----------------------------------------------------------------------===//
486
// Check: Any use of 'getpwd' is insecure.
487
// CWE-477: Use of Obsolete Functions
488
//===----------------------------------------------------------------------===//
489
490
8
void WalkAST::checkCall_getpw(const CallExpr *CE, const FunctionDecl *FD) {
491
8
  if (!filter.check_getpw)
492
0
    return;
493
8
494
8
  const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
495
8
  if (!FPT)
496
0
    return;
497
8
498
8
  // Verify that the function takes two arguments.
499
8
  if (FPT->getNumParams() != 2)
500
0
    return;
501
8
502
8
  // Verify the first argument type is integer.
503
8
  if (!FPT->getParamType(0)->isIntegralOrUnscopedEnumerationType())
504
0
    return;
505
8
506
8
  // Verify the second argument type is char*.
507
8
  const PointerType *PT = FPT->getParamType(1)->getAs<PointerType>();
508
8
  if (!PT)
509
0
    return;
510
8
511
8
  if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
512
0
    return;
513
8
514
8
  // Issue a warning.
515
8
  PathDiagnosticLocation CELoc =
516
8
    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
517
8
  BR.EmitBasicReport(AC->getDecl(), filter.checkName_getpw,
518
8
                     "Potential buffer overflow in call to 'getpw'",
519
8
                     "Security",
520
8
                     "The getpw() function is dangerous as it may overflow the "
521
8
                     "provided buffer. It is obsoleted by getpwuid().",
522
8
                     CELoc, CE->getCallee()->getSourceRange());
523
8
}
524
525
//===----------------------------------------------------------------------===//
526
// Check: Any use of 'mktemp' is insecure.  It is obsoleted by mkstemp().
527
// CWE-377: Insecure Temporary File
528
//===----------------------------------------------------------------------===//
529
530
8
void WalkAST::checkCall_mktemp(const CallExpr *CE, const FunctionDecl *FD) {
531
8
  if (!filter.check_mktemp) {
532
0
    // Fall back to the security check of looking for enough 'X's in the
533
0
    // format string, since that is a less severe warning.
534
0
    checkCall_mkstemp(CE, FD);
535
0
    return;
536
0
  }
537
8
538
8
  const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
539
8
  if(!FPT)
540
0
    return;
541
8
542
8
  // Verify that the function takes a single argument.
543
8
  if (FPT->getNumParams() != 1)
544
0
    return;
545
8
546
8
  // Verify that the argument is Pointer Type.
547
8
  const PointerType *PT = FPT->getParamType(0)->getAs<PointerType>();
548
8
  if (!PT)
549
0
    return;
550
8
551
8
  // Verify that the argument is a 'char*'.
552
8
  if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
553
0
    return;
554
8
555
8
  // Issue a warning.
556
8
  PathDiagnosticLocation CELoc =
557
8
    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
558
8
  BR.EmitBasicReport(AC->getDecl(), filter.checkName_mktemp,
559
8
                     "Potential insecure temporary file in call 'mktemp'",
560
8
                     "Security",
561
8
                     "Call to function 'mktemp' is insecure as it always "
562
8
                     "creates or uses insecure temporary file.  Use 'mkstemp' "
563
8
                     "instead",
564
8
                     CELoc, CE->getCallee()->getSourceRange());
565
8
}
566
567
//===----------------------------------------------------------------------===//
568
// Check: Use of 'mkstemp', 'mktemp', 'mkdtemp' should contain at least 6 X's.
569
//===----------------------------------------------------------------------===//
570
571
72
void WalkAST::checkCall_mkstemp(const CallExpr *CE, const FunctionDecl *FD) {
572
72
  if (!filter.check_mkstemp)
573
0
    return;
574
72
575
72
  StringRef Name = FD->getIdentifier()->getName();
576
72
  std::pair<signed, signed> ArgSuffix =
577
72
    llvm::StringSwitch<std::pair<signed, signed> >(Name)
578
72
      .Case("mktemp", std::make_pair(0,-1))
579
72
      .Case("mkstemp", std::make_pair(0,-1))
580
72
      .Case("mkdtemp", std::make_pair(0,-1))
581
72
      .Case("mkstemps", std::make_pair(0,1))
582
72
      .Default(std::make_pair(-1, -1));
583
72
584
72
  assert(ArgSuffix.first >= 0 && "Unsupported function");
585
72
586
72
  // Check if the number of arguments is consistent with out expectations.
587
72
  unsigned numArgs = CE->getNumArgs();
588
72
  if ((signed) numArgs <= ArgSuffix.first)
589
0
    return;
590
72
591
72
  const StringLiteral *strArg =
592
72
    dyn_cast<StringLiteral>(CE->getArg((unsigned)ArgSuffix.first)
593
72
                              ->IgnoreParenImpCasts());
594
72
595
72
  // Currently we only handle string literals.  It is possible to do better,
596
72
  // either by looking at references to const variables, or by doing real
597
72
  // flow analysis.
598
72
  if (!strArg || strArg->getCharByteWidth() != 1)
599
0
    return;
600
72
601
72
  // Count the number of X's, taking into account a possible cutoff suffix.
602
72
  StringRef str = strArg->getString();
603
72
  unsigned numX = 0;
604
72
  unsigned n = str.size();
605
72
606
72
  // Take into account the suffix.
607
72
  unsigned suffix = 0;
608
72
  if (ArgSuffix.second >= 0) {
609
24
    const Expr *suffixEx = CE->getArg((unsigned)ArgSuffix.second);
610
24
    Expr::EvalResult EVResult;
611
24
    if (!suffixEx->EvaluateAsInt(EVResult, BR.getContext()))
612
0
      return;
613
24
    llvm::APSInt Result = EVResult.Val.getInt();
614
24
    // FIXME: Issue a warning.
615
24
    if (Result.isNegative())
616
0
      return;
617
24
    suffix = (unsigned) Result.getZExtValue();
618
24
    n = (n > suffix) ? n - suffix : 
00
;
619
24
  }
620
72
621
384
  
for (unsigned i = 0; 72
i < n;
++i312
)
622
312
    if (str[i] == 'X') ++numX;
623
72
624
72
  if (numX >= 6)
625
32
    return;
626
40
627
40
  // Issue a warning.
628
40
  PathDiagnosticLocation CELoc =
629
40
    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
630
40
  SmallString<512> buf;
631
40
  llvm::raw_svector_ostream out(buf);
632
40
  out << "Call to '" << Name << "' should have at least 6 'X's in the"
633
40
    " format string to be secure (" << numX << " 'X'";
634
40
  if (numX != 1)
635
32
    out << 's';
636
40
  out << " seen";
637
40
  if (suffix) {
638
16
    out << ", " << suffix << " character";
639
16
    if (suffix > 1)
640
8
      out << 's';
641
16
    out << " used as a suffix";
642
16
  }
643
40
  out << ')';
644
40
  BR.EmitBasicReport(AC->getDecl(), filter.checkName_mkstemp,
645
40
                     "Insecure temporary file creation", "Security",
646
40
                     out.str(), CELoc, strArg->getSourceRange());
647
40
}
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
656
32
void WalkAST::checkCall_strcpy(const CallExpr *CE, const FunctionDecl *FD) {
657
32
  if (!filter.check_strcpy)
658
0
    return;
659
32
660
32
  if (!checkCall_strCommon(CE, FD))
661
0
    return;
662
32
663
32
  const auto *Target = CE->getArg(0)->IgnoreImpCasts(),
664
32
             *Source = CE->getArg(1)->IgnoreImpCasts();
665
32
666
32
  if (const auto *Array = dyn_cast<ConstantArrayType>(Target->getType())) {
667
32
    uint64_t ArraySize = BR.getContext().getTypeSize(Array) / 8;
668
32
    if (const auto *String = dyn_cast<StringLiteral>(Source)) {
669
24
      if (ArraySize >= String->getLength() + 1)
670
16
        return;
671
16
    }
672
32
  }
673
16
674
16
  // Issue a warning.
675
16
  PathDiagnosticLocation CELoc =
676
16
    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
677
16
  BR.EmitBasicReport(AC->getDecl(), filter.checkName_strcpy,
678
16
                     "Potential insecure memory buffer bounds restriction in "
679
16
                     "call 'strcpy'",
680
16
                     "Security",
681
16
                     "Call to function 'strcpy' is insecure as it does not "
682
16
                     "provide bounding of the memory buffer. Replace "
683
16
                     "unbounded copy functions with analogous functions that "
684
16
                     "support length arguments such as 'strlcpy'. CWE-119.",
685
16
                     CELoc, CE->getCallee()->getSourceRange());
686
16
}
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
695
8
void WalkAST::checkCall_strcat(const CallExpr *CE, const FunctionDecl *FD) {
696
8
  if (!filter.check_strcpy)
697
0
    return;
698
8
699
8
  if (!checkCall_strCommon(CE, FD))
700
0
    return;
701
8
702
8
  // Issue a warning.
703
8
  PathDiagnosticLocation CELoc =
704
8
    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
705
8
  BR.EmitBasicReport(AC->getDecl(), filter.checkName_strcpy,
706
8
                     "Potential insecure memory buffer bounds restriction in "
707
8
                     "call 'strcat'",
708
8
                     "Security",
709
8
                     "Call to function 'strcat' is insecure as it does not "
710
8
                     "provide bounding of the memory buffer. Replace "
711
8
                     "unbounded copy functions with analogous functions that "
712
8
                     "support length arguments such as 'strlcat'. CWE-119.",
713
8
                     CELoc, CE->getCallee()->getSourceRange());
714
8
}
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
732
void WalkAST::checkDeprecatedOrUnsafeBufferHandling(const CallExpr *CE,
733
241
                                                    const FunctionDecl *FD) {
734
241
  if (!filter.check_DeprecatedOrUnsafeBufferHandling)
735
0
    return;
736
241
737
241
  if (!BR.getContext().getLangOpts().C11)
738
3
    return;
739
238
740
238
  // Issue a warning. ArgIndex == -1: Deprecated but not unsafe (has size
741
238
  // restrictions).
742
238
  enum { DEPR_ONLY = -1, UNKNOWN_CALL = -2 };
743
238
744
238
  StringRef Name = FD->getIdentifier()->getName();
745
238
  if (Name.startswith("__builtin_"))
746
6
    Name = Name.substr(10);
747
238
748
238
  int ArgIndex =
749
238
      llvm::StringSwitch<int>(Name)
750
238
          .Cases("scanf", "wscanf", "vscanf", "vwscanf", 0)
751
238
          .Cases("sprintf", "vsprintf", "fscanf", "fwscanf", "vfscanf",
752
238
                 "vfwscanf", "sscanf", "swscanf", "vsscanf", "vswscanf", 1)
753
238
          .Cases("swprintf", "snprintf", "vswprintf", "vsnprintf", "memcpy",
754
238
                 "memmove", "memset", "strncpy", "strncat", DEPR_ONLY)
755
238
          .Default(UNKNOWN_CALL);
756
238
757
238
  assert(ArgIndex != UNKNOWN_CALL && "Unsupported function");
758
238
  bool BoundsProvided = ArgIndex == DEPR_ONLY;
759
238
760
238
  if (!BoundsProvided) {
761
160
    // Currently we only handle (not wide) string literals. It is possible to do
762
160
    // better, either by looking at references to const variables, or by doing
763
160
    // real flow analysis.
764
160
    auto FormatString =
765
160
        dyn_cast<StringLiteral>(CE->getArg(ArgIndex)->IgnoreParenImpCasts());
766
160
    if (FormatString &&
767
160
        
FormatString->getString().find("%s") == StringRef::npos80
&&
768
160
        
FormatString->getString().find("%[") == StringRef::npos56
)
769
56
      BoundsProvided = true;
770
160
  }
771
238
772
238
  SmallString<128> Buf1;
773
238
  SmallString<512> Buf2;
774
238
  llvm::raw_svector_ostream Out1(Buf1);
775
238
  llvm::raw_svector_ostream Out2(Buf2);
776
238
777
238
  Out1 << "Potential insecure memory buffer bounds restriction in call '"
778
238
       << Name << "'";
779
238
  Out2 << "Call to function '" << Name
780
238
       << "' is insecure as it does not provide ";
781
238
782
238
  if (!BoundsProvided) {
783
104
    Out2 << "bounding of the memory buffer or ";
784
104
  }
785
238
786
238
  Out2 << "security checks introduced "
787
238
          "in the C11 standard. Replace with analogous functions that "
788
238
          "support length arguments or provides boundary checks such as '"
789
238
       << Name << "_s' in case of C11";
790
238
791
238
  PathDiagnosticLocation CELoc =
792
238
      PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
793
238
  BR.EmitBasicReport(AC->getDecl(),
794
238
                     filter.checkName_DeprecatedOrUnsafeBufferHandling,
795
238
                     Out1.str(), "Security", Out2.str(), CELoc,
796
238
                     CE->getCallee()->getSourceRange());
797
238
}
798
799
//===----------------------------------------------------------------------===//
800
// Common check for str* functions with no bounds parameters.
801
//===----------------------------------------------------------------------===//
802
803
40
bool WalkAST::checkCall_strCommon(const CallExpr *CE, const FunctionDecl *FD) {
804
40
  const FunctionProtoType *FPT = FD->getType()->getAs<FunctionProtoType>();
805
40
  if (!FPT)
806
0
    return false;
807
40
808
40
  // Verify the function takes two arguments, three in the _chk version.
809
40
  int numArgs = FPT->getNumParams();
810
40
  if (numArgs != 2 && 
numArgs != 320
)
811
0
    return false;
812
40
813
40
  // Verify the type for both arguments.
814
120
  
for (int i = 0; 40
i < 2;
i++80
) {
815
80
    // Verify that the arguments are pointers.
816
80
    const PointerType *PT = FPT->getParamType(i)->getAs<PointerType>();
817
80
    if (!PT)
818
0
      return false;
819
80
820
80
    // Verify that the argument is a 'char*'.
821
80
    if (PT->getPointeeType().getUnqualifiedType() != BR.getContext().CharTy)
822
0
      return false;
823
80
  }
824
40
825
40
  return true;
826
40
}
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
834
81
void WalkAST::checkCall_rand(const CallExpr *CE, const FunctionDecl *FD) {
835
81
  if (!filter.check_rand || !CheckRand)
836
9
    return;
837
72
838
72
  const FunctionProtoType *FTP = FD->getType()->getAs<FunctionProtoType>();
839
72
  if (!FTP)
840
0
    return;
841
72
842
72
  if (FTP->getNumParams() == 1) {
843
40
    // Is the argument an 'unsigned short *'?
844
40
    // (Actually any integer type is allowed.)
845
40
    const PointerType *PT = FTP->getParamType(0)->getAs<PointerType>();
846
40
    if (!PT)
847
0
      return;
848
40
849
40
    if (! PT->getPointeeType()->isIntegralOrUnscopedEnumerationType())
850
0
      return;
851
32
  } else if (FTP->getNumParams() != 0)
852
0
    return;
853
72
854
72
  // Issue a warning.
855
72
  SmallString<256> buf1;
856
72
  llvm::raw_svector_ostream os1(buf1);
857
72
  os1 << '\'' << *FD << "' is a poor random number generator";
858
72
859
72
  SmallString<256> buf2;
860
72
  llvm::raw_svector_ostream os2(buf2);
861
72
  os2 << "Function '" << *FD
862
72
      << "' is obsolete because it implements a poor random number generator."
863
72
      << "  Use 'arc4random' instead";
864
72
865
72
  PathDiagnosticLocation CELoc =
866
72
    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
867
72
  BR.EmitBasicReport(AC->getDecl(), filter.checkName_rand, os1.str(),
868
72
                     "Security", os2.str(), CELoc,
869
72
                     CE->getCallee()->getSourceRange());
870
72
}
871
872
//===----------------------------------------------------------------------===//
873
// Check: 'random' should not be used
874
// Originally: <rdar://problem/63371000>
875
//===----------------------------------------------------------------------===//
876
877
9
void WalkAST::checkCall_random(const CallExpr *CE, const FunctionDecl *FD) {
878
9
  if (!CheckRand || 
!filter.check_rand8
)
879
1
    return;
880
8
881
8
  const FunctionProtoType *FTP = FD->getType()->getAs<FunctionProtoType>();
882
8
  if (!FTP)
883
0
    return;
884
8
885
8
  // Verify that the function takes no argument.
886
8
  if (FTP->getNumParams() != 0)
887
0
    return;
888
8
889
8
  // Issue a warning.
890
8
  PathDiagnosticLocation CELoc =
891
8
    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
892
8
  BR.EmitBasicReport(AC->getDecl(), filter.checkName_rand,
893
8
                     "'random' is not a secure random number generator",
894
8
                     "Security",
895
8
                     "The 'random' function produces a sequence of values that "
896
8
                     "an adversary may be able to predict.  Use 'arc4random' "
897
8
                     "instead", CELoc, CE->getCallee()->getSourceRange());
898
8
}
899
900
//===----------------------------------------------------------------------===//
901
// Check: 'vfork' should not be used.
902
// POS33-C: Do not use vfork().
903
//===----------------------------------------------------------------------===//
904
905
22
void WalkAST::checkCall_vfork(const CallExpr *CE, const FunctionDecl *FD) {
906
22
  if (!filter.check_vfork)
907
0
    return;
908
22
909
22
  // All calls to vfork() are insecure, issue a warning.
910
22
  PathDiagnosticLocation CELoc =
911
22
    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
912
22
  BR.EmitBasicReport(AC->getDecl(), filter.checkName_vfork,
913
22
                     "Potential insecure implementation-specific behavior in "
914
22
                     "call 'vfork'",
915
22
                     "Security",
916
22
                     "Call to function 'vfork' is insecure as it can lead to "
917
22
                     "denial of service situations in the parent process. "
918
22
                     "Replace calls to vfork with calls to the safer "
919
22
                     "'posix_spawn' function",
920
22
                     CELoc, CE->getCallee()->getSourceRange());
921
22
}
922
923
//===----------------------------------------------------------------------===//
924
// Check: Should check whether privileges are dropped successfully.
925
// Originally: <rdar://problem/6337132>
926
//===----------------------------------------------------------------------===//
927
928
555
void WalkAST::checkUncheckedReturnValue(CallExpr *CE) {
929
555
  if (!filter.check_UncheckedReturn)
930
16
    return;
931
539
932
539
  const FunctionDecl *FD = CE->getDirectCallee();
933
539
  if (!FD)
934
0
    return;
935
539
936
539
  if (II_setid[0] == nullptr) {
937
132
    static const char * const identifiers[num_setids] = {
938
132
      "setuid", "setgid", "seteuid", "setegid",
939
132
      "setreuid", "setregid"
940
132
    };
941
132
942
924
    for (size_t i = 0; i < num_setids; 
i++792
)
943
792
      II_setid[i] = &BR.getContext().Idents.get(identifiers[i]);
944
132
  }
945
539
946
539
  const IdentifierInfo *id = FD->getIdentifier();
947
539
  size_t identifierid;
948
539
949
3.65k
  for (identifierid = 0; identifierid < num_setids; 
identifierid++3.11k
)
950
3.14k
    if (id == II_setid[identifierid])
951
32
      break;
952
539
953
539
  if (identifierid >= num_setids)
954
507
    return;
955
32
956
32
  const FunctionProtoType *FTP = FD->getType()->getAs<FunctionProtoType>();
957
32
  if (!FTP)
958
0
    return;
959
32
960
32
  // Verify that the function takes one or two arguments (depending on
961
32
  //   the function).
962
32
  if (FTP->getNumParams() != (identifierid < 4 ? 
116
:
216
))
963
0
    return;
964
32
965
32
  // The arguments must be integers.
966
80
  
for (unsigned i = 0; 32
i < FTP->getNumParams();
i++48
)
967
48
    if (!FTP->getParamType(i)->isIntegralOrUnscopedEnumerationType())
968
0
      return;
969
32
970
32
  // Issue a warning.
971
32
  SmallString<256> buf1;
972
32
  llvm::raw_svector_ostream os1(buf1);
973
32
  os1 << "Return value is not checked in call to '" << *FD << '\'';
974
32
975
32
  SmallString<256> buf2;
976
32
  llvm::raw_svector_ostream os2(buf2);
977
32
  os2 << "The return value from the call to '" << *FD
978
32
      << "' is not checked.  If an error occurs in '" << *FD
979
32
      << "', the following code may execute with unexpected privileges";
980
32
981
32
  PathDiagnosticLocation CELoc =
982
32
    PathDiagnosticLocation::createBegin(CE, BR.getSourceManager(), AC);
983
32
  BR.EmitBasicReport(AC->getDecl(), filter.checkName_UncheckedReturn, os1.str(),
984
32
                     "Security", os2.str(), CELoc,
985
32
                     CE->getCallee()->getSourceRange());
986
32
}
987
988
//===----------------------------------------------------------------------===//
989
// SecuritySyntaxChecker
990
//===----------------------------------------------------------------------===//
991
992
namespace {
993
class SecuritySyntaxChecker : public Checker<check::ASTCodeBody> {
994
public:
995
  ChecksFilter filter;
996
997
  void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
998
174
                        BugReporter &BR) const {
999
174
    WalkAST walker(BR, mgr.getAnalysisDeclContext(D), filter);
1000
174
    walker.Visit(D->getBody());
1001
174
  }
1002
};
1003
}
1004
1005
22
void ento::registerSecuritySyntaxChecker(CheckerManager &mgr) {
1006
22
  mgr.registerChecker<SecuritySyntaxChecker>();
1007
22
}
1008
1009
12
bool ento::shouldRegisterSecuritySyntaxChecker(const LangOptions &LO) {
1010
12
  return true;
1011
12
}
1012
1013
#define REGISTER_CHECKER(name)                                                 \
1014
203
  void ento::register##name(CheckerManager &mgr) {                             \
1015
203
    SecuritySyntaxChecker *checker =  mgr.getChecker<SecuritySyntaxChecker>(); \
1016
203
    checker->filter.check_##name = true;                                       \
1017
203
    checker->filter.checkName_##name = mgr.getCurrentCheckName();              \
1018
203
  }                                                                            \
clang::ento::registerbcmp(clang::ento::CheckerManager&)
Line
Count
Source
1014
12
  void ento::register##name(CheckerManager &mgr) {                             \
1015
12
    SecuritySyntaxChecker *checker =  mgr.getChecker<SecuritySyntaxChecker>(); \
1016
12
    checker->filter.check_##name = true;                                       \
1017
12
    checker->filter.checkName_##name = mgr.getCurrentCheckName();              \
1018
12
  }                                                                            \
clang::ento::registerbcopy(clang::ento::CheckerManager&)
Line
Count
Source
1014
12
  void ento::register##name(CheckerManager &mgr) {                             \
1015
12
    SecuritySyntaxChecker *checker =  mgr.getChecker<SecuritySyntaxChecker>(); \
1016
12
    checker->filter.check_##name = true;                                       \
1017
12
    checker->filter.checkName_##name = mgr.getCurrentCheckName();              \
1018
12
  }                                                                            \
clang::ento::registerbzero(clang::ento::CheckerManager&)
Line
Count
Source
1014
12
  void ento::register##name(CheckerManager &mgr) {                             \
1015
12
    SecuritySyntaxChecker *checker =  mgr.getChecker<SecuritySyntaxChecker>(); \
1016
12
    checker->filter.check_##name = true;                                       \
1017
12
    checker->filter.checkName_##name = mgr.getCurrentCheckName();              \
1018
12
  }                                                                            \
clang::ento::registergets(clang::ento::CheckerManager&)
Line
Count
Source
1014
20
  void ento::register##name(CheckerManager &mgr) {                             \
1015
20
    SecuritySyntaxChecker *checker =  mgr.getChecker<SecuritySyntaxChecker>(); \
1016
20
    checker->filter.check_##name = true;                                       \
1017
20
    checker->filter.checkName_##name = mgr.getCurrentCheckName();              \
1018
20
  }                                                                            \
clang::ento::registergetpw(clang::ento::CheckerManager&)
Line
Count
Source
1014
20
  void ento::register##name(CheckerManager &mgr) {                             \
1015
20
    SecuritySyntaxChecker *checker =  mgr.getChecker<SecuritySyntaxChecker>(); \
1016
20
    checker->filter.check_##name = true;                                       \
1017
20
    checker->filter.checkName_##name = mgr.getCurrentCheckName();              \
1018
20
  }                                                                            \
clang::ento::registermkstemp(clang::ento::CheckerManager&)
Line
Count
Source
1014
20
  void ento::register##name(CheckerManager &mgr) {                             \
1015
20
    SecuritySyntaxChecker *checker =  mgr.getChecker<SecuritySyntaxChecker>(); \
1016
20
    checker->filter.check_##name = true;                                       \
1017
20
    checker->filter.checkName_##name = mgr.getCurrentCheckName();              \
1018
20
  }                                                                            \
clang::ento::registermktemp(clang::ento::CheckerManager&)
Line
Count
Source
1014
20
  void ento::register##name(CheckerManager &mgr) {                             \
1015
20
    SecuritySyntaxChecker *checker =  mgr.getChecker<SecuritySyntaxChecker>(); \
1016
20
    checker->filter.check_##name = true;                                       \
1017
20
    checker->filter.checkName_##name = mgr.getCurrentCheckName();              \
1018
20
  }                                                                            \
clang::ento::registerstrcpy(clang::ento::CheckerManager&)
Line
Count
Source
1014
12
  void ento::register##name(CheckerManager &mgr) {                             \
1015
12
    SecuritySyntaxChecker *checker =  mgr.getChecker<SecuritySyntaxChecker>(); \
1016
12
    checker->filter.check_##name = true;                                       \
1017
12
    checker->filter.checkName_##name = mgr.getCurrentCheckName();              \
1018
12
  }                                                                            \
clang::ento::registerrand(clang::ento::CheckerManager&)
Line
Count
Source
1014
12
  void ento::register##name(CheckerManager &mgr) {                             \
1015
12
    SecuritySyntaxChecker *checker =  mgr.getChecker<SecuritySyntaxChecker>(); \
1016
12
    checker->filter.check_##name = true;                                       \
1017
12
    checker->filter.checkName_##name = mgr.getCurrentCheckName();              \
1018
12
  }                                                                            \
clang::ento::registervfork(clang::ento::CheckerManager&)
Line
Count
Source
1014
22
  void ento::register##name(CheckerManager &mgr) {                             \
1015
22
    SecuritySyntaxChecker *checker =  mgr.getChecker<SecuritySyntaxChecker>(); \
1016
22
    checker->filter.check_##name = true;                                       \
1017
22
    checker->filter.checkName_##name = mgr.getCurrentCheckName();              \
1018
22
  }                                                                            \
clang::ento::registerFloatLoopCounter(clang::ento::CheckerManager&)
Line
Count
Source
1014
9
  void ento::register##name(CheckerManager &mgr) {                             \
1015
9
    SecuritySyntaxChecker *checker =  mgr.getChecker<SecuritySyntaxChecker>(); \
1016
9
    checker->filter.check_##name = true;                                       \
1017
9
    checker->filter.checkName_##name = mgr.getCurrentCheckName();              \
1018
9
  }                                                                            \
clang::ento::registerUncheckedReturn(clang::ento::CheckerManager&)
Line
Count
Source
1014
20
  void ento::register##name(CheckerManager &mgr) {                             \
1015
20
    SecuritySyntaxChecker *checker =  mgr.getChecker<SecuritySyntaxChecker>(); \
1016
20
    checker->filter.check_##name = true;                                       \
1017
20
    checker->filter.checkName_##name = mgr.getCurrentCheckName();              \
1018
20
  }                                                                            \
clang::ento::registerDeprecatedOrUnsafeBufferHandling(clang::ento::CheckerManager&)
Line
Count
Source
1014
12
  void ento::register##name(CheckerManager &mgr) {                             \
1015
12
    SecuritySyntaxChecker *checker =  mgr.getChecker<SecuritySyntaxChecker>(); \
1016
12
    checker->filter.check_##name = true;                                       \
1017
12
    checker->filter.checkName_##name = mgr.getCurrentCheckName();              \
1018
12
  }                                                                            \
1019
                                                                               \
1020
203
  bool ento::shouldRegister##name(const LangOptions &LO) {                     \
1021
203
    return true;                                                               \
1022
203
  }
clang::ento::shouldRegisterbcmp(clang::LangOptions const&)
Line
Count
Source
1020
12
  bool ento::shouldRegister##name(const LangOptions &LO) {                     \
1021
12
    return true;                                                               \
1022
12
  }
clang::ento::shouldRegisterbcopy(clang::LangOptions const&)
Line
Count
Source
1020
12
  bool ento::shouldRegister##name(const LangOptions &LO) {                     \
1021
12
    return true;                                                               \
1022
12
  }
clang::ento::shouldRegisterbzero(clang::LangOptions const&)
Line
Count
Source
1020
12
  bool ento::shouldRegister##name(const LangOptions &LO) {                     \
1021
12
    return true;                                                               \
1022
12
  }
clang::ento::shouldRegistergets(clang::LangOptions const&)
Line
Count
Source
1020
20
  bool ento::shouldRegister##name(const LangOptions &LO) {                     \
1021
20
    return true;                                                               \
1022
20
  }
clang::ento::shouldRegistergetpw(clang::LangOptions const&)
Line
Count
Source
1020
20
  bool ento::shouldRegister##name(const LangOptions &LO) {                     \
1021
20
    return true;                                                               \
1022
20
  }
clang::ento::shouldRegistermkstemp(clang::LangOptions const&)
Line
Count
Source
1020
20
  bool ento::shouldRegister##name(const LangOptions &LO) {                     \
1021
20
    return true;                                                               \
1022
20
  }
clang::ento::shouldRegistermktemp(clang::LangOptions const&)
Line
Count
Source
1020
20
  bool ento::shouldRegister##name(const LangOptions &LO) {                     \
1021
20
    return true;                                                               \
1022
20
  }
clang::ento::shouldRegisterstrcpy(clang::LangOptions const&)
Line
Count
Source
1020
12
  bool ento::shouldRegister##name(const LangOptions &LO) {                     \
1021
12
    return true;                                                               \
1022
12
  }
clang::ento::shouldRegisterrand(clang::LangOptions const&)
Line
Count
Source
1020
12
  bool ento::shouldRegister##name(const LangOptions &LO) {                     \
1021
12
    return true;                                                               \
1022
12
  }
clang::ento::shouldRegistervfork(clang::LangOptions const&)
Line
Count
Source
1020
22
  bool ento::shouldRegister##name(const LangOptions &LO) {                     \
1021
22
    return true;                                                               \
1022
22
  }
clang::ento::shouldRegisterFloatLoopCounter(clang::LangOptions const&)
Line
Count
Source
1020
9
  bool ento::shouldRegister##name(const LangOptions &LO) {                     \
1021
9
    return true;                                                               \
1022
9
  }
clang::ento::shouldRegisterUncheckedReturn(clang::LangOptions const&)
Line
Count
Source
1020
20
  bool ento::shouldRegister##name(const LangOptions &LO) {                     \
1021
20
    return true;                                                               \
1022
20
  }
clang::ento::shouldRegisterDeprecatedOrUnsafeBufferHandling(clang::LangOptions const&)
Line
Count
Source
1020
12
  bool ento::shouldRegister##name(const LangOptions &LO) {                     \
1021
12
    return true;                                                               \
1022
12
  }
1023
1024
REGISTER_CHECKER(bcmp)
1025
REGISTER_CHECKER(bcopy)
1026
REGISTER_CHECKER(bzero)
1027
REGISTER_CHECKER(gets)
1028
REGISTER_CHECKER(getpw)
1029
REGISTER_CHECKER(mkstemp)
1030
REGISTER_CHECKER(mktemp)
1031
REGISTER_CHECKER(strcpy)
1032
REGISTER_CHECKER(rand)
1033
REGISTER_CHECKER(vfork)
1034
REGISTER_CHECKER(FloatLoopCounter)
1035
REGISTER_CHECKER(UncheckedReturn)
1036
REGISTER_CHECKER(DeprecatedOrUnsafeBufferHandling)