0

我最近安装了“klocwork”并试图摆脱现有代码上的错误。显示的错误似乎很简单。终止时没有 null 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 ; 
}

有任何想法吗?

4

3 回答 3

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所说的不同)。

于 2010-07-05T18:24:55.797 回答
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

我们目前正在开发以清理它并使其更易于理解。不仅是问题,还有解决方案。

于 2010-07-06T16:00:48.683 回答
0

撇开 Klocwork 的错误不谈,我认为这段代码是错误的。为什么将缓冲区大小限制vsnprintf为 4096,而缓冲区大小为SNMP_BUF_LEN?这两者是如何相互关联的?如果SNMP_BUF_LEN< 4096,那么您可能刚刚溢出缓冲区。为什么不将SNMP_BUF_LEN其作为 vsnprintf 中的限制参数传递?

此外,写入destStr[writtenchars]是可疑的。根据 vsnprintf 的变体(它们确实有所不同),writtenchars 可能是它想要写入的字符数,这会再次导致您写入超出缓冲区的末尾。

综上所述,Klocwork 并不完美。我们有非常明确地试图保证安全的宏,而 Klocwork 错误地将它们检测为可能超出字符串。我认为那也是一个 snprintf 案例。

总的来说是一款不错的产品,但它确实有一些漏洞,你无法解决它的所有抱怨。

于 2010-07-05T17:17:10.720 回答