您的代码不正确:两种选择都有潜在的缓冲区溢出。
我不确定Coverity是否正确诊断问题,您没有发布确切的错误消息。Coverity 可能表明您使用了环境中的字符串,该字符串可能具有任意长度,当您的代码将其复制到 1024 字节缓冲区时,可能会导致缓冲区溢出,这确实是一件好事。原因如下:
strncpy
不做你认为它做的事。永远不要使用这个函数,它的语义很容易出错,它不是适合你的工具。从tostrncpy(dest, src, n)
复制不超过n
chars并用字节填充数组的其余部分,直到字节被写入。必须指向至少包含字符的数组。如果更短,则行为效率低下,因为填充通常是不必要的,但如果长度至少为,则不会以 为空终止,在许多情况下会导致未定义的行为。src
dest
dest
'\0'
n
dest
n
src
src
n
dest
strncpy
你的代码:
char path[1024] = { NULL, };
if (getenv("A"))
strncpy(path, getenv("A"), strlen(getenv("A")));
相当于
char path[1024] = { NULL, };
if (getenv("A"))
memcpy(path, getenv("A"), strlen(getenv("A")));
如您所见,没有真正的保护被授予。
您调用getenv
3 次,使用您的替代实现确实会更有效,但还有其他问题:
path
你用初始化{ NULL, }
。这是不一致的,在许多情况下是不正确的。 NULL
通常 #defined 为((void*)0)
,因此 . 的初始值设定项无效char
。 path
可以这样初始化:
char path[1024] = { 0 };
为避免溢出目标缓冲区,请使用以下代码:
char path[1024] = { 0 };
char *p = getenv("A");
if (p != NULL) {
strncat(path, p, sizeof(path) - 1);
}
但这会截断环境值,这可能不合适,具体取决于您使用path
.
另一种方法是直接使用环境值:
char *path = getenv("A");
if (path == NULL)
path = "";
如果您setenv
在程序执行期间更改环境值,您可能希望使用 复制环境值path = strdup(path);
。这也可能修复来自 Coverity 的污染字符串警告,尽管副本的大小与原始的大小相同,并且可能没有足够的内存可用,应该对其进行测试。从C 中的 Tainted string来看,Coverity 似乎对 tainted strings 有点极端。虽然您收到的警告表明存在真正的问题,但消除警告有时可能需要奇怪的解决方法。