Hi zaks.anna,
Currently realloc(ptr, 0) is treated as free() which seems to be not correct. C
standard (N1570) establishes equivalent behavior for malloc(0) and realloc(ptr,
0):
"7.22.3 Memory management functions calloc, malloc, realloc: 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."
The patch equalizes the processing of malloc(0) and realloc(ptr,0).
The patch also enables unix.Malloc checker to detect references to
zero-allocated memory returned by realloc(ptr,0) ("Use of zero-allocated
memory" warning).
Please review.
http://reviews.llvm.org/D9040
Files:
lib/StaticAnalyzer/Checkers/MallocChecker.cpp
test/Analysis/malloc-annotations.c
test/Analysis/malloc.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
@@ -1906,52 +1906,24 @@
return nullptr;
DefinedOrUnknownSVal Arg1Val = Arg1ValG.castAs<DefinedOrUnknownSVal>();
- // Compare the size argument to 0.
- DefinedOrUnknownSVal SizeZero =
- svalBuilder.evalEQ(State, Arg1Val,
- svalBuilder.makeIntValWithPtrWidth(0, false));
-
ProgramStateRef StatePtrIsNull, StatePtrNotNull;
std::tie(StatePtrIsNull, StatePtrNotNull) = State->assume(PtrEQ);
- ProgramStateRef StateSizeIsZero, StateSizeNotZero;
- std::tie(StateSizeIsZero, StateSizeNotZero) = State->assume(SizeZero);
- // We only assume exceptional states if they are definitely true; if the
- // state is under-constrained, assume regular realloc behavior.
- bool PrtIsNull = StatePtrIsNull && !StatePtrNotNull;
- bool SizeIsZero = StateSizeIsZero && !StateSizeNotZero;
-
- // If the ptr is NULL and the size is not 0, the call is equivalent to
- // malloc(size).
- if ( PrtIsNull && !SizeIsZero) {
+ // If the ptr is NULL the call is equivalent to malloc(size).
+ if (StatePtrIsNull && !StatePtrNotNull) {
ProgramStateRef stateMalloc = MallocMemAux(C, CE, CE->getArg(1),
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 (ProgramStateRef stateFree = FreeMemAux(C, CE, StateSizeIsZero, 0,
- false, ReleasedAllocated)){
- // The semantics of the return value are:
- // If size was equal to 0, either NULL or a pointer suitable to be passed
- // to free() is returned. We just free the input pointer and do not add
- // any constrains on the output pointer.
- return stateFree;
- }
-
// Default behavior.
if (ProgramStateRef stateFree =
FreeMemAux(C, CE, State, 0, false, ReleasedAllocated)) {
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();
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits