V579. The 'Foo' function receives the pointer and its size as arguments. It is possibly a mistake. Inspect the N argument

21.07.2011

Анализатор обнаружил в коде подозрительный вызов функции. В качестве аргументов в функцию передается указатель и размер этого указателя. На самом деле, разработчики часто хотят передать в функцию не размер указателя, а размер буфера.

Рассмотрим, как подобная ошибка может возникнуть в коде. Предположим, в начале имелся код следующего вида:

char buf[100];
...
memset(buf, 0, sizeof(buf));

Код корректен. Функция memset() очищает массив из 100 байт. Затем, код изменился, и буфер стал переменного размера. Код очистки буфера изменить забыли:

char *buf = new char[N];
...
memset(buf, 0, sizeof(buf));

Теперь код некорректен. Оператор sizeof() возвращает размер указателя, а не размер буфера с данными. Как результат, функция memset() очищает только часть массива.

Рассмотрим другой пример, взятый из реального приложения:

apr_size_t ap_regerror(int errcode,
  const ap_regex_t *preg, char *errbuf,
  apr_size_t errbuf_size)
{
  ...
  apr_snprintf(errbuf, sizeof errbuf,
    "%s%s%-6d", message, addmessage,
    (int)preg->re_erroffset);
  ...
}

В таком коде заметить ошибку непросто. Функция apr_snprintf() принимает в качестве аргумента указатель 'errbuf' и размер этого указателя 'sizeof errbuf'. Анализатор считает этот код подозрительным и абсолютно прав. Размер буфера находится в переменной 'errbuf_size' и именно эту переменную следует использовать. Корректный код:

apr_snprintf(errbuf, errbuf_size,
  "%s%s%-6d", message, addmessage,
  (int)preg->re_erroffset);
Посмотрите на примеры ошибок в реальных проектах, найденные с помощью этой диагностики.