简体   繁体   English

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

[英]Not null terminated string - a KlocWork error with no understandable reason

I've recently installed "klocwork" and am trying to get rid of bugs on an existing code. 我最近安装了“ klocwork”,并试图摆脱现有代码上的错误。 The error shown seems to be simple. 显示的错误似乎很简单。 No null at the termination of the char * _p_ . char * _p_终止时不为null。 I have manually added a null termination (even though there is no need), but it doesn't please the Klocwork. 我已经手动添加了一个空终止符(即使没有必要),但这并不能使Klocwork满意。 Any ideas? 有任何想法吗?

The exact message is:- 确切的消息是:-

Incorrectly terminated string ' p ' causes a buffer overflow in p . 错误地终止的字符串“P”导致P A缓冲区溢出。

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_);   

=========================================================== Hi Guys, Thanks for your answers, but it seems a bit more obscure than that. ================================================== =========大家好,谢谢您的回答,但似乎比这还晦涩。 I have refined the code to this simple case:- When the code is written all in one function there is no error, whereas, when the allocation section is wrapped in a function (and a text passed as parameter) the Klocwork error returns. 我将代码优化为这种简单的情况:-将代码全部写在一个函数中时,没有错误,而将分配节包装在一个函数中(以及作为参数传递的文本),则返回Klocwork错误。 See this code:- version without an error:- 参见以下代码:-版本无错误:-

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_);
 /***********************************************************/

whereas when taking the code between /*++++ */ and wrapping it in a function returns the above KlocWork error. 而在/ * ++++ * /之间获取代码并将其包装在函数中时,将返回上述KlocWork错误。

Hence, 因此,

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 ; 
}

any ideas? 有任何想法吗?

KlocWork is correctly diagnosing the problem that you can be writing with a null pointer if memory allocation fails: 如果内存分配失败,KlocWork可以正确诊断您可以使用空指针编写的问题:

_p_= destStr;
if (destStr == NULL)
{
    printf("WARNING: Failed to alloc memory in in function ...\n");
    destStr = "kukuRiko";

At this point, the (horribly named) ' _p_ ' variable is still null, but you go ahead and use it in the printing operation below. 在这一点上,(很叫)' _p_ '变量仍然为空,但是您可以继续在下面的打印操作中使用它。

Also note that the 'trivial' fix of adding ' _p_ ' after this breaks your memory management; 还要注意,在此之后添加“ _p_ ”的“琐碎”修复会破坏您的内存管理; you later do ' free(_p_); 你以后做' free(_p_); ' which will lead to horrible problems if ' _p_ ' points to the constant string. 如果' _p_ '指向常量字符串,将导致可怕的问题。

You also have 'memory in in function' in the message. 您还可以“ 功能记忆”在消息中。 And 'wrong parameters number' does mean roughly the same as 'wrong number of parameters' but the latter is more idiomatic English. “错误的参数号”的含义与“错误的参数号”大致相同,但后者是更惯用的英语。 I'm not convinced any of the exclamation marks are helpful in the error message; 我不认为任何感叹号都会对错误消息有所帮助; there is a strong argument that they should go outside the double quotes surrounding the function name even if one of them is deemed desirable. 有一个强有力的论据认为,即使认为其中之一是可取的,它们也应该在函数名的双引号之外。


With the revised version of the problem, I wonder if Klocwork is diagnosing what Microsoft says of its vsnprintf() , that it does not guarantee null termination (which is different from what C99 and POSIX says). 对于问题的修订版本,我想知道Klocwork是否正在诊断Microsoft关于其vsnprintf()的说法,即它不能保证null终止(这与C99和POSIX所说的不同)。

Jonathan has it right. 乔纳森说对了。 We've recently broken up this checker into two families that might explain it better: 我们最近将此检查程序分为两个家族,可能会更好地解释它:

http://www.klocwork.com/products/documentation/Insight-9.1/Checkers:NNTS.MIGHT http://www.klocwork.com/products/documentation/Insight-9.1/Checkers:NNTS.MUST http://www.klocwork.com/products/documentation/Insight-9.1/Checkers:NNTS.MIGHT http://www.klocwork.com/products/documentation/Insight-9.1/Checkers:NNTS.MUST

We are currently under development to clean this up and make it easier to understand. 我们目前正在开发中,以清理并使其更易于理解。 Not only the problem but the solution as well. 不仅是问题,而且是解决方案。

Klocwork's error aside, I think this code is wrong. 除了Klocwork的错误,我认为这段代码是错误的。 Why are you limiting the vsnprintf to 4096, while the buffer size is SNMP_BUF_LEN ? 为什么在缓冲区大小为SNMP_BUF_LENvsnprintf限制为4096? How do those two related to each other? 这两个之间如何关联? If SNMP_BUF_LEN < 4096, then you may have just overflowed your buffer. 如果SNMP_BUF_LEN <4096,则可能是缓冲区溢出了。 Why wouldn't you pass SNMP_BUF_LEN as the limiting argument in vsnprintf? 为什么不通过SNMP_BUF_LEN作为vsnprintf中的限制参数?

Also, the write to destStr[writtenchars] is suspect. 同样,怀疑写入destStr[writtenchars] Depending on the variant of vsnprintf (they do vary), writtenchars might be the number of characters it wanted to write, which would again cause you to write past the end of your buffer. 根据vsnprintf的变体(它们确实有所不同),writechars可能是它写入的字符数,这将再次导致您在缓冲区末尾进行写入。

That all said, Klocwork isn't perfect. 综上所述,Klocwork并不完美。 We had macros that were very explicitly trying to be safe, and Klocwork mis-detected them as potentially overrunning the string. 我们有非常明确地试图确保安全的宏,而Kloc​​work误将其检测为可能超出了字符串的范围。 I think that was a snprintf case as well. 我认为这也是一个snprintf案例。

Overall a good product, but it does have a few holes and you can't fix all it's complaints. 总体来说是一个好的产品,但是它确实有一些漏洞,您无法解决所有问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM