r337000 - [Analyzer] alpha.unix.cstring.OutOfBounds checker enable/disable fix

Adam Balogh via cfe-commits cfe-commits at lists.llvm.org
Fri Jul 13 06:44:44 PDT 2018


Author: baloghadamsoftware
Date: Fri Jul 13 06:44:44 2018
New Revision: 337000

URL: http://llvm.org/viewvc/llvm-project?rev=337000&view=rev
Log:
[Analyzer] alpha.unix.cstring.OutOfBounds checker enable/disable fix

It was not possible to disable alpha.unix.cstring.OutOfBounds checker's reports
since unix.Malloc checker always implicitly enabled the filter. Moreover if the
checker was disabled from command line (-analyzer-disable-checker ..) the out
of bounds warnings were nevertheless emitted under different checker names such
as unix.cstring.NullArg, or unix.Malloc.

This patch fixes the case sot that Malloc checker only enables implicitly the
underlying modeling of strcpy, memcpy etc. but not the warning messages that
would have been emmitted by alpha.unix.cstring.OutOfBounds

Patch by: Dániel Krupp

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


Added:
    cfe/trunk/test/Analysis/cstring-plist.c
Modified:
    cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
    cfe/trunk/test/Analysis/malloc.c
    cfe/trunk/test/Analysis/string.c

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp?rev=337000&r1=336999&r2=337000&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CStringChecker.cpp Fri Jul 13 06:44:44 2018
@@ -305,10 +305,10 @@ ProgramStateRef CStringChecker::CheckLoc
   ProgramStateRef StOutBound = state->assumeInBound(Idx, Size, false);
   if (StOutBound && !StInBound) {
     // These checks are either enabled by the CString out-of-bounds checker
-    // explicitly or the "basic" CStringNullArg checker support that Malloc
-    // checker enables.
-    assert(Filter.CheckCStringOutOfBounds || Filter.CheckCStringNullArg);
-
+    // explicitly or implicitly by the Malloc checker.
+    // In the latter case we only do modeling but do not emit warning.
+    if (!Filter.CheckCStringOutOfBounds)
+      return nullptr;
     // Emit a bug report.
     if (warningMsg) {
       emitOutOfBoundsBug(C, StOutBound, S, warningMsg);
@@ -1039,7 +1039,7 @@ bool CStringChecker::memsetAux(const Exp
     std::tie(StateWholeReg, StateNotWholeReg) =
         State->assume(svalBuilder.evalEQ(State, Extent, *SizeNL));
 
-    // With the semantic of 'memset()', we should convert the CharVal to 
+    // With the semantic of 'memset()', we should convert the CharVal to
     // unsigned char.
     CharVal = svalBuilder.evalCast(CharVal, Ctx.UnsignedCharTy, Ctx.IntTy);
 
@@ -2418,5 +2418,5 @@ void CStringChecker::checkDeadSymbols(Sy
 REGISTER_CHECKER(CStringNotNullTerm)
 
   void ento::registerCStringCheckerBasic(CheckerManager &Mgr) {
-    registerCStringNullArg(Mgr);
+    Mgr.registerChecker<CStringChecker>();
   }

Added: cfe/trunk/test/Analysis/cstring-plist.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cstring-plist.c?rev=337000&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/cstring-plist.c (added)
+++ cfe/trunk/test/Analysis/cstring-plist.c Fri Jul 13 06:44:44 2018
@@ -0,0 +1,22 @@
+// RUN: rm -f %t
+// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,unix.Malloc,unix.cstring.NullArg -analyzer-disable-checker=alpha.unix.cstring.OutOfBounds -analyzer-output=plist -analyzer-config path-diagnostics-alternate=false -o %t %s
+// RUN: FileCheck -input-file %t %s
+
+typedef __typeof(sizeof(int)) size_t;
+void *malloc(size_t);
+void free(void *);
+char *strncpy(char *restrict s1, const char *restrict s2, size_t n);
+
+
+
+void cstringchecker_bounds_nocrash() {
+  char *p = malloc(2);
+  strncpy(p, "AAA", sizeof("AAA")); // we don't expect warning as the checker is disabled
+  free(p);
+}
+
+// CHECK: <key>diagnostics</key>
+// CHECK-NEXT: <array>
+// CHECK-NEXT: </array>
+// CHECK-NEXT: </dict>
+// CHECK-NEXT: </plist>

Modified: cfe/trunk/test/Analysis/malloc.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=337000&r1=336999&r2=337000&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/malloc.c (original)
+++ cfe/trunk/test/Analysis/malloc.c Fri Jul 13 06:44:44 2018
@@ -375,7 +375,7 @@ void CheckUseZeroReallocatedPathWarn(_Bo
 // or inter-procedural analysis, this is a conservative answer.
 int *f3() {
   static int *p = 0;
-  p = malloc(12); 
+  p = malloc(12);
   return p; // no-warning
 }
 
@@ -384,7 +384,7 @@ int *f3() {
 // functions or inter-procedural analysis, this is a conservative answer.
 static int *p_f4 = 0;
 int *f4() {
-  p_f4 = malloc(12); 
+  p_f4 = malloc(12);
   return p_f4; // no-warning
 }
 
@@ -1232,7 +1232,7 @@ void radar10978247(int myValueSize) {
 
   if (myValueSize <= sizeof(stackBuffer))
     buffer = stackBuffer;
-  else 
+  else
     buffer = malloc(myValueSize);
 
   // do stuff with the buffer
@@ -1246,7 +1246,7 @@ void radar10978247_positive(int myValueS
 
   if (myValueSize <= sizeof(stackBuffer))
     buffer = stackBuffer;
-  else 
+  else
     buffer = malloc(myValueSize);
 
   // do stuff with the buffer
@@ -1254,7 +1254,7 @@ void radar10978247_positive(int myValueS
     return;
   else
     return; // expected-warning {{leak}}
-}
+}
 // <rdar://problem/11269741> Previously this triggered a false positive
 // because malloc() is known to return uninitialized memory and the binding
 // of 'o' to 'p->n' was not getting propertly handled.  Now we report a leak.
@@ -1698,7 +1698,7 @@ void testReallocEscaped(void **memory) {
 void *smallocNoWarn(size_t size) {
   if (size == 0) {
     return malloc(1); // this branch is never called
-  } 
+  }
   else {
     return malloc(size);
   }
@@ -1777,21 +1777,12 @@ void freeFunctionPtr() {
   free((void *)fnptr); // expected-warning {{Argument to free() is a function pointer}}
 }
 
-// Enabling the malloc checker enables some of the buffer-checking portions
-// of the C-string checker.
-void cstringchecker_bounds_nocrash() {
-  char *p = malloc(2);
-  strncpy(p, "AAA", sizeof("AAA")); // expected-warning {{Size argument is greater than the length of the destination buffer}}
-
-  free(p);
-}
-
 void allocateSomeMemory(void *offendingParameter, void **ptr) {
   *ptr = malloc(1);
 }
 
 void testNoCrashOnOffendingParameter() {
-  // "extern" is necessary to avoid unrelated warnings 
+  // "extern" is necessary to avoid unrelated warnings
   // on passing uninitialized value.
   extern void *offendingParameter;
   void* ptr;

Modified: cfe/trunk/test/Analysis/string.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/string.c?rev=337000&r1=336999&r2=337000&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/string.c (original)
+++ cfe/trunk/test/Analysis/string.c Fri Jul 13 06:44:44 2018
@@ -31,6 +31,8 @@ typedef typeof(sizeof(int)) size_t;
 void clang_analyzer_eval(int);
 
 int scanf(const char *restrict format, ...);
+void *malloc(size_t);
+void free(void *);
 
 //===----------------------------------------------------------------------===
 // strlen()
@@ -110,7 +112,7 @@ void strlen_global() {
   if (a == 0) {
     clang_analyzer_eval(b == 0); // expected-warning{{TRUE}}
     // Make sure clang_analyzer_eval does not invalidate globals.
-    clang_analyzer_eval(strlen(global_str) == 0); // expected-warning{{TRUE}}    
+    clang_analyzer_eval(strlen(global_str) == 0); // expected-warning{{TRUE}}
   }
 
   // Call a function with unknown effects, which should invalidate globals.
@@ -309,11 +311,13 @@ void strcpy_effects(char *x, char *y) {
   clang_analyzer_eval(globalInt == 42); // expected-warning{{TRUE}}
 }
 
+#ifndef SUPPRESS_OUT_OF_BOUND
 void strcpy_overflow(char *y) {
   char x[4];
   if (strlen(y) == 4)
     strcpy(x, y); // expected-warning{{String copy function overflows destination buffer}}
 }
+#endif
 
 void strcpy_no_overflow(char *y) {
   char x[4];
@@ -348,11 +352,13 @@ void stpcpy_effect(char *x, char *y) {
   clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}}
 }
 
+#ifndef SUPPRESS_OUT_OF_BOUND
 void stpcpy_overflow(char *y) {
   char x[4];
   if (strlen(y) == 4)
     stpcpy(x, y); // expected-warning{{String copy function overflows destination buffer}}
 }
+#endif
 
 void stpcpy_no_overflow(char *y) {
   char x[4];
@@ -403,6 +409,7 @@ void strcat_effects(char *y) {
   clang_analyzer_eval((int)strlen(x) == (orig_len + strlen(y))); // expected-warning{{TRUE}}
 }
 
+#ifndef SUPPRESS_OUT_OF_BOUND
 void strcat_overflow_0(char *y) {
   char x[4] = "12";
   if (strlen(y) == 4)
@@ -420,6 +427,7 @@ void strcat_overflow_2(char *y) {
   if (strlen(y) == 2)
     strcat(x, y); // expected-warning{{String copy function overflows destination buffer}}
 }
+#endif
 
 void strcat_no_overflow(char *y) {
   char x[5] = "12";
@@ -496,6 +504,15 @@ void strncpy_effects(char *x, char *y) {
   clang_analyzer_eval(a == x[0]); // expected-warning{{UNKNOWN}}
 }
 
+#ifndef SUPPRESS_OUT_OF_BOUND
+// Enabling the malloc checker enables some of the buffer-checking portions
+// of the C-string checker.
+void cstringchecker_bounds_nocrash() {
+  char *p = malloc(2);
+  strncpy(p, "AAA", sizeof("AAA")); // expected-warning {{Size argument is greater than the length of the destination buffer}}
+  free(p);
+}
+
 void strncpy_overflow(char *y) {
   char x[4];
   if (strlen(y) == 4)
@@ -516,6 +533,7 @@ void strncpy_no_overflow2(char *y, int n
   if (strlen(y) == 3)
     strncpy(x, y, n); // expected-warning{{Size argument is greater than the length of the destination buffer}}
 }
+#endif
 
 void strncpy_truncate(char *y) {
   char x[4];
@@ -592,6 +610,7 @@ void strncat_effects(char *y) {
   clang_analyzer_eval(strlen(x) == (orig_len + strlen(y))); // expected-warning{{TRUE}}
 }
 
+#ifndef SUPPRESS_OUT_OF_BOUND
 void strncat_overflow_0(char *y) {
   char x[4] = "12";
   if (strlen(y) == 4)
@@ -615,6 +634,8 @@ void strncat_overflow_3(char *y) {
   if (strlen(y) == 4)
     strncat(x, y, 2); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
 }
+#endif
+
 void strncat_no_overflow_1(char *y) {
   char x[5] = "12";
   if (strlen(y) == 2)
@@ -632,6 +653,7 @@ void strncat_symbolic_dst_length(char *d
   clang_analyzer_eval(strlen(dst) >= 4); // expected-warning{{TRUE}}
 }
 
+#ifndef SUPPRESS_OUT_OF_BOUND
 void strncat_symbolic_src_length(char *src) {
   char dst[8] = "1234";
   strncat(dst, src, 3);
@@ -649,6 +671,7 @@ void strncat_unknown_src_length(char *sr
   char dst2[8] = "1234";
   strncat(dst2, &src[offset], 4); // expected-warning{{Size argument is greater than the free space in the destination buffer}}
 }
+#endif
 
 // There is no strncat_unknown_dst_length because if we can't get a symbolic
 // length for the "before" strlen, we won't be able to set one for "after".




More information about the cfe-commits mailing list