我最近安装了“klocwork”,并试图摆脱现有代码上的错误。
显示的错误似乎很简单。在char * _p_
终止时不为空。
我手动添加了一个空终止(即使没有必要),但它不喜欢Klocwork。有什么想法吗?
确切的信息是: -
错误地终止字符串' p '导致 p 中的缓冲区溢出。
char *ptr;
int writtenchars = 0 ;
va_list args;
char* destStr;
if (argc != 2) {
printf(" wrong parameters number - %d instead of %d\n", argc, 2);
char str[25]="wrong parameters number ";
char *_p_; /********************************************************/
va_start(args, str);
destStr = (char*) malloc(SNMP_BUF_LEN);
_p_= destStr;
if (destStr == NULL) {
printf("WARNING: Failed to alloc memory in in function \"snmp_rebuildstringinbuf!!!\" \n");
destStr="kukuRiko";
}
else {
writtenchars = (int) vsnprintf(destStr, 4095, str, args);
if (writtenchars>SNMP_BUF_LEN) {
printf("WARNING: Too long string rebuilded in function \"snmp_rebuildstringinbuf!!!\" %d chars\n",writtenchars);
}
destStr[writtenchars] = '\0' ; //Moshe - making sure the last value of the string is null terminated in order to prevent future buffer overflows.
}
va_end(args);
/******************************************************************************/
//The KlocWork error relates to this line //
logCWriteLog_msg(moduleId, level, __FILE__, __LINE__, _p_, ltrue);
free (_p_);
=============================================== ============ 嗨,大家好, 谢谢你的回答,但似乎比这更模糊。我已经将代码改进为这个简单的案例: - 当代码全部写入一个函数时没有错误,而当分配部分包含在函数中(以及作为参数传递的文本)时,Klocwork错误返回。 请参阅此代码: - 没有错误的版本: -
char *_p_; /*+++++++++++++++++++*/
int writtenchars = 0 ;
va_list args;
char* destStr;
char* str = "hello World";
va_start(args, str);
destStr = (char*)malloc(SNMP_BUF_LEN);
if (destStr == NULL) {
printf("WARNING: Failed to alloc memory in function \n");
}
else {
writtenchars = (int) vsnprintf(destStr, (SNMP_BUF_LEN) - 1, str, args);
}
/*+++++++++++++++++++*/
_p_ = destStr ;
if (_p_ != NULL) {
logCWriteLog_msg(moduleId, level, __FILE__, __LINE__, _p_, ltrue);
}
free (_p_);
/***********************************************************/
当在/ * ++++ * /之间取代码并将其包装在函数中时,返回上面的KlocWork错误。
因此,
char *writingToSomeBuffer (char * str) {
int writtenchars = 0 ;
va_list args;
char* destStr;
va_start(args, str);
destStr = (char*)malloc(SNMP_BUF_LEN);
if (destStr == NULL) {
printf("WARNING: Failed to alloc memory in function \n");
}
else {
writtenchars = (int) vsnprintf(destStr, (SNMP_BUF_LEN) - 1, str, args);
}
return destStr;
}
int main () {
char *_p_;
_p_ = writingToSomeBuffer("hello world");
if (_p_ != NULL) {
logCWriteLog_msg(moduleId, level, __FILE__, __LINE__, _p_, ltrue);
}
free (_p_);
return 0 ;
}
任何想法?
答案 0 :(得分:3)
如果内存分配失败,KlocWork正确诊断出您可以使用空指针编写的问题:
_p_= destStr;
if (destStr == NULL)
{
printf("WARNING: Failed to alloc memory in in function ...\n");
destStr = "kukuRiko";
此时,(可怕命名的)“_p_
”变量仍然为空,但您继续在下面的打印操作中使用它。
另请注意,在此之后添加“_p_
”的“琐碎”修复会破坏您的内存管理;如果'free(_p_);
'指向常量字符串,你后来会做'_p_
'会导致可怕的问题。
您还在消息中的 功能中有“记忆”。并且'错误的参数数字'的确意味着与“错误的参数数量”大致相同,但后者更像是惯用的英语。我不相信任何感叹号都会对错误信息有帮助;有一个强烈的论点,即他们应该超出函数名称的双引号,即使其中一个被认为是可取的。
根据问题的修订版本,我想知道Klocwork是否正在诊断微软对其vsnprintf()所说的内容,它不保证空终止(这与C99和POSIX所说的不同)
答案 1 :(得分:2)
乔纳森说得对。我们最近将这个检查器拆分为两个可以更好地解释它的系列:
http://www.klocwork.com/products/documentation/Insight-9.1/Checkers:NNTS.MIGHT http://www.klocwork.com/products/documentation/Insight-9.1/Checkers:NNTS.MUST
我们目前正在开发中以清理它并使其更容易理解。不仅是问题,还有解决方案。
答案 2 :(得分:0)
除了Klocwork的错误,我认为这段代码是错误的。为什么要将vsnprintf
限制为4096,而缓冲区大小为SNMP_BUF_LEN
?这两者如何相互关联?如果SNMP_BUF_LEN
< 4096,那么你可能刚刚溢出了你的缓冲区。为什么不通过SNMP_BUF_LEN
作为vsnprintf中的限制参数?
此外,对destStr[writtenchars]
的写入是可疑的。根据vsnprintf的变体(它们确实有所不同),书写链可能是想要写入的字符数,这将再次导致您写入缓冲区的末尾。
所有人都说,Klocwork并不完美。我们有非常明确地尝试安全的宏,并且Klocwork错误地检测到它们可能超出了字符串。我认为这也是一个snprintf案例。
总体而言,这是一款优秀的产品,但确实有一些漏洞,你无法解决所有问题。