diff options
author | Ted Kremenek <kremenek@apple.com> | 2009-11-21 01:25:37 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2009-11-21 01:25:37 +0000 |
commit | c79d7d49c5ec42e8bb6ac34350ebb5bc24ca663d (patch) | |
tree | 81bb9b03ff5e625bc5005514329598719b8cf30e /lib/Analysis/UndefinedArgChecker.cpp | |
parent | 9cf910efc4fb7001a6d276ed2eabf01f0f0efaaa (diff) |
Pull BadCallChecker int UndefinedArgChecker, and have UndefinedArgChecker also handled undefined receivers in message expressions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89524 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/UndefinedArgChecker.cpp')
-rw-r--r-- | lib/Analysis/UndefinedArgChecker.cpp | 84 |
1 files changed, 70 insertions, 14 deletions
diff --git a/lib/Analysis/UndefinedArgChecker.cpp b/lib/Analysis/UndefinedArgChecker.cpp index a0c0d48712..ea7d971fdb 100644 --- a/lib/Analysis/UndefinedArgChecker.cpp +++ b/lib/Analysis/UndefinedArgChecker.cpp @@ -21,16 +21,23 @@ using namespace clang; namespace { class VISIBILITY_HIDDEN UndefinedArgChecker : public CheckerVisitor<UndefinedArgChecker> { - BugType *BT_call; - BugType *BT_msg; + BugType *BT_call_null; + BugType *BT_call_undef; + BugType *BT_call_arg; + BugType *BT_msg_undef; + BugType *BT_msg_arg; public: - UndefinedArgChecker() : BT_call(0), BT_msg(0) {} + UndefinedArgChecker() : + BT_call_null(0), BT_call_undef(0), BT_call_arg(0), + BT_msg_undef(0), BT_msg_arg(0) {} static void *getTag() { static int x = 0; return &x; } void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE); void PreVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *ME); +private: + void EmitBadCall(BugType *BT, CheckerContext &C, const CallExpr *CE); }; } // end anonymous namespace @@ -38,18 +45,49 @@ void clang::RegisterUndefinedArgChecker(GRExprEngine &Eng) { Eng.registerCheck(new UndefinedArgChecker()); } +void UndefinedArgChecker::EmitBadCall(BugType *BT, CheckerContext &C, + const CallExpr *CE) { + ExplodedNode *N = C.GenerateNode(CE, true); + if (!N) + return; + + EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getName(), N); + R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, + bugreporter::GetCalleeExpr(N)); + C.EmitReport(R); +} + void UndefinedArgChecker::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE){ + + const Expr *Callee = CE->getCallee()->IgnoreParens(); + SVal L = C.getState()->getSVal(Callee); + + if (L.isUndef()) { + if (!BT_call_undef) + BT_call_undef = + new BuiltinBug("Called function pointer is an undefined pointer value"); + EmitBadCall(BT_call_undef, C, CE); + return; + } + + if (isa<loc::ConcreteInt>(L)) { + if (!BT_call_null) + BT_call_null = + new BuiltinBug("Called function pointer is null (null dereference)"); + EmitBadCall(BT_call_null, C, CE); + } + for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) { if (C.getState()->getSVal(*I).isUndef()) { if (ExplodedNode *N = C.GenerateNode(CE, true)) { - if (!BT_call) - BT_call = new BuiltinBug("Pass-by-value argument in function call is " - "undefined"); + if (!BT_call_arg) + BT_call_arg = new BuiltinBug("Pass-by-value argument in function call" + " is undefined"); // Generate a report for this bug. - EnhancedBugReport *R = new EnhancedBugReport(*BT_call, - BT_call->getName(), N); + EnhancedBugReport *R = new EnhancedBugReport(*BT_call_arg, + BT_call_arg->getName(), N); R->addRange((*I)->getSourceRange()); R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, *I); C.EmitReport(R); @@ -62,18 +100,36 @@ void UndefinedArgChecker::PreVisitCallExpr(CheckerContext &C, void UndefinedArgChecker::PreVisitObjCMessageExpr(CheckerContext &C, const ObjCMessageExpr *ME) { - // Check for any arguments that are uninitialized/undefined. const GRState *state = C.getState(); + + if (const Expr *receiver = ME->getReceiver()) + if (state->getSVal(receiver).isUndef()) { + if (ExplodedNode *N = C.GenerateNode(ME, true)) { + if (!BT_msg_undef) + BT_msg_undef = + new BuiltinBug("Receiver in message expression is a garbage value"); + EnhancedBugReport *R = + new EnhancedBugReport(*BT_msg_undef, BT_msg_undef->getName(), N); + R->addRange(receiver->getSourceRange()); + R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, + receiver); + C.EmitReport(R); + } + return; + } + + // Check for any arguments that are uninitialized/undefined. for (ObjCMessageExpr::const_arg_iterator I = ME->arg_begin(), E = ME->arg_end(); I != E; ++I) { if (state->getSVal(*I).isUndef()) { if (ExplodedNode *N = C.GenerateNode(ME, true)) { - if (!BT_msg) - BT_msg = new BuiltinBug("Pass-by-value argument in message expression" - " is undefined"); + if (!BT_msg_arg) + BT_msg_arg = + new BuiltinBug("Pass-by-value argument in message expression" + " is undefined"); // Generate a report for this bug. - EnhancedBugReport *R = new EnhancedBugReport(*BT_msg, BT_msg->getName(), - N); + EnhancedBugReport *R = new EnhancedBugReport(*BT_msg_arg, + BT_msg_arg->getName(), N); R->addRange((*I)->getSourceRange()); R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, *I); C.EmitReport(R); |