11
11
//
12
12
// ===----------------------------------------------------------------------===//
13
13
14
- #include " clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration .h"
14
+ #include " clang/AST/ExprCXX .h"
15
15
#include " clang/AST/ParentMap.h"
16
16
#include " clang/Basic/TargetInfo.h"
17
+ #include " clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
17
18
#include " clang/StaticAnalyzer/Core/BugReporter/BugType.h"
18
19
#include " clang/StaticAnalyzer/Core/Checker.h"
19
20
#include " clang/StaticAnalyzer/Core/CheckerManager.h"
20
21
#include " clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
21
22
#include " clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
22
23
#include " llvm/ADT/SmallString.h"
23
24
#include " llvm/ADT/StringExtras.h"
25
+ #include " llvm/Support/Casting.h"
24
26
#include " llvm/Support/raw_ostream.h"
25
27
26
28
using namespace clang ;
@@ -29,11 +31,8 @@ using namespace ento;
29
31
namespace {
30
32
31
33
class CallAndMessageChecker
32
- : public Checker< check::PreStmt<CallExpr>,
33
- check::PreStmt<CXXDeleteExpr>,
34
- check::PreObjCMessage,
35
- check::ObjCMessageNil,
36
- check::PreCall > {
34
+ : public Checker<check::PreObjCMessage, check::ObjCMessageNil,
35
+ check::PreCall> {
37
36
mutable std::unique_ptr<BugType> BT_call_null;
38
37
mutable std::unique_ptr<BugType> BT_call_undef;
39
38
mutable std::unique_ptr<BugType> BT_cxx_call_null;
@@ -48,11 +47,10 @@ class CallAndMessageChecker
48
47
mutable std::unique_ptr<BugType> BT_call_few_args;
49
48
50
49
public:
51
- DefaultBool Check_CallAndMessageUnInitRefArg;
52
- CheckerNameRef CheckName_CallAndMessageUnInitRefArg;
50
+ enum CheckKind { CK_CallAndMessageUnInitRefArg, CK_NumCheckKinds };
51
+
52
+ DefaultBool ChecksEnabled[CK_NumCheckKinds];
53
53
54
- void checkPreStmt (const CallExpr *CE, CheckerContext &C) const ;
55
- void checkPreStmt (const CXXDeleteExpr *DE, CheckerContext &C) const ;
56
54
void checkPreObjCMessage (const ObjCMethodCall &msg, CheckerContext &C) const ;
57
55
58
56
// / Fill in the return value that results from messaging nil based on the
@@ -144,7 +142,7 @@ bool CallAndMessageChecker::uninitRefOrPointer(
144
142
CheckerContext &C, const SVal &V, SourceRange ArgRange, const Expr *ArgEx,
145
143
std::unique_ptr<BugType> &BT, const ParmVarDecl *ParamDecl, const char *BD,
146
144
int ArgumentNumber) const {
147
- if (!Check_CallAndMessageUnInitRefArg )
145
+ if (!ChecksEnabled[CK_CallAndMessageUnInitRefArg] )
148
146
return false ;
149
147
150
148
// No parameter declaration available, i.e. variadic function argument.
@@ -311,63 +309,36 @@ bool CallAndMessageChecker::PreVisitProcessArg(CheckerContext &C,
311
309
return false ;
312
310
}
313
311
314
- void CallAndMessageChecker::checkPreStmt (const CallExpr *CE,
315
- CheckerContext &C) const {
316
-
317
- const Expr *Callee = CE->getCallee ()->IgnoreParens ();
312
+ void CallAndMessageChecker::checkPreCall (const CallEvent &Call,
313
+ CheckerContext &C) const {
318
314
ProgramStateRef State = C.getState ();
319
- const LocationContext *LCtx = C.getLocationContext ();
320
- SVal L = State->getSVal (Callee, LCtx);
321
-
322
- if (L.isUndef ()) {
323
- if (!BT_call_undef)
324
- BT_call_undef.reset (new BuiltinBug (
325
- this , " Called function pointer is an uninitialized pointer value" ));
326
- emitBadCall (BT_call_undef.get (), C, Callee);
327
- return ;
328
- }
329
-
330
- ProgramStateRef StNonNull, StNull;
331
- std::tie (StNonNull, StNull) = State->assume (L.castAs <DefinedOrUnknownSVal>());
332
-
333
- if (StNull && !StNonNull) {
334
- if (!BT_call_null)
335
- BT_call_null.reset (new BuiltinBug (
336
- this , " Called function pointer is null (null dereference)" ));
337
- emitBadCall (BT_call_null.get (), C, Callee);
338
- return ;
339
- }
340
-
341
- C.addTransition (StNonNull);
342
- }
315
+ if (const CallExpr *CE = dyn_cast_or_null<CallExpr>(Call.getOriginExpr ())) {
316
+ const Expr *Callee = CE->getCallee ()->IgnoreParens ();
317
+ const LocationContext *LCtx = C.getLocationContext ();
318
+ SVal L = State->getSVal (Callee, LCtx);
319
+
320
+ if (L.isUndef ()) {
321
+ if (!BT_call_undef)
322
+ BT_call_undef.reset (new BuiltinBug (
323
+ this , " Called function pointer is an uninitialized pointer value" ));
324
+ emitBadCall (BT_call_undef.get (), C, Callee);
325
+ return ;
326
+ }
343
327
344
- void CallAndMessageChecker::checkPreStmt (const CXXDeleteExpr *DE,
345
- CheckerContext &C) const {
328
+ ProgramStateRef StNonNull, StNull;
329
+ std::tie (StNonNull, StNull) =
330
+ State->assume (L.castAs <DefinedOrUnknownSVal>());
346
331
347
- SVal Arg = C. getSVal (DE-> getArgument ());
348
- if (Arg. isUndef ()) {
349
- StringRef Desc;
350
- ExplodedNode *N = C. generateErrorNode ( );
351
- if (!N)
332
+ if (StNull && !StNonNull) {
333
+ if (!BT_call_null)
334
+ BT_call_null. reset ( new BuiltinBug (
335
+ this , " Called function pointer is null (null dereference) " ) );
336
+ emitBadCall (BT_call_null. get (), C, Callee);
352
337
return ;
353
- if (!BT_cxx_delete_undef)
354
- BT_cxx_delete_undef.reset (
355
- new BuiltinBug (this , " Uninitialized argument value" ));
356
- if (DE->isArrayFormAsWritten ())
357
- Desc = " Argument to 'delete[]' is uninitialized" ;
358
- else
359
- Desc = " Argument to 'delete' is uninitialized" ;
360
- BugType *BT = BT_cxx_delete_undef.get ();
361
- auto R = std::make_unique<PathSensitiveBugReport>(*BT, Desc, N);
362
- bugreporter::trackExpressionValue (N, DE, *R);
363
- C.emitReport (std::move (R));
364
- return ;
365
- }
366
- }
338
+ }
367
339
368
- void CallAndMessageChecker::checkPreCall (const CallEvent &Call,
369
- CheckerContext &C) const {
370
- ProgramStateRef State = C.getState ();
340
+ State = StNonNull;
341
+ }
371
342
372
343
// If this is a call to a C++ method, check if the callee is null or
373
344
// undefined.
@@ -425,6 +396,30 @@ void CallAndMessageChecker::checkPreCall(const CallEvent &Call,
425
396
}
426
397
}
427
398
399
+ if (const auto *DC = dyn_cast<CXXDeallocatorCall>(&Call)) {
400
+ const CXXDeleteExpr *DE = DC->getOriginExpr ();
401
+ assert (DE);
402
+ SVal Arg = C.getSVal (DE->getArgument ());
403
+ if (Arg.isUndef ()) {
404
+ StringRef Desc;
405
+ ExplodedNode *N = C.generateErrorNode ();
406
+ if (!N)
407
+ return ;
408
+ if (!BT_cxx_delete_undef)
409
+ BT_cxx_delete_undef.reset (
410
+ new BuiltinBug (this , " Uninitialized argument value" ));
411
+ if (DE->isArrayFormAsWritten ())
412
+ Desc = " Argument to 'delete[]' is uninitialized" ;
413
+ else
414
+ Desc = " Argument to 'delete' is uninitialized" ;
415
+ BugType *BT = BT_cxx_delete_undef.get ();
416
+ auto R = std::make_unique<PathSensitiveBugReport>(*BT, Desc, N);
417
+ bugreporter::trackExpressionValue (N, DE, *R);
418
+ C.emitReport (std::move (R));
419
+ return ;
420
+ }
421
+ }
422
+
428
423
// Don't check for uninitialized field values in arguments if the
429
424
// caller has a body that is available and we have the chance to inline it.
430
425
// This is a hack, but is a reasonable compromise betweens sometimes warning
@@ -444,8 +439,8 @@ void CallAndMessageChecker::checkPreCall(const CallEvent &Call,
444
439
if (FD && i < FD->getNumParams ())
445
440
ParamDecl = FD->getParamDecl (i);
446
441
if (PreVisitProcessArg (C, Call.getArgSVal (i), Call.getArgSourceRange (i),
447
- Call.getArgExpr (i), i,
448
- checkUninitFields, Call, *BT, ParamDecl))
442
+ Call.getArgExpr (i), i, checkUninitFields, Call, *BT,
443
+ ParamDecl))
449
444
return ;
450
445
}
451
446
@@ -609,12 +604,13 @@ bool ento::shouldRegisterCallAndMessageChecker(const CheckerManager &mgr) {
609
604
return true ;
610
605
}
611
606
612
- void ento::registerCallAndMessageUnInitRefArg (CheckerManager &mgr) {
613
- CallAndMessageChecker *Checker = mgr.getChecker <CallAndMessageChecker>();
614
- Checker->Check_CallAndMessageUnInitRefArg = true ;
615
- Checker->CheckName_CallAndMessageUnInitRefArg = mgr.getCurrentCheckerName ();
616
- }
607
+ #define REGISTER_CHECKER (name ) \
608
+ void ento::register ##name(CheckerManager &mgr) { \
609
+ CallAndMessageChecker *checker = mgr.getChecker <CallAndMessageChecker>(); \
610
+ checker->ChecksEnabled [CallAndMessageChecker::CK_##name] = true ; \
611
+ \
612
+ } \
613
+ \
614
+ bool ento::shouldRegister##name(const CheckerManager &mgr) { return true ; }
617
615
618
- bool ento::shouldRegisterCallAndMessageUnInitRefArg (const CheckerManager &mgr) {
619
- return true ;
620
- }
616
+ REGISTER_CHECKER (CallAndMessageUnInitRefArg)
0 commit comments