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 
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