]> granicus.if.org Git - clang/commitdiff
Extend memset/memcpy/memmove checking to include memcmp
authorMatt Beaumont-Gay <matthewbg@google.com>
Fri, 5 Aug 2011 00:22:34 +0000 (00:22 +0000)
committerMatt Beaumont-Gay <matthewbg@google.com>
Fri, 5 Aug 2011 00:22:34 +0000 (00:22 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@136950 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/Sema.h
lib/Sema/SemaChecking.cpp
test/SemaCXX/warn-memset-bad-sizeof.cpp

index c08df35dbb7f59d5def10bab01c798cbefcbfd7d..5363b50368dafd04f798a7eacf2ea461c1d032ab 100644 (file)
@@ -5992,16 +5992,16 @@ private:
                                  bool isPrintf);
 
   /// \brief Enumeration used to describe which of the memory setting or copying
-  /// functions is being checked by \c CheckMemsetcpymoveArguments().
+  /// functions is being checked by \c CheckMemaccessArguments().
   enum CheckedMemoryFunction {
     CMF_Memset,
     CMF_Memcpy,
-    CMF_Memmove
+    CMF_Memmove,
+    CMF_Memcmp
   };
   
-  void CheckMemsetcpymoveArguments(const CallExpr *Call, 
-                                   CheckedMemoryFunction CMF,
-                                   IdentifierInfo *FnName);
+  void CheckMemaccessArguments(const CallExpr *Call, CheckedMemoryFunction CMF,
+                               IdentifierInfo *FnName);
 
   void CheckReturnStackAddr(Expr *RetValExp, QualType lhsType,
                             SourceLocation ReturnLoc);
index 81ae7b3afb02aa6654ffe57422e6df884adb71a7..af6141e3aeb5c89e95da347dbdbd1d8c659bbb3d 100644 (file)
@@ -319,7 +319,7 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
                           TheCall->getCallee()->getLocStart());
   }
 
-  // Memset/memcpy/memmove handling
+  // Memset/memcpy/memmove/memcmp handling
   int CMF = -1;
   switch (FDecl->getBuiltinID()) {
   case Builtin::BI__builtin_memset:
@@ -340,6 +340,10 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
     CMF = CMF_Memmove;
     break;
     
+  case Builtin::BI__builtin_memcmp:
+    CMF = CMF_Memcmp;
+    break;
+    
   default:
     if (FDecl->getLinkage() == ExternalLinkage &&
         (!getLangOptions().CPlusPlus || FDecl->isExternC())) {
@@ -349,12 +353,14 @@ bool Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) {
         CMF = CMF_Memcpy;
       else if (FnInfo->isStr("memmove"))
         CMF = CMF_Memmove;
+      else if (FnInfo->isStr("memcmp"))
+        CMF = CMF_Memcmp;
     }
     break;
   }
    
   if (CMF != -1)
-    CheckMemsetcpymoveArguments(TheCall, CheckedMemoryFunction(CMF), FnInfo);
+    CheckMemaccessArguments(TheCall, CheckedMemoryFunction(CMF), FnInfo);
 
   return false;
 }
@@ -1881,12 +1887,13 @@ static QualType getSizeOfArgType(const Expr* E) {
 /// \brief Check for dangerous or invalid arguments to memset().
 ///
 /// This issues warnings on known problematic, dangerous or unspecified
-/// arguments to the standard 'memset', 'memcpy', and 'memmove' function calls.
+/// arguments to the standard 'memset', 'memcpy', 'memmove', and 'memcmp'
+/// function calls.
 ///
 /// \param Call The call expression to diagnose.
-void Sema::CheckMemsetcpymoveArguments(const CallExpr *Call,
-                                       CheckedMemoryFunction CMF,
-                                       IdentifierInfo *FnName) {
+void Sema::CheckMemaccessArguments(const CallExpr *Call,
+                                   CheckedMemoryFunction CMF,
+                                   IdentifierInfo *FnName) {
   // It is possible to have a non-standard definition of memset.  Validate
   // we have enough arguments, and if not, abort further checking.
   if (Call->getNumArgs() < 3)
index 90ac50472e98df065f9a4563a5f32513962bb8df..f4876ab442fc5488072002fe2b1c3f079b7df11b 100644 (file)
@@ -3,6 +3,7 @@
 extern "C" void *memset(void *, int, unsigned);
 extern "C" void *memmove(void *s1, const void *s2, unsigned n);
 extern "C" void *memcpy(void *s1, const void *s2, unsigned n);
+extern "C" void *memcmp(void *s1, const void *s2, unsigned n);
 
 struct S {int a, b, c, d;};
 typedef S* PS;
@@ -51,6 +52,11 @@ void f(Mat m, const Foo& const_foo, char *buffer) {
   memcpy(0, &s, sizeof(&s));  // \
       // expected-warning {{argument to 'sizeof' in 'memcpy' call is the same expression as the source}}
 
+  memmove(ps, 0, sizeof(ps));  // \
+      // expected-warning {{argument to 'sizeof' in 'memmove' call is the same expression as the destination}}
+  memcmp(ps, 0, sizeof(ps));  // \
+      // expected-warning {{argument to 'sizeof' in 'memcmp' call is the same expression as the destination}}
+
   /* Shouldn't warn */
   memset((void*)&s, 0, sizeof(&s));
   memset(&s, 0, sizeof(s));
@@ -99,3 +105,10 @@ void f(Mat m, const Foo& const_foo, char *buffer) {
   memcpy(&foo, &arr, sizeof(Foo));
   memcpy(&arr, &foo, sizeof(Foo));
 }
+
+namespace ns {
+void memset(void* s, char c, int n);
+void f(int* i) {
+  memset(i, 0, sizeof(i));
+}
+}