ariccio updated this revision to Diff 55774.
ariccio added a comment.

Only check for MSVC-specific functions when actually building FOR MSVC (i.e. 
`isWindowsMSVCEnvironment`).

Sidenote: is there any reason why none of the `ASTContext&`s are `const`ified 
in this file?


http://reviews.llvm.org/D18073

Files:
  llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
  llvm/tools/clang/test/Analysis/alternative-malloc-api.c
  llvm/tools/clang/test/Analysis/malloc.c

Index: llvm/tools/clang/test/Analysis/alternative-malloc-api.c
===================================================================
--- llvm/tools/clang/test/Analysis/alternative-malloc-api.c
+++ llvm/tools/clang/test/Analysis/alternative-malloc-api.c
@@ -0,0 +1,100 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.deadcode.UnreachableCode,alpha.core.CastSize,unix.Malloc,debug.ExprInspection -analyzer-store=region -verify %s
+
+#include "Inputs/system-header-simulator.h"
+
+// Without -fms-compatibility, wchar_t isn't a builtin type. MSVC defines
+// _WCHAR_T_DEFINED if wchar_t is available. Microsoft recommends that you use
+// the builtin type: "Using the typedef version can cause portability
+// problems", but we're ok here because we're not actually running anything.
+// Also of note is this cryptic warning: "The wchar_t type is not supported
+// when you compile C code".
+//
+// See the docs for more:
+// https://msdn.microsoft.com/en-us/library/dh8che7s.aspx
+#if !defined(_WCHAR_T_DEFINED)
+// "Microsoft implements wchar_t as a two-byte unsigned value"
+typedef unsigned short wchar_t;
+#define _WCHAR_T_DEFINED
+#endif // !defined(_WCHAR_T_DEFINED)
+
+void free(void *);
+
+char *tempnam(const char *dir, const char *pfx);
+
+void testTempnamLeak(const char* dir, const char* prefix) {
+  char* fileName = tempnam(dir, prefix);
+}// expected-warning {{Potential leak of memory pointed to by}}
+
+void testTempnamNoLeak(const char* dir, const char* prefix) {
+  char* fileName = tempnam(dir, prefix);
+  free(fileName);// no warning
+}
+
+
+// What does "ContentIsDefined" refer to?
+void testTempnamNoLeakContentIsDefined(const char* dir, const char* prefix) {
+  char* fileName = tempnam(dir, prefix);
+  char result = fileName[0];// no warning
+  free(fileName);
+}
+
+#if defined(_WIN32)
+char *_tempnam(const char *dir, const char *prefix);
+wchar_t *_wtempnam(const wchar_t *dir, const wchar_t *prefix);
+
+char *_tempnam_dbg(const char *dir, const char *prefix, int blockType,
+                   const char *filename, int linenumber);
+
+wchar_t *_wtempnam_dbg(const wchar_t *dir, const wchar_t *prefix,
+                       int blockType, const char *filename, int linenumber);
+
+void testWinTempnamLeak(const char* dir, const char* prefix) {
+  char* fileName = _tempnam(dir, prefix);
+}// expected-warning {{Potential leak of memory pointed to by}}
+
+void testWinTempnamDbgLeak(const char* dir, const char* prefix) {
+  char* fileName = _tempnam_dbg(dir, prefix, 0, __FILE__, __LINE__);
+}// expected-warning {{Potential leak of memory pointed to by}}
+
+void testWinWideTempnamLeak(const wchar_t* dir, const wchar_t* prefix) {
+  wchar_t* fileName = _wtempnam(dir, prefix);
+}// expected-warning {{Potential leak of memory pointed to by}}
+
+void testWinWideTempnaDbgmLeak(const wchar_t* dir, const wchar_t* prefix) {
+  wchar_t* fileName = _wtempnam_dbg(dir, prefix, 0, __FILE__, __LINE__);
+}// expected-warning {{Potential leak of memory pointed to by}}
+
+void testWinTempnamNoLeak(const char* dir, const char* prefix) {
+  char* fileName = _tempnam(dir, prefix);
+  free(fileName);// no warning
+}
+
+void testWinTempnamDbgNoLeak(const char* dir, const char* prefix) {
+  char* fileName = _tempnam_dbg(dir, prefix, 0, __FILE__, __LINE__);
+  free(fileName);// no warning
+}
+
+void testWinWideTempnamNoLeak(const wchar_t* dir, const wchar_t* prefix) {
+  wchar_t* fileName = _wtempnam(dir, prefix);
+  free(fileName);// no warning
+}
+
+void testWinWideTempnamDbgNoLeak(const wchar_t* dir, const wchar_t* prefix) {
+  wchar_t* fileName = _wtempnam_dbg(dir, prefix, 0, __FILE__, __LINE__);
+  free(fileName);// no warning
+}
+
+// What does "ContentIsDefined" refer to?
+void testWinTempnamNoLeakContentIsDefined(const char* dir, const char* prefix) {
+  char* fileName = _tempnam(dir, prefix);
+  char result = fileName[0];// no warning
+  free(fileName);
+}
+
+// What does "ContentIsDefined" refer to?
+void testWinWideTempnamNoLeakContentIsDefined(const wchar_t* dir, const wchar_t* prefix) {
+  wchar_t* fileName = _wtempnam(dir, prefix);
+  wchar_t result = fileName[0];// no warning
+  free(fileName);
+}
+#endif //defined(_WIN32)
Index: llvm/tools/clang/test/Analysis/malloc.c
===================================================================
--- llvm/tools/clang/test/Analysis/malloc.c
+++ llvm/tools/clang/test/Analysis/malloc.c
@@ -32,11 +32,37 @@
 char *strndup(const char *s, size_t n);
 int memcmp(const void *s1, const void *s2, size_t n);
 
+
 // Windows variants
+#if defined(_WIN32)
 char *_strdup(const char *strSource);
 wchar_t *_wcsdup(const wchar_t *strSource);
+unsigned char *_mbsdup(const unsigned char *strSource);
+
 void *_alloca(size_t size);
 
+void *_calloc_dbg(size_t num, size_t size, int blockType,
+                  const char *filename, int linenumber);
+
+char *_strdup_dbg(const char *strSource, int blockType,
+                  const char *filename, int linenumber);
+
+wchar_t *_wcsdup_dbg(const wchar_t *strSource, int blockType,
+                     const char *filename, int linenumber);
+
+unsigned char *_mbsdup_dbg(const unsigned char *strSource, int blockType,
+                           const char *filename, int linenumber);
+
+
+// Very frequently used debug versions
+void _free_dbg(void *userData, int blockType);
+void _malloc_dbg(size_t size, int blockType, const char *filename,
+                 int linenumber);
+
+void *_realloc_dbg(void *userData, size_t newSize,
+                   int blockType, const char *filename, int linenumber);
+#endif //defined(_WIN32)
+
 void myfoo(int *p);
 void myfooint(int p);
 char *fooRetPtr();
@@ -76,9 +102,11 @@
   int *p = alloca(sizeof(int));
 } // no warn
 
+#if defined(_WIN32)
 void winAllocaTest() {
   int *p = _alloca(sizeof(int));
 } // no warn
+#endif //defined(_WIN32)
 
 void allocaBuiltinTest() {
   int *p = __builtin_alloca(sizeof(int));
@@ -235,11 +263,12 @@
   int *p = alloca(0); // no warning
 }
 
+#if defined(_WIN32)
 void CheckUseZeroWinAllocatedNoWarn2() {
   int *p = _alloca(0); // no warning
 }
+#endif //defined(_WIN32)
 
-
 void CheckUseZeroAllocatedNoWarn3() {
   int *p = malloc(0);
   int *q = realloc(p, 8); // no warning
@@ -263,10 +292,12 @@
   return *p; // expected-warning {{Use of zero-allocated memory}}
 }
 
+#if defined(_WIN32)
 char CheckUseZeroWinAllocated2() {
   char *p = _alloca(0);
   return *p; // expected-warning {{Use of zero-allocated memory}}
 }
+#endif //defined(_WIN32)
 
 void UseZeroAllocated(int *p) {
   if (p)
@@ -290,26 +321,42 @@
   free(p);
 }
 
+#if defined(_WIN32)
 void CheckUseZeroAllocated6() {
+  int *p = _calloc_dbg(0, 2, 0, __FILE__, __LINE__);
+  *p = 1; // expected-warning {{Use of zero-allocated memory}}
+  free(p);
+}
+#endif //defined(_WIN32)
+
+void CheckUseZeroAllocated7() {
   int *p = calloc(2, 0);
   *p = 1; // expected-warning {{Use of zero-allocated memory}}
   free(p);
 }
 
-void CheckUseZeroAllocated7() {
+#if defined(_WIN32)
+void CheckUseZeroAllocated8() {
+  int *p = _calloc_dbg(2, 0, 0, __FILE__, __LINE__);
+  *p = 1; // expected-warning {{Use of zero-allocated memory}}
+  free(p);
+}
+#endif //defined(_WIN32)
+
+void CheckUseZeroAllocated9() {
   int *p = realloc(0, 0);
   *p = 1; // expected-warning {{Use of zero-allocated memory}}
   free(p);
 }
 
-void CheckUseZeroAllocated8() {
+void CheckUseZeroAllocated10() {
   int *p = malloc(8);
   int *q = realloc(p, 0);
   *q = 1; // expected-warning {{Use of zero-allocated memory}}
   free(q);
 }
 
-void CheckUseZeroAllocated9() {
+void CheckUseZeroAllocated11() {
   int *p = realloc(0, 0);
   int *q = realloc(p, 0);
   *q = 1; // expected-warning {{Use of zero-allocated memory}}
@@ -1071,7 +1118,6 @@
   free(p);
 }
 
-
 // The same test as the one above, but with what is actually generated on a mac.
 static __inline char *
 __inline_strcpy_chk (char *restrict __dest, const char *restrict __src)
@@ -1111,21 +1157,47 @@
   s2[validIndex + 1] = 'b';
 } // expected-warning {{Potential leak of memory pointed to by}}
 
+#if defined(_WIN32)
 void testWinStrdup(const char *s, unsigned validIndex) {
   char *s2 = _strdup(s);
   s2[validIndex + 1] = 'b';
 } // expected-warning {{Potential leak of memory pointed to by}}
 
+void testWinWcsdup(const wchar_t *s, unsigned validIndex) {
+  wchar_t *s2 = _wcsdup(s);
+  s2[validIndex + 1] = 'b';
+} // expected-warning {{Potential leak of memory pointed to by}}
+
+void testWinMbsdup(const unsigned char *s, unsigned validIndex) {
+  unsigned char *s2 = _mbsdup(s);
+  s2[validIndex + 1] = 'b';
+} // expected-warning {{Potential leak of memory pointed to by}}
+
+#endif // defined(_WIN32)
+
 void testWcsdup(const wchar_t *s, unsigned validIndex) {
   wchar_t *s2 = wcsdup(s);
   s2[validIndex + 1] = 'b';
 } // expected-warning {{Potential leak of memory pointed to by}}
 
-void testWinWcsdup(const wchar_t *s, unsigned validIndex) {
-  wchar_t *s2 = _wcsdup(s);
+
+#if defined(_WIN32)
+void testWinMbsdupDbg(const unsigned char *s, unsigned validIndex) {
+  unsigned char *s2 = _mbsdup_dbg(s, 0, __FILE__, __LINE__);
   s2[validIndex + 1] = 'b';
 } // expected-warning {{Potential leak of memory pointed to by}}
 
+void testStrdupDbg(const char *s, unsigned validIndex) {
+  char *s2 = _strdup_dbg(s, 0, __FILE__, __LINE__);
+  s2[validIndex + 1] = 'b';
+} // expected-warning {{Potential leak of memory pointed to by}}
+
+void testWinWcsdupDbg(const wchar_t *s, unsigned validIndex) {
+  wchar_t *s2 = _wcsdup_dbg(s, 0, __FILE__, __LINE__);
+  s2[validIndex + 1] = 'b';
+} // expected-warning {{Potential leak of memory pointed to by}}
+#endif //defined(_WIN32)
+
 int testStrndup(const char *s, unsigned validIndex, unsigned size) {
   char *s2 = strndup(s, size);
   s2 [validIndex + 1] = 'b';
@@ -1141,24 +1213,33 @@
   free(s2);
 }
 
+#if defined(_WIN32)
 void testWinStrdupContentIsDefined(const char *s, unsigned validIndex) {
   char *s2 = _strdup(s);
   char result = s2[1];// no warning
   free(s2);
 }
-
-void testWcsdupContentIsDefined(const wchar_t *s, unsigned validIndex) {
-  wchar_t *s2 = wcsdup(s);
+void testWinWcsdupContentIsDefined(const wchar_t *s, unsigned validIndex) {
+  wchar_t *s2 = _wcsdup(s);
   wchar_t result = s2[1];// no warning
   free(s2);
 }
+void testWinMbsdupContentIsDefined(const unsigned char *s, unsigned validIndex) {
+  unsigned char *s2 = _mbsdup(s);
+  unsigned char result = s2[1];// no warning
+  free(s2);
+}
 
-void testWinWcsdupContentIsDefined(const wchar_t *s, unsigned validIndex) {
-  wchar_t *s2 = _wcsdup(s);
+#endif // defined(_WIN32)
+
+void testWcsdupContentIsDefined(const wchar_t *s, unsigned validIndex) {
+  wchar_t *s2 = wcsdup(s);
   wchar_t result = s2[1];// no warning
   free(s2);
 }
 
+
+
 // ----------------------------------------------------------------------------
 // Test the system library functions to which the pointer can escape.
 // This tests false positive suppression.
@@ -1507,19 +1588,30 @@
   return newPtr;
 }
 
-
 char *testLeakWithinReturn(char *str) {
   return strdup(strdup(str)); // expected-warning{{leak}}
 }
 
+#if defined(_WIN32)
 char *testWinLeakWithinReturn(char *str) {
   return _strdup(_strdup(str)); // expected-warning{{leak}}
 }
 
 wchar_t *testWinWideLeakWithinReturn(wchar_t *str) {
   return _wcsdup(_wcsdup(str)); // expected-warning{{leak}}
 }
 
+unsigned char *testWinMbsLeakWithinReturn(unsigned char *str) {
+  return _mbsdup(_mbsdup(str)); // expected-warning{{leak}}
+}
+
+#endif //defined(_WIN32)
+
+wchar_t *testWideLeakWithinReturn(wchar_t *str) {
+  return wcsdup(wcsdup(str)); // expected-warning{{leak}}
+}
+
+
 void passConstPtr(const char * ptr);
 
 void testPassConstPointer() {
Index: llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
===================================================================
--- llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -174,7 +174,13 @@
         II_valloc(nullptr), II_reallocf(nullptr), II_strndup(nullptr),
         II_strdup(nullptr), II_win_strdup(nullptr), II_kmalloc(nullptr),
         II_if_nameindex(nullptr), II_if_freenameindex(nullptr),
-        II_wcsdup(nullptr), II_win_wcsdup(nullptr) {}
+        II_wcsdup(nullptr), II_wtempnam(nullptr), II_tempnam(nullptr),
+        II_win_wcsdup(nullptr), II_malloc_dbg(nullptr), II_free_dbg(nullptr),
+        II_realloc_dbg(nullptr), II_calloc_dbg(nullptr),
+        II_wcsdup_dbg(nullptr), II_strdup_dbg(nullptr), II_mbsdup(nullptr),
+        II_mbsdup_dbg(nullptr), II_win_tempnam(nullptr),
+        II_win_tempnam_dbg(nullptr),
+        II_wtempnam_dbg(nullptr) {}
 
   /// In pessimistic mode, the checker assumes that it does not know which
   /// functions might free the memory.
@@ -234,9 +240,14 @@
   mutable std::unique_ptr<BugType> BT_UseZerroAllocated[CK_NumCheckKinds];
   mutable IdentifierInfo *II_alloca, *II_win_alloca, *II_malloc, *II_free,
                          *II_realloc, *II_calloc, *II_valloc, *II_reallocf,
-                         *II_strndup, *II_strdup, *II_win_strdup, *II_kmalloc,
+                         *II_strndup, *II_strdup, *II_kmalloc,
                          *II_if_nameindex, *II_if_freenameindex, *II_wcsdup,
-                         *II_win_wcsdup;
+                         *II_tempnam, *II_wtempnam,
+                         *II_win_wcsdup, *II_malloc_dbg, *II_free_dbg,
+                         *II_realloc_dbg, *II_calloc_dbg, *II_wcsdup_dbg,
+                         *II_strdup_dbg, *II_mbsdup, *II_mbsdup_dbg,
+                         *II_win_tempnam, *II_win_tempnam_dbg, *II_wtempnam_dbg,
+                         *II_win_strdup;
   mutable Optional<uint64_t> KernelZeroFlagVal;
 
   void initIdentifierInfo(ASTContext &C) const;
@@ -543,14 +554,35 @@
   II_strdup = &Ctx.Idents.get("strdup");
   II_strndup = &Ctx.Idents.get("strndup");
   II_wcsdup = &Ctx.Idents.get("wcsdup");
+  
   II_kmalloc = &Ctx.Idents.get("kmalloc");
   II_if_nameindex = &Ctx.Idents.get("if_nameindex");
   II_if_freenameindex = &Ctx.Idents.get("if_freenameindex");
 
-  //MSVC uses `_`-prefixed instead, so we check for them too.
-  II_win_strdup = &Ctx.Idents.get("_strdup");
-  II_win_wcsdup = &Ctx.Idents.get("_wcsdup");
-  II_win_alloca = &Ctx.Idents.get("_alloca");
+  II_tempnam = &Ctx.Idents.get("tempnam");
+
+  // MSVC uses `_`-prefixed instead, so we check for them too.
+  if (Ctx.getTargetInfo().getTriple().isWindowsMSVCEnvironment()) {
+    II_win_tempnam = &Ctx.Idents.get("_tempnam");
+
+    II_mbsdup = &Ctx.Idents.get("_mbsdup");
+    
+    II_win_strdup = &Ctx.Idents.get("_strdup");
+    II_win_wcsdup = &Ctx.Idents.get("_wcsdup");
+    II_win_alloca = &Ctx.Idents.get("_alloca");
+
+    II_malloc_dbg = &Ctx.Idents.get("_malloc_dbg");
+    II_free_dbg = &Ctx.Idents.get("_free_dbg");
+    II_realloc_dbg = &Ctx.Idents.get("_realloc_dbg");
+    II_calloc_dbg = &Ctx.Idents.get("_calloc_dbg");
+    II_wcsdup_dbg = &Ctx.Idents.get("_wcsdup_dbg");
+    II_strdup_dbg = &Ctx.Idents.get("_strdup_dbg");
+    II_mbsdup_dbg = &Ctx.Idents.get("_mbsdup_dbg");
+
+    II_win_tempnam_dbg = &Ctx.Idents.get("_tempnam_dbg");
+    II_wtempnam = &Ctx.Idents.get("_wtempnam");
+    II_wtempnam_dbg = &Ctx.Idents.get("_wtempnam_dbg");
+  }
 }
 
 bool MallocChecker::isMemFunction(const FunctionDecl *FD, ASTContext &C) const {
@@ -586,16 +618,23 @@
     initIdentifierInfo(C);
 
     if (Family == AF_Malloc && CheckFree) {
-      if (FunI == II_free || FunI == II_realloc || FunI == II_reallocf)
+      if (FunI == II_free || FunI == II_realloc || FunI == II_reallocf ||
+          FunI == II_free_dbg || FunI == II_realloc_dbg)
         return true;
     }
 
     if (Family == AF_Malloc && CheckAlloc) {
       if (FunI == II_malloc || FunI == II_realloc || FunI == II_reallocf ||
           FunI == II_calloc || FunI == II_valloc || FunI == II_strdup ||
-          FunI == II_win_strdup || FunI == II_strndup || FunI == II_wcsdup ||
-          FunI == II_win_wcsdup || FunI == II_kmalloc)
-        return true;
+          FunI == II_strndup || FunI == II_wcsdup || FunI == II_kmalloc ||
+          FunI == II_wtempnam || FunI == II_tempnam ||
+          FunI == II_malloc_dbg || FunI == II_realloc_dbg ||
+          FunI == II_win_wcsdup || FunI == II_calloc_dbg ||
+          FunI == II_wcsdup_dbg || FunI == II_strdup_dbg ||
+          FunI == II_mbsdup || FunI == II_mbsdup_dbg || 
+          FunI == II_win_tempnam || FunI == II_win_tempnam_dbg ||
+          FunI == II_win_strdup || FunI == II_wtempnam_dbg)
+       return true;
     }
 
     if (Family == AF_IfNameIndex && CheckFree) {
@@ -759,7 +798,7 @@
     initIdentifierInfo(C.getASTContext());
     IdentifierInfo *FunI = FD->getIdentifier();
 
-    if (FunI == II_malloc) {
+    if (FunI == II_malloc || FunI == II_malloc_dbg) {
       if (CE->getNumArgs() < 1)
         return;
       if (CE->getNumArgs() < 3) {
@@ -786,20 +825,24 @@
         return;
       State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State);
       State = ProcessZeroAllocation(C, CE, 0, State);
-    } else if (FunI == II_realloc) {
+    } else if ((FunI == II_realloc) || (FunI == II_realloc_dbg)) {
       State = ReallocMem(C, CE, false, State);
       State = ProcessZeroAllocation(C, CE, 1, State);
     } else if (FunI == II_reallocf) {
       State = ReallocMem(C, CE, true, State);
       State = ProcessZeroAllocation(C, CE, 1, State);
-    } else if (FunI == II_calloc) {
+    } else if ((FunI == II_calloc) || (FunI == II_calloc_dbg)) {
       State = CallocMem(C, CE, State);
       State = ProcessZeroAllocation(C, CE, 0, State);
       State = ProcessZeroAllocation(C, CE, 1, State);
-    } else if (FunI == II_free) {
+    } else if ((FunI == II_free) || (FunI == II_free_dbg)) {
       State = FreeMemAux(C, CE, State, 0, false, ReleasedAllocatedMemory);
-    } else if (FunI == II_strdup || FunI == II_win_strdup ||
-               FunI == II_wcsdup || FunI == II_win_wcsdup) {
+    } else if (FunI == II_strdup || FunI == II_wcsdup || FunI == II_tempnam ||
+               FunI == II_wtempnam || FunI == II_win_wcsdup ||
+               FunI == II_wcsdup_dbg || FunI == II_win_strdup ||
+               FunI == II_strdup_dbg || FunI == II_mbsdup ||
+               FunI == II_mbsdup_dbg || FunI == II_win_tempnam ||
+               FunI == II_win_tempnam_dbg || FunI == II_wtempnam_dbg) {
       State = MallocUpdateRefState(C, CE, State);
     } else if (FunI == II_strndup) {
       State = MallocUpdateRefState(C, CE, State);
@@ -1054,7 +1097,7 @@
   if (!State)
     return nullptr;
 
-  if (Att->getModule() != II_malloc)
+  if ((Att->getModule() != II_malloc) && (Att->getModule() != II_malloc_dbg))
     return nullptr;
 
   OwnershipAttr::args_iterator I = Att->args_begin(), E = Att->args_end();
@@ -1148,7 +1191,7 @@
   if (!State)
     return nullptr;
 
-  if (Att->getModule() != II_malloc)
+  if ((Att->getModule() != II_malloc) && (Att->getModule() != II_malloc_dbg))
     return nullptr;
 
   bool ReleasedAllocated = false;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to