来自Coverity使用getenv的污点字符串消息

时间:2014-12-08 05:56:21

标签: c coverity coverity-prevent

在我的代码上运行Coverity会导致受污染的字符串错误消息。我正在使用堆栈中声明的“path”变量,所以我不确定为什么我会看到错误。我只能认为在getenv()中直接使用strncpy()会导致错误。下面的修复会消除这个错误吗?

char path[1024] = {NULL, };
if(getenv("A"))
    strncpy(path, getenv("A"), strlen(getenv("A")));

char path[1024] = {NULL, };
char * adriver = getenv("A");
if(adriver)
    strncpy(path, adriver, strlen(adriver));

4 个答案:

答案 0 :(得分:8)

不,这可能无法解决错误。

Coverity告诉你环境变量中的数据" A"几乎可以说是什么;这些数据不受您的程序控制。

因此,在使用数据之前,您需要对数据进行一些完整性检查。

如果有人将环境变量A设置为包含1025个字符的字符串,则建议的修补程序当前会有缓冲区溢出。

此外,任何版本的代码都不会NUL终止"路径"串。这是因为,你正在使用strncpy,如果应用了字节限制,它将不会NUL终止(在这种情况下,它将说明"将复制的字符串限制为我从字符串中获得的长度&# 34。)

你应该做的是首先检查字符串的大小。如果它太大,则返回某种错误代码;变量A中的路径太大,因此您的代码将无法按预期运行。如果它不是太大,请将其复制到路径缓冲区中。如果你想使用strncpy,请确保在最后为NUL留出空间,然后明确地添加它,因为strncpy不能保证在那里放置NUL。

答案 1 :(得分:5)

您的代码不正确:两种备选方案都有潜在的缓冲区溢出。

我不确定 Coverity 是否正确诊断问题,您没有发布确切的错误消息。 Coverity可能表示您使用了环境中的字符串,该字符串可能具有任何长度,当您的代码复制到1024字节缓冲区时可能导致缓冲区溢出,实际上它指向您这是一件好事。原因如下:

strncpy没有按照您的想法行事。此函数应永远使用,其语义容易出错,它不适合您的工具。 strncpy(dest, src, n)n复制src个字符到dest,并在dest填充'\0'字节的其余部分,直到n已写入1}}个字节。 dest必须指向至少n个字符的数组。如果src较短,则行为效率低,因为填充通常是不必要的,但如果src的长度至少为n,则dest将不会被null终止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中的污染字符串警告,尽管副本的大小与原始大小相同,并且可能无法使用足够的内存,应该对其进行测试。从Tainted string in C来看,似乎Coverity对于受污染的字符串有点极端。虽然你得到的警告表明存在真正的问题,但摆脱警告有时可能需要奇怪的解决方法。

答案 2 :(得分:0)

If Not IsObject(App) Then
   Set SapGuiAuto = GetObject("SAPGUI")
   Set App = SapGuiAuto.GetScriptingEngine
End If
If Not IsObject(Connection) Then
   Set Connection = App.Children(0)
End If
If Not IsObject(session) Then
   Set session = Connection.Children(0)
End If
If IsObject(WScript) Then
   WScript.ConnectObject session, "on"
   WScript.ConnectObject App, "on"
End If

session.findById("wnd[0]").maximize
session.findById("wnd[0]/tbar[0]/okcd").Text = "/nXXXX" 'XXX = your t-code
... ...

不仅仅是你需要的吗?您是否有理由复制getenv返回的内容?如果是的话,

char *path = getenv("A");

答案 3 :(得分:0)

  

下面的修复会消除此错误吗?

不,但这几乎肯定会:

char *e = getenv("A");
char path[e ? strlen(e) + 1 : 1];
strcpy(path, e ? e : "");

getenv("A")返回1024字节或更长字符串的字符串时,会出现代码的主要问题。将其复制到path会导致缓冲区溢出,因为不能保证strlen(getenv("A"))小于或等于1024.您可以通过使用以下方法解决此问题:

strncpy(path, getenv("A"), sizeof path); // NOT RECOMMENDED

...但后来path不会以'\0'字符终止; path在这种情况下不会成为字符串,因为根据定义,字符串必须'\0'字符终止...这意味着您不会能够将它用作字符串。

Coverity最有可能在这里抱怨,我的代码通过使用足够大的VLA(可变长度数组)存储整个字符串以及'\0'来解决问题。字符串的结尾。