非null终止字符串 - KlocWork错误,没有可理解的原因

时间:2010-07-05 16:38:29

标签: c klocwork

我最近安装了“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 ; 
}

任何想法?

3 个答案:

答案 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案例。

总体而言,这是一款优秀的产品,但确实有一些漏洞,你无法解决所有问题。