在我的代码上运行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));
答案 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'
来解决问题。字符串的结尾。