r184288 - Fix a crash in the static analyzer (bug #16307)

Pavel Labath labath at google.com
Wed Jun 19 01:19:57 PDT 2013


Author: labath
Date: Wed Jun 19 03:19:56 2013
New Revision: 184288

URL: http://llvm.org/viewvc/llvm-project?rev=184288&view=rev
Log:
Fix a crash in the static analyzer (bug #16307)

Summary:
When processing a call to a function, which got passed less arguments than it
expects, the analyzer would crash.

I've also added a test for that and a analyzer warning which detects these
cases.

CC: cfe-commits

Differential Revision: http://llvm-reviews.chandlerc.com/D994

Modified:
    cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp
    cfe/trunk/test/Analysis/inline.c
    cfe/trunk/test/Analysis/inline.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp?rev=184288&r1=184287&r2=184288&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp Wed Jun 19 03:19:56 2013
@@ -40,6 +40,7 @@ class CallAndMessageChecker
   mutable OwningPtr<BugType> BT_objc_subscript_undef;
   mutable OwningPtr<BugType> BT_msg_arg;
   mutable OwningPtr<BugType> BT_msg_ret;
+  mutable OwningPtr<BugType> BT_call_few_args;
 public:
 
   void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
@@ -280,11 +281,33 @@ void CallAndMessageChecker::checkPreCall
     State = StNonNull;
   }
 
+  const Decl *D = Call.getDecl();
+  if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) {
+    // If we have a declaration, we can make sure we pass enough parameters to
+    // the function.
+    unsigned Params = FD->getNumParams();
+    if (Call.getNumArgs() < Params) {
+      ExplodedNode *N = C.generateSink();
+      if (!N)
+        return;
+
+      LazyInit_BT("Function call with too few arguments", BT_call_few_args);
+
+      SmallString<512> Str;
+      llvm::raw_svector_ostream os(Str);
+      os << "Function taking " << Params << " argument"
+         << (Params == 1 ? "" : "s") << " is called with less ("
+         << Call.getNumArgs() << ")";
+
+      BugReport *R = new BugReport(*BT_call_few_args, os.str(), N);
+      C.emitReport(R);
+    }
+  }
+
   // Don't check for uninitialized field values in arguments if the
   // caller has a body that is available and we have the chance to inline it.
   // This is a hack, but is a reasonable compromise betweens sometimes warning
   // and sometimes not depending on if we decide to inline a function.
-  const Decl *D = Call.getDecl();
   const bool checkUninitFields =
     !(C.getAnalysisManager().shouldInlineCall() && (D && D->getBody()));
 

Modified: cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp?rev=184288&r1=184287&r2=184288&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp Wed Jun 19 03:19:56 2013
@@ -272,8 +272,11 @@ static void addParameterValuesToBindings
                                          CallEvent::param_iterator E) {
   MemRegionManager &MRMgr = SVB.getRegionManager();
 
+  // If the function has fewer parameters than the call has arguments, we simply
+  // do not bind any values to them.
+  unsigned NumArgs = Call.getNumArgs();
   unsigned Idx = 0;
-  for (; I != E; ++I, ++Idx) {
+  for (; I != E && Idx < NumArgs; ++I, ++Idx) {
     const ParmVarDecl *ParamDecl = *I;
     assert(ParamDecl && "Formal parameter has no decl?");
 

Modified: cfe/trunk/test/Analysis/inline.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/inline.c?rev=184288&r1=184287&r2=184288&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/inline.c (original)
+++ cfe/trunk/test/Analysis/inline.c Wed Jun 19 03:19:56 2013
@@ -110,3 +110,9 @@ void never_called_by_anyone() {
   clang_analyzer_checkInlined(0); // no-warning
 }
 
+
+void knr_one_argument(a) int a; { }
+
+void call_with_less_arguments() {
+  knr_one_argument(); // expected-warning{{too few arguments}} expected-warning{{Function taking 1 argument}}
+}

Modified: cfe/trunk/test/Analysis/inline.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/inline.cpp?rev=184288&r1=184287&r2=184288&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/inline.cpp (original)
+++ cfe/trunk/test/Analysis/inline.cpp Wed Jun 19 03:19:56 2013
@@ -420,3 +420,10 @@ namespace rdar12409977  {
     clang_analyzer_eval(obj.getThis()->x == 42); // expected-warning{{TRUE}}
   }
 }
+
+namespace bug16307 {
+  void one_argument(int a) { }
+  void call_with_less() {
+    reinterpret_cast<void (*)()>(one_argument)(); // expected-warning{{Function taking 1 argument}}
+  }
+}





More information about the cfe-commits mailing list