Coverage Report

Created: 2023-09-30 09:22

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