r371256 - [analyzer] pr43179: Make CallDescription defensive against C variadic functions.

Artem Dergachev via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 6 13:55:25 PDT 2019


Author: dergachev
Date: Fri Sep  6 13:55:24 2019
New Revision: 371256

URL: http://llvm.org/viewvc/llvm-project?rev=371256&view=rev
Log:
[analyzer] pr43179: Make CallDescription defensive against C variadic functions.

Most functions that our checkers react upon are not C-style variadic functions,
and therefore they have as many actual arguments as they have formal parameters.

However, it's not impossible to define a variadic function with the same name.
This will crash any checker that relies on CallDescription to check the number
of arguments but silently assumes that the number of parameters is the same.

Change CallDescription to check both the number of arguments and the number of
parameters by default.

If we're intentionally trying to match variadic functions, allow specifying
arguments and parameters separately (possibly omitting any of them).
For now we only have one CallDescription which would make use of those,
namely __builtin_va_start itself.

Differential Revision: https://reviews.llvm.org/D67019

Added:
    cfe/trunk/test/Analysis/cast-value-weird.cpp
Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
    cfe/trunk/lib/StaticAnalyzer/Checkers/ValistChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h?rev=371256&r1=371255&r2=371256&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h Fri Sep  6 13:55:24 2019
@@ -1064,8 +1064,19 @@ class CallDescription {
   // e.g. "{a, b}" represent the qualified names, like "a::b".
   std::vector<const char *> QualifiedName;
   Optional<unsigned> RequiredArgs;
+  Optional<size_t> RequiredParams;
   int Flags;
 
+  // A constructor helper.
+  static Optional<size_t> readRequiredParams(Optional<unsigned> RequiredArgs,
+                                             Optional<size_t> RequiredParams) {
+    if (RequiredParams)
+      return RequiredParams;
+    if (RequiredArgs)
+      return static_cast<size_t>(*RequiredArgs);
+    return None;
+  }
+
 public:
   /// Constructs a CallDescription object.
   ///
@@ -1078,14 +1089,17 @@ public:
   /// call. Omit this parameter to match every occurrence of call with a given
   /// name regardless the number of arguments.
   CallDescription(int Flags, ArrayRef<const char *> QualifiedName,
-                  Optional<unsigned> RequiredArgs = None)
+                  Optional<unsigned> RequiredArgs = None,
+                  Optional<size_t> RequiredParams = None)
       : QualifiedName(QualifiedName), RequiredArgs(RequiredArgs),
+        RequiredParams(readRequiredParams(RequiredArgs, RequiredParams)),
         Flags(Flags) {}
 
   /// Construct a CallDescription with default flags.
   CallDescription(ArrayRef<const char *> QualifiedName,
-                  Optional<unsigned> RequiredArgs = None)
-      : CallDescription(0, QualifiedName, RequiredArgs) {}
+                  Optional<unsigned> RequiredArgs = None,
+                  Optional<size_t> RequiredParams = None)
+      : CallDescription(0, QualifiedName, RequiredArgs, RequiredParams) {}
 
   /// Get the name of the function that this object matches.
   StringRef getFunctionName() const { return QualifiedName.back(); }

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/ValistChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/ValistChecker.cpp?rev=371256&r1=371255&r2=371256&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/ValistChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/ValistChecker.cpp Fri Sep  6 13:55:24 2019
@@ -116,7 +116,9 @@ const SmallVector<ValistChecker::VAListA
         // vswprintf is the wide version of vsnprintf,
         // vsprintf has no wide version
         {{"vswscanf", 3}, 2}};
-const CallDescription ValistChecker::VaStart("__builtin_va_start", 2),
+
+const CallDescription
+    ValistChecker::VaStart("__builtin_va_start", /*Args=*/2, /*Params=*/1),
     ValistChecker::VaCopy("__builtin_va_copy", 2),
     ValistChecker::VaEnd("__builtin_va_end", 1);
 } // end anonymous namespace

Modified: cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp?rev=371256&r1=371255&r2=371256&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp Fri Sep  6 13:55:24 2019
@@ -368,7 +368,8 @@ bool CallEvent::isCalled(const CallDescr
 
   if (CD.Flags & CDF_MaybeBuiltin) {
     return CheckerContext::isCLibraryFunction(FD, CD.getFunctionName()) &&
-           (!CD.RequiredArgs || CD.RequiredArgs <= getNumArgs());
+           (!CD.RequiredArgs || CD.RequiredArgs <= getNumArgs()) &&
+           (!CD.RequiredParams || CD.RequiredParams <= parameters().size());
   }
 
   if (!CD.IsLookupDone) {
@@ -407,7 +408,8 @@ bool CallEvent::isCalled(const CallDescr
       return false;
   }
 
-  return (!CD.RequiredArgs || CD.RequiredArgs == getNumArgs());
+  return (!CD.RequiredArgs || CD.RequiredArgs == getNumArgs()) &&
+         (!CD.RequiredParams || CD.RequiredParams == parameters().size());
 }
 
 SVal CallEvent::getArgSVal(unsigned Index) const {

Added: cfe/trunk/test/Analysis/cast-value-weird.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cast-value-weird.cpp?rev=371256&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/cast-value-weird.cpp (added)
+++ cfe/trunk/test/Analysis/cast-value-weird.cpp Fri Sep  6 13:55:24 2019
@@ -0,0 +1,9 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,apiModeling -verify %s
+
+// expected-no-diagnostics
+
+namespace llvm {
+template <typename>
+void cast(...);
+void a() { cast<int>(int()); } // no-crash
+} // namespace llvm




More information about the cfe-commits mailing list