views:

157

answers:

6

I'm supporting some c code on Solaris, and I've seen something weird at least I think it is:

char new_login[64];
...
strcpy(new_login, (char *)login);
...
free(new_login);

My understanding is that since the variable is a local array the memory comes from the stack and does not need to be freed, and moreover since no malloc/calloc/realloc was used the behaviour is undefined.

This is a real-time system so I think it is a waste of cycles. Am I missing something obvious?

+3  A: 

No. This is a bug.

According to free(3)....

free() frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behaviour occurs. If ptr is NULL, no operation is performed.

So you have undefined behavior happening in your program.

Paul Nathan
+7  A: 

You can only free() something you gor from malloc,calloc or realloc. freeing something on the stack yields undefined behaviour, you're lucky this doesn't cause your program to crash, or worse.

Consider that a serious bug, and delete that line asap.

nos
"Consider that a serious bug, and delete that line asap". This is such a serious bug that if the current code runs correctly, I would want to try to work out why before changing it. There may be something I've seriously misunderstood (like maybe one of those tokens is actually `new_1ogin` or something). I'd probably be wasting my time, but I'd be that paranoid ;-)
Steve Jessop
Perhaps, the `free` checks the range of the pointer and does nothing when it's from an area outside the heap. IMHO it's not a good idea, but who knows what the implementer thought (in my former embedded programmer life I even implemented that behaviour on one of our acquisition controllers).
tristopia
Agreed, but on a particular implementation, "perhaps" becomes "either it does, or it doesn't". I always want to know what kinds of bugs are in practice detectable, and what kinds aren't, because it makes it easier to intelligently debug future problems.
Steve Jessop
If you were going to put that test into your `free()` implementation, you'd presumably do something more to handle it than "silently ignore".
caf
It's possible that it wasn't a bug. Malloc hooks could intrinsically define different behavior from free than what's defined in the standard.
Yktula
+1  A: 

Definitely a bug. free() MUST ONLY be used for heap alloc'd memory, unless it's redefined to do something completely different, which I doubt to be the case.

jweyrich
A: 

IN MOST CASES, you can only free() something allocated on the heap. See http://www.opengroup.org/onlinepubs/009695399/functions/free.html .

HOWEVER: One way to go about doing what you'd like to be doing is to scope temporary variables allocated on the stack. like so:

{
char new_login[64];
... /* No later-used variables should be allocated on the stack here */
strcpy(new_login, (char *)login);
}
...
Yktula
A: 

Thanks. Glad to see I'm not crazy. Also, there was no bounds checking on the strcpy. I usually use strncpy to avoid such things.

vidicon
A: 

The free() is definitely a bug.
However, it's possible there's another bug here:


   strcpy(new_login, (char *)login);

If the function isn't pedantically confirming that login is 63 or fewer characters with the appropriate null termination, then this code has a classic buffer overflow bug. If a malicious party can fill login with the right bytes, they can overwrite the return pointer on the stack and execute arbitrary code. One solution is:


   new_login[sizeof(new_login)-1]='\0';
   strncpy(new_login, (char *)login, sizeof(new_login)-1 );
Dan B