diff options
| -rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 38 | ||||
| -rw-r--r-- | clang/test/Analysis/malloc.c | 26 | 
2 files changed, 53 insertions, 11 deletions
| diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index a7655c4fb9d..91002158c57 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -501,8 +501,24 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) const {    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 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) const {    }    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)) { diff --git a/clang/test/Analysis/malloc.c b/clang/test/Analysis/malloc.c index c13e15257be..f9af199b5fa 100644 --- a/clang/test/Analysis/malloc.c +++ b/clang/test/Analysis/malloc.c @@ -33,6 +33,17 @@ void f2() {    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 @@ void f6() {      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 @@ void f7() {    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.}}  } | 

