Updated the patch. Left an old behavior for C89. Please review.

In http://reviews.llvm.org/D9040#173371, @joerg wrote:

> I don't believe we have to change anything here. The historic behavior of 
> realloc(ptr, 0) is free(ptr) + returning NULL. That is also valid behavior 
> under C11 where the behavior of malloc(0) is implemtation defined.


This behavior is not valid since C99. Under C99 and C11 the pure "If the size 
of the space requested is zero, the behavior is implementation-defined" (The 
C89 Draft) was restricted to "If the size of the space requested is zero, the  
ehavior is implementation-defined: either a null pointer is returned, or the 
behavior is as if the size were some nonzero value, except that the returned 
pointer shall not be used to access an object." (C99 N1256 p.7.20.3; C11 N1570 
p.7.22.3).

Another reason for tracking the return value from realloc(ptr, 0) is in ability 
to detect accesses to zero-allocated memory in realloc case which is currently 
missing. (http://reviews.llvm.org/D8273).


http://reviews.llvm.org/D9040

Files:
  lib/StaticAnalyzer/Checkers/MallocChecker.cpp
  test/Analysis/malloc-annotations.c
  test/Analysis/malloc.c
  test/Analysis/realloc-C89.c

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: lib/StaticAnalyzer/Checkers/MallocChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -1919,30 +1919,42 @@
   // state is under-constrained, assume regular realloc behavior.
   bool PrtIsNull = StatePtrIsNull && !StatePtrNotNull;
   bool SizeIsZero = StateSizeIsZero && !StateSizeNotZero;
+  bool IsC89 = !C.getLangOpts().C99 && !C.getLangOpts().CPlusPlus;
 
-  // If the ptr is NULL and the size is not 0, the call is equivalent to 
-  // malloc(size).
-  if ( PrtIsNull && !SizeIsZero) {
+  if (PrtIsNull) {
+    // The C89 Draft, p.4.10.3.4 : If ptr is a null pointer, the realloc
+    // function behaves like the malloc function for the specified size.
+    // The C89 Draft, p.4.10.3 : If the size of the space requested is zero,
+    // the behavior is implementation-defined.
+    if (IsC89 && SizeIsZero)
+      return nullptr;
+
+    // C99 (N1256) p.7.20.3 : If the size of the space requested is zero, the 
+    // behavior is implementation defined : either a null pointer is returned, or
+    // the behavior is as if the size were some nonzero value, except that the
+    // returned pointer shall not be used to access an object.
+    //
+    // We keep tracking the returned pointer in case of a zero-allocation to
+    // check for zero-allocated memory access and to ensure that the memory is
+    // freed.
     ProgramStateRef stateMalloc = MallocMemAux(C, CE, CE->getArg(1),
-                                               UndefinedVal(), StatePtrIsNull);
+                                                 UndefinedVal(),
+                                                 StatePtrIsNull);
     return stateMalloc;
   }
 
-  if (PrtIsNull && SizeIsZero)
-    return nullptr;
-
   // Get the from and to pointer symbols as in toPtr = realloc(fromPtr, size).
-  assert(!PrtIsNull);
   SymbolRef FromPtr = arg0Val.getAsSymbol();
   SVal RetVal = State->getSVal(CE, LCtx);
   SymbolRef ToPtr = RetVal.getAsSymbol();
   if (!FromPtr || !ToPtr)
     return nullptr;
 
   bool ReleasedAllocated = false;
 
-  // If the size is 0, free the memory.
-  if (SizeIsZero)
+  if (IsC89 && SizeIsZero)
+    // The C89 Draft, p.4.10.3.4: If size is zero and ptr is not a null
+    // pointer, the object it points to is freed.
     if (ProgramStateRef stateFree = FreeMemAux(C, CE, StateSizeIsZero, 0,
                                                false, ReleasedAllocated)){
       // The semantics of the return value are:
Index: test/Analysis/malloc-annotations.c
===================================================================
--- test/Analysis/malloc-annotations.c
+++ test/Analysis/malloc-annotations.c
@@ -41,11 +41,6 @@
   realloc(p,0); // expected-warning{{Attempt to free released memory}}
 }
 
-void f2_realloc_1() {
-  int *p = malloc(12);
-  int *q = realloc(p,0); // no-warning
-}
-
 // ownership attributes tests
 void naf1() {
   int *p = my_malloc3(12);
@@ -176,15 +171,6 @@
     free(p);
 }
 
-void f6_realloc() {
-  int *p = malloc(12);
-  if (!p)
-    return; // no-warning
-  else
-    realloc(p,0);
-}
-
-
 char *doit2();
 void pr6069() {
   char *buf = doit2();
Index: test/Analysis/malloc.c
===================================================================
--- test/Analysis/malloc.c
+++ test/Analysis/malloc.c
@@ -37,11 +37,6 @@
   realloc(p,0); // expected-warning{{Attempt to free released memory}}
 }
 
-void f2_realloc_1() {
-  int *p = malloc(12);
-  int *q = realloc(p,0); // no-warning
-}
-
 void reallocNotNullPtr(unsigned sizeIn) {
   unsigned size = 12;
   char *p = (char*)malloc(size);
@@ -79,38 +74,22 @@
 void reallocSizeZero1() {
   char *p = malloc(12);
   char *r = realloc(p, 0);
-  if (!r) {
-    free(p); // expected-warning {{Attempt to free released memory}}
-  } else {
-    free(r);
-  }
+  free(r);
 }
 
 void reallocSizeZero2() {
   char *p = malloc(12);
   char *r = realloc(p, 0);
-  if (!r) {
-    free(p); // expected-warning {{Attempt to free released memory}}
-  } else {
-    free(r);
-  }
-  free(p); // expected-warning {{Attempt to free released memory}}
-}
+} // expected-warning {{Potential leak of memory pointed to by}}
 
 void reallocSizeZero3() {
-  char *p = malloc(12);
-  char *r = realloc(p, 0);
-  free(r);
-}
-
-void reallocSizeZero4() {
   char *r = realloc(0, 0);
   free(r);
 }
 
-void reallocSizeZero5() {
+void reallocSizeZero4() {
   char *r = realloc(0, 0);
-}
+} // expected-warning {{Potential leak of memory pointed to by}}
 
 void reallocPtrZero1() {
   char *r = realloc(0, 12);
@@ -263,21 +242,21 @@
 
 void CheckUseZeroAllocated7() {
   int *p = realloc(0, 0);
-  *p = 1; //TODO: warn about use of zero-allocated memory
+  *p = 1; // expected-warning {{Use of zero-allocated memory}}
   free(p);
 }
 
 void CheckUseZeroAllocated8() {
   int *p = malloc(8);
   int *q = realloc(p, 0);
-  *q = 1; //TODO: warn about use of zero-allocated memory
+  *q = 1; // expected-warning {{Use of zero-allocated memory}}
   free(q);
 }
 
 void CheckUseZeroAllocated9() {
   int *p = realloc(0, 0);
   int *q = realloc(p, 0);
-  *q = 1; //TODO: warn about use of zero-allocated memory
+  *q = 1; // expected-warning {{Use of zero-allocated memory}}
   free(q);
 }
 
@@ -339,15 +318,6 @@
     free(p);
 }
 
-void f6_realloc() {
-  int *p = malloc(12);
-  if (!p)
-    return; // no-warning
-  else
-    realloc(p,0);
-}
-
-
 char *doit2();
 void pr6069() {
   char *buf = doit2();
Index: test/Analysis/realloc-C89.c
===================================================================
--- test/Analysis/realloc-C89.c
+++ test/Analysis/realloc-C89.c
@@ -0,0 +1,60 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc -analyzer-store=region -verify -std=c89 %s
+typedef __typeof(sizeof(int)) size_t;
+void *malloc(size_t);
+void *realloc(void *ptr, size_t size);
+
+void reallocSizeZero1() {
+  char *p = malloc(12);
+  char *r = realloc(p, 0);
+  if (!r) {
+    free(p); // expected-warning {{Attempt to free released memory}}
+  } else {
+    free(r);
+  }
+}
+
+void reallocSizeZero2() {
+  char *p = malloc(12);
+  char *r = realloc(p, 0);
+  if (!r) {
+    free(p); // expected-warning {{Attempt to free released memory}}
+  } else {
+    free(r);
+  }
+  free(p); // expected-warning {{Attempt to free released memory}}
+}
+
+void reallocSizeZero3() {
+  char *p = malloc(12);
+  char *r = realloc(p, 0);
+  free(r); // no warning
+}
+
+void reallocSizeZero4() {
+  char *r = realloc(0, 0);
+  free(r); // no warning
+}
+
+void reallocSizeZero5() {
+  char *r = realloc(0, 0);
+} // no warning
+
+void CheckUseZeroAllocated1() {
+  int *p = realloc(0, 0);
+  *p = 1; // no warning
+  free(p);
+}
+
+void CheckUseZeroAllocated8() {
+  int *p = malloc(8);
+  int *q = realloc(p, 0);
+  *q = 1; // no warning
+  free(q);
+}
+
+void CheckUseZeroAllocated9() {
+  int *p = realloc(0, 0);
+  int *q = realloc(p, 0);
+  *q = 1; // no warning
+  free(q);
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to