>
>
>
V512. Call of the 'Foo' function will l…


V512. Call of the 'Foo' function will lead to buffer overflow.

Анализатор обнаружил потенциально возможную ошибку, связанную с заполнением, копированием или сравнением буферов памяти. Ошибка может приводить к переполнению буфера (buffer overflow).

Примечание: ранее данная диагностика содержала в себе дополнительный функционал, но позже было решено вынести его в отдельную диагностику V1086. О причинах и последствиях такого решения можно прочитать в специальной заметке.

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

Рассмотрим пример N1:

#define BYTES_COUNT 5

struct Example
{
  unsigned char id[BYTES_COUNT];
  unsigned char extended[BYTES_COUNT - 2];
  unsigned char data[20];
};

void ClearID(Example *data)
{
  memset(&data->id, 0, BYTES_COUNT);
  memset(&data->extended, 0, BYTES_COUNT);
}

В данном примере в функцию 'ClearID' передаётся указатель на объект типа 'Example'. Внутри функции происходит очистка полей 'id' и 'extended' с помощью функции 'memset'. Из-за невнимательного использования макроса 'BYTES_COUNT' при очистке поля 'extended' произойдёт переполнение буфера, которое приведёт к перезаписи соседнего поля 'data'.

Также переполнение буфера можно получить при неправильном приведении типов, как в примере N2:

struct MyTime
{
  int timestamp;
  ....
};

MyTime s;
time((time_t*)&s.timestamp);

Данный пример, на первый взгляд, не содержит в себе опасностей и даже будет корректно работать, пока совпадает размер типов 'int' и 'time_t'. Проблема проявится при использовании стандартной библиотеки, где тип 'time_t' может быть 64-битным. При этом переменная 'int' имеет размер 32 бита.

В таком случае при вызове функции 'time' произойдёт запись в переменную 'timestamp', а также в область памяти после неё. Корректный вариант:

struct MyTime
{
  time_t time;
  ....
};

MyTime s;
time(&s.time);

Совместимость с предыдущими версиями

Ранее диагностическое правило содержало в себе дополнительный функционал, который был перенесён в диагностику V1086. Новая диагностика выявляет случаи, когда буфер обработан не полностью.

До разделения была возможность тонко настроить поведение диагностики и отключить неактуальную часть с помощью специальных комментариев. В целях обеспечения обратной совместимости, осталась возможность отключить диагностику V512 с помощью специального комментария:

//-V512_OVERFLOW_OFF

Этот комментарий можно вписать в заголовочный файл, который включается во все другие файлы. Например, это может быть "stdafx.h". Если вписать этот комментарий в "*.cpp" файл, то он будет действовать только для этого файла.

Поскольку теперь диагностика V512 ищет только переполнение буфера, то этот комментарий стал эквивалентен полному отключению диагностики (//-V::512).

Работа с неизвестными значениями аргументов для форматных строк

Иногда анализатор при работе с форматной строкой может не знать точное значение аргумента – к примеру, когда он пришёл из параметра функции:

void foo(int someVar)
{
  char buf[2];
  sprintf(buf, "%d", someVar);
  ....
}

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

//V_512_WARN_ON_UNKNOWN_FORMAT_ARGS

В этом случае для работы анализатор будет использовать диапазон значений из типа аргумента.

Примечание касательно функции 'strncpy'

Неоднократно к нам в поддержку обращались пользователи, считая, что анализатор выдаёт ложное предупреждение на подобный код:

char buf[5];
strncpy(buf, "X", 100);

На первый взгляд может показаться, что функция должна скопировать только 2 байта (символ 'X' и терминальный ноль). Но, на самом деле, здесь действительно произойдёт выход за пределы массива. Причиной тому является важное свойство функции 'strncpy':

Если требуемое количество символов (третий аргумент функции) больше длины исходной строки, то целевая строка будет дополнена нулевыми символами до требуемого размера.

Более подробно с этим или другими свойствами функции 'strncpy' можно ознакомиться на cppreference.

Выявляемые диагностикой ошибки классифицируются согласно ГОСТ Р 71207–2024 как критические и относятся к типу: Ошибки переполнения буфера (записи или чтения за пределами выделенной для буфера памяти).

Данная диагностика классифицируется как:

Взгляните на примеры ошибок, обнаруженных с помощью диагностики V512.