[analyzer] Malloc: fix another false positive.
, when we return a symbol reachable to the malloced one via pointer
arithmetic.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151121 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index fed64f1..e21dde1 100644
--- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -881,7 +881,17 @@
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 3e5feb2..da320c0 100644
--- a/test/Analysis/malloc.c
+++ b/test/Analysis/malloc.c
@@ -631,6 +631,27 @@
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 @@
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 @@
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);