Строка с нулевым символом в конце - ошибка KlocWork без понятной причины - PullRequest
0 голосов
/ 05 июля 2010

Я недавно установил "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 ]

3 голосов
/ 05 июля 2010

KlocWork правильно диагностирует проблему, которую вы можете записать с нулевым указателем, если выделение памяти не удалось:

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

На данный момент (ужасно названная) переменная '_p_' по-прежнему равна нулю, но вы можете использовать ее в операции печати ниже.

Также обратите внимание, что «тривиальное» исправление добавления «1007 *» после этого нарушает управление памятью; позже вы выполните «free(_p_);», что приведет к ужасным проблемам, если «_p_» будет указывать на постоянную строку.

У вас также есть «память в в функция» в сообщении. И «неправильный номер параметров» означает примерно то же самое, что «неправильный номер параметров», но последний - более идиоматический английский. Я не уверен, что любой из восклицательных знаков полезен в сообщении об ошибке; существует сильный аргумент, что они должны выходить за пределы двойных кавычек, окружающих имя функции, даже если один из них считается желательным.


С исправленной версией проблемы мне интересно, диагностирует ли Klocwork то, что Microsoft говорит о своей vsnprintf () , что он не гарантирует нулевого завершения (что отличается от того, что C99 и POSIX говорит).

2 голосов
/ 06 июля 2010

Джонатан правильно понял. Недавно мы разбили эту проверку на две семьи, которые могли бы объяснить это лучше:

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

В настоящее время мы находимся в стадии разработки, чтобы исправить это и упростить понимание. Не только проблема, но и решение.

0 голосов
/ 05 июля 2010

Ошибка Klocwork в стороне, я думаю, что этот код неправильный.Почему вы ограничиваете vsnprintf до 4096, тогда как размер буфера равен SNMP_BUF_LEN?Как эти двое связаны друг с другом?Если SNMP_BUF_LEN <4096, возможно, вы только что переполнили буфер.Почему бы вам не передать <code>SNMP_BUF_LEN в качестве ограничивающего аргумента в vsnprintf?

Также запись в destStr[writtenchars] является подозрительной.В зависимости от варианта vsnprintf (они различаются), значениеCHLL может быть числом символов, которое хотел написать, что снова заставило бы вас писать после конца буфера.Тем не менее, Klocwork не идеален.У нас были макросы, которые явно пытались быть безопасными, и Klocwork ошибочно обнаружила их как потенциально выходящие за пределы строки.Я думаю, что это был случай snprintf.

В целом хороший продукт, но у него есть несколько дыр, и вы не можете исправить все его жалобы.

...