Coverage Report

Created: 2020-11-24 06:42

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