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

- Совместимость с предыдущими версиями
- Работа с неизвестными значениями аргументов для форматных строк
- Примечание касательно функции 'strncpy'

Анализатор обнаружил потенциально возможную ошибку, связанную с заполнением, копированием или сравнением буферов памяти. Ошибка может приводить к переполнению буфера (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 как критические и относятся к типу: Ошибки переполнения буфера (записи или чтения за пределами выделенной для буфера памяти).

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

CWE-119 CWE-125 CWE-193 CWE-467 CWE-682 CWE-787 CWE-806 CERT-ARR01-C CERT-ARR30-C

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