Your code is incorrect: you have a potential buffer overflow in both alternatives.
I am not sure Coverity diagnoses the problem correctly, you did not post the exact error message. Coverity is possibly indicating that you use a string from the environment, that could have any length, potentially causing a buffer overflow when copied by your code into a 1024 byte buffer, indeed it is a good thing it pointed you to this. Here is why:
strncpy
does not do what you think it does. This function should never be used, its semantics are error prone, it is not the right tool for your purpose. strncpy(dest, src, n)
copies no more than n
chars from src
to dest
and fills the rest of the array at dest
with '\0'
bytes until n
bytes have been written. dest
must point to an array of at least n
chars. If src
is shorter, the behavior is inefficient as the padding is usually unnecessary, but if src
has a length of at least n
, dest
will not be null terminated by strncpy
, leading to undefined behavior in many cases.
Your code:
char path[1024] = { NULL, };
if (getenv("A"))
strncpy(path, getenv("A"), strlen(getenv("A")));
is equivalent to
char path[1024] = { NULL, };
if (getenv("A"))
memcpy(path, getenv("A"), strlen(getenv("A")));
As you see, no real protection is granted.
You call getenv
3 times, it would indeed be more efficient to use your alternative implementation, but there are other problems:
You initialize path
with { NULL, }
. This is inconsistent and in many cases incorrect. NULL
is commonly #defined as ((void*)0)
, thus an invalid initializer for char
. path
could be initialized this way:
char path[1024] = { 0 };
To avoid overflowing the destination buffer, use this code:
char path[1024] = { 0 };
char *p = getenv("A");
if (p != NULL) {
strncat(path, p, sizeof(path) - 1);
}
But this would truncate the environment value, which may not be appropriate depending on how you use path
.
An alternative is to use the environment value directly:
char *path = getenv("A");
if (path == NULL)
path = "";
And if you change the environment values with setenv
during the execution of your program, you might want to make a copy of the environment value with path = strdup(path);
. This might also fix the tainted string warning from Coverity, although the copy would be the same size as the original and enough memory might not be available, which should be tested. Judging from Tainted string in C , it seems Coverity is a bit extreme about tainted strings. While the warning you get indicates a real problem, getting rid of the warning may sometimes require strange workarounds.
char
, especially if the implementation definesNULL
as((void *)0)
, which is a legitimate value in C (but not legitimate in C++). You could usechar path[1024] = "";
instead. You are also abusingstrncpy()
; you should be limiting it to the length ofpath
(minus 1). If someone runs your code with a PATH that is more than 1023 characters long, you will overflow the array and may end up crashing and will not get a null-terminated string. It is unlikely that either of these is a factor in the 'tainted string' message. – Medalistmemset()
after initializingpath
to all bytes zero. – Medalistgetenv()
calls. – Protestantismif (!adriver)
is only true ifadriver
isNULL
. In other words, you have reversed the meaning of theif
statement from the first piece of code. You probably meantif (adriver)
. – Medalistgetenv()
before you do much with it in order to get rid of the taintedness. But I've not gone manual bashing to find out more -- you can do that about as well as I can. – Medalist