Anyone working on a checker for realloc?

Having had a discussion with someone about problems with using realloc, I was wondering if anyone has done anything with a security checker (Lenny?) or static analysis module for problems with using realloc.

Sample (bad) code:

  p = malloc ( 12 );
  realloc ( p, 24 );
  *p = 123; // realloc can move memory - but usually doesn't

-- Marshall

Marshall Clow Idio Software <mailto:mclow.lists@gmail.com>

A.D. 1517: Martin Luther nails his 95 Theses to the church door and is promptly moderated down to (-1, Flamebait).
        -- Yu Suzuki

There is a checker for realloc and it does bind the return value properly, if there is a return value. I think this checker is not entirely complete at a quick glance.

It should probably additionally check that the symbol being assigned is not the same as the symbol passed into realloc as arg 1 and make sure that the return value is actually being assigned to something.

Another sample bad code is this:

p = malloc(120:
p = realloc(p, 24);

The problem here is that realloc might return an error. If it does, the input pointer is still valid and hasn't been free'd. I have seen this too often and it seems to be a common misunderstanding. reallocf doesn't have the same problem.

Marshall, in short, the checker for realloc is not complete, but does exist. It is part of the Malloc checker.

-Lenny

I tried adding some more tests to malloc.c specifically to check realloc (ptr, 0) as a synonym for free(ptr)

But the checker didn't catch them :frowning:

Line 39:
  Line 39: Allocated memory never released. Potential memory leak.
  Line 202: Allocated memory never released. Potential memory leak.
  Line 202: Array access (from variable 'x') results in a null pointer dereference
3 errors generated.

void f2_realloc() {
  int *p = malloc(12);
  realloc(p,0);
  realloc(p,0); // expected-warning{{Try to free a memory block that has been released}} ## line 39
}

void f6_realloc() {
  int *p = malloc(12);
  if (!p)
    return; // no-warning
  else
    realloc(p,0); ## This one works, btw
}

void f7_realloc() {
  char *x = (char*) malloc(4);
  realloc(x,0);
  x[0] = 'a'; // expected-warning{{Use dynamically allocated memory after it is freed.}} ## line 202
}

I see the code in llvm/tools/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp, but it doesn't catch these.
(And I don't see why it doesn't)

-- Marshall

Sorry to revive an old thread, but I don't know if this is universally true. The (very outdated) OS X man pages include this:

"If size is zero and ptr is not NULL, a new, minimum sized object is allocated and the original object is freed."

So it seems like the actual behavior is dependent on the target. (I think this is because a return value of NULL means failure, but the non-null "minimum size object" is taken from the malloc pool in my simple test.)

Is it worth pulling this back out of the checker?
Jordy