diff options
-rw-r--r-- | lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 12 | ||||
-rw-r--r-- | test/Analysis/malloc.c | 45 |
2 files changed, 42 insertions, 15 deletions
diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index fed64f1b04..e21dde1f82 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -881,7 +881,17 @@ void MallocChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const { return; // Check if we are returning a symbol. - SymbolRef Sym = C.getState()->getSVal(E, C.getLocationContext()).getAsSymbol(); + SVal RetVal = C.getState()->getSVal(E, C.getLocationContext()); + SymbolRef Sym = RetVal.getAsSymbol(); + if (!Sym) + // If we are returning a field of the allocated struct or an array element, + // the callee could still free the memory. + // TODO: This logic should be a part of generic symbol escape callback. + if (const MemRegion *MR = RetVal.getAsRegion()) + if (isa<FieldRegion>(MR) || isa<ElementRegion>(MR)) + if (const SymbolicRegion *BMR = + dyn_cast<SymbolicRegion>(MR->getBaseRegion())) + Sym = BMR->getSymbol(); if (!Sym) return; diff --git a/test/Analysis/malloc.c b/test/Analysis/malloc.c index 3e5feb2857..da320c01d1 100644 --- a/test/Analysis/malloc.c +++ b/test/Analysis/malloc.c @@ -631,6 +631,27 @@ void symbolLostWithStrcpy_InlineStrcpyVersion(char *s) { p = ((__builtin_object_size (p, 0) != (size_t) -1) ? __builtin___strcpy_chk (p, s, __builtin_object_size (p, 2 > 1)) : __inline_strcpy_chk (p, s)); free(p); } + +// Here we are returning a pointer one past the allocated value. An idiom which +// can be used for implementing special malloc. The correct uses of this might +// be rare enough so that we could keep this as a warning. +static void *specialMalloc(int n){ + int *p; + p = malloc( n+8 ); + if( p ){ + p[0] = n; + p++; + } + return p; +} + +// Potentially, the user could free the struct by performing pointer arithmetic on the return value. +// This is a variation of the specialMalloc issue, though probably would be more rare in correct code. +int *specialMallocWithStruct() { + struct StructWithInt *px= malloc(sizeof(struct StructWithInt)); + return &(px->g); +} + // Below are the known false positives. // TODO: There should be no warning here. This one might be difficult to get rid of. @@ -650,20 +671,6 @@ void dependsOnValueOfPtr(int *g, unsigned f) { return; } -// TODO: Should this be a warning? -// Here we are returning a pointer one past the allocated value. An idiom which -// can be used for implementing special malloc. The correct uses of this might -// be rare enough so that we could keep this as a warning. -static void *specialMalloc(int n){ - int *p; - p = malloc( n+8 ); - if( p ){ - p[0] = n; - p++; - } - return p;// expected-warning {{Memory is never released; potential memory leak}} -} - // False negatives. // TODO: This requires tracking symbols stored inside the structs/arrays. @@ -673,6 +680,16 @@ void testMalloc5() { pSt->memP = malloc(12); } +// TODO: This is another false negative. +void testMallocWithParam(int **p) { + *p = (int*) malloc(sizeof(int)); + *p = 0; +} + +void testMallocWithParam_2(int **p) { + *p = (int*) malloc(sizeof(int)); +} + // TODO: This should produce a warning, similar to the previous issue. void localArrayTest() { char *p = (char*)malloc(12); |