[cfe-commits] r130303 - in /cfe/trunk: lib/StaticAnalyzer/Checkers/MallocChecker.cpp test/Analysis/malloc.c
Lenny Maiorani
lenny at colorado.edu
Wed Apr 27 07:49:29 PDT 2011
Author: lenny
Date: Wed Apr 27 09:49:29 2011
New Revision: 130303
URL: http://llvm.org/viewvc/llvm-project?rev=130303&view=rev
Log:
More accurately model realloc() when the size argument is 0. realloc() with a size of 0 is equivalent to free(). The memory region should be marked as free and not used again.
Unit tests f2_realloc_0(), f6_realloc(), and f7_realloc() contributed by Marshall Clow <mclow.lists at gmail.com>. Thanks!
Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
cfe/trunk/test/Analysis/malloc.c
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=130303&r1=130302&r2=130303&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Wed Apr 27 09:49:29 2011
@@ -501,8 +501,24 @@
DefinedOrUnknownSVal PtrEQ =
svalBuilder.evalEQ(state, arg0Val, svalBuilder.makeNull());
- // If the ptr is NULL, the call is equivalent to malloc(size).
- if (const GRState *stateEqual = state->assume(PtrEQ, true)) {
+ // Get the size argument. If there is no size arg then give up.
+ const Expr *Arg1 = CE->getArg(1);
+ if (!Arg1)
+ return;
+
+ // Get the value of the size argument.
+ DefinedOrUnknownSVal Arg1Val =
+ cast<DefinedOrUnknownSVal>(state->getSVal(Arg1));
+
+ // Compare the size argument to 0.
+ DefinedOrUnknownSVal SizeZero =
+ svalBuilder.evalEQ(state, Arg1Val,
+ svalBuilder.makeIntValWithPtrWidth(0, false));
+
+ // If the ptr is NULL and the size is not 0, the call is equivalent to
+ // malloc(size).
+ const GRState *stateEqual = state->assume(PtrEQ, true);
+ if (stateEqual && state->assume(SizeZero, false)) {
// Hack: set the NULL symbolic region to released to suppress false warning.
// In the future we should add more states for allocated regions, e.g.,
// CheckedNull, CheckedNonNull.
@@ -517,17 +533,17 @@
}
if (const GRState *stateNotEqual = state->assume(PtrEQ, false)) {
- const Expr *Arg1 = CE->getArg(1);
- DefinedOrUnknownSVal Arg1Val =
- cast<DefinedOrUnknownSVal>(stateNotEqual->getSVal(Arg1));
- DefinedOrUnknownSVal SizeZero =
- svalBuilder.evalEQ(stateNotEqual, Arg1Val,
- svalBuilder.makeIntValWithPtrWidth(0, false));
-
+ // If the size is 0, free the memory.
if (const GRState *stateSizeZero = stateNotEqual->assume(SizeZero, true))
- if (const GRState *stateFree = FreeMemAux(C, CE, stateSizeZero, 0, false))
- C.addTransition(stateFree->BindExpr(CE, UndefinedVal(), true));
+ if (const GRState *stateFree =
+ FreeMemAux(C, CE, stateSizeZero, 0, false)) {
+ // Add the state transition to set input pointer argument to be free.
+ C.addTransition(stateFree);
+
+ // Bind the return value to UndefinedVal because it is now free.
+ C.addTransition(stateFree->BindExpr(CE, UndefinedVal(), true));
+ }
if (const GRState *stateSizeNotZero = stateNotEqual->assume(SizeZero,false))
if (const GRState *stateFree = FreeMemAux(C, CE, stateSizeNotZero,
0, false)) {
Modified: cfe/trunk/test/Analysis/malloc.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.c?rev=130303&r1=130302&r2=130303&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/malloc.c (original)
+++ cfe/trunk/test/Analysis/malloc.c Wed Apr 27 09:49:29 2011
@@ -33,6 +33,17 @@
free(p); // expected-warning{{Try to free a memory block that has been released}}
}
+void f2_realloc_0() {
+ int *p = malloc(12);
+ realloc(p,0);
+ realloc(p,0); // expected-warning{{Try to free a memory block that has been released}}
+}
+
+void f2_realloc_1() {
+ int *p = malloc(12);
+ int *q = realloc(p,0); // expected-warning{{Assigned value is garbage or undefined}}
+}
+
// ownership attributes tests
void naf1() {
int *p = my_malloc3(12);
@@ -166,6 +177,15 @@
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();
@@ -182,6 +202,12 @@
x[0] = 'a'; // expected-warning{{Use dynamically allocated memory after it is freed.}}
}
+void f7_realloc() {
+ char *x = (char*) malloc(4);
+ realloc(x,0);
+ x[0] = 'a'; // expected-warning{{Use dynamically allocated memory after it is freed.}}
+}
+
void PR6123() {
int *x = malloc(11); // expected-warning{{Cast a region whose size is not a multiple of the destination type size.}}
}
More information about the cfe-commits
mailing list