Emmet said:
In the course of examining the code for an Internet-connected
authentication server, I came across the following code (twice in one
function with different constants in the "if") in a file of some 2000
non-comment lines written by a "C" expert:
if( elem->tag == SOME_MANIFEST_CONSTANT ) /* Alt */
{
char *tempValue = malloc(32);
strcpy(tempValue, elem->value);
What makes you so sure 32 characters is enough to hold the length of
elem->value? Usually, in place of explicit constants such as "32" you
use a #define which makes your meaning clear, such as MAX_VALUE_LEN,
which you then use in place of 32 above, and semantically as required
in other places in your code.
As others have pointed out, malloc can return with NULL, so technically
you should handle that case.
while( tempValue[0] == '0' )
{
tempValue++;
}
It appears as though what you are trying to do here is to skip a '0'
(possibly repeated) prefix the value of your string. But what if the
string contents itself is nothing but '0's? Is it really your
intention to strip them all away? Assuming that you were trying to
text encode a numeric value of some kind, the number "0" would be
reduced to the empty string here.
some_api_function(tempValue); /* Alt */
}
Ok, as others have pointed out you have a memory leak here, because you
forgot to use free() on what was given to you from malloc. You cannot
simply put free(tempValue) before the } because you've *lost* the
original pointer due to your destructive operation of incrementing it,
as a means of trying to "get rid of leading 0s". This may not be a big
deal if you are using something called the Boehm garbage collector
tool, however, you did not make this clear.
Let's try for a rewrite:
if( elem->tag == SOME_MANIFEST_CONSTANT ) /* Alt */
{
char *s, *t = elem->value;
int len;
while (t[0] == '0' && t[1] !='\0') t++;
len = strlen (t) + 1;
s = malloc (len * sizeof (char));
if (s) {
memcpy (s, t, len);
some_api_function (s);
free (s); /* Unless the function above frees it */
} else {
/* Do something about the failure of malloc */
}
}
So what we've done is we've scanned for the prefixed '0's in the
original string before its copied, as we are allowing for a single "0"
digit without truncating it down to "". Then we've allocated exactly
as much space as it required by the string we are copying. We've
checked for a possible failure of malloc. And finally we free the
memory for the copied string ourself (or we could remove that free()
line and require that the function "some_api_function" do the freeing,
or some other mechanism such as the Boehm garbage collector.)