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

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


> Примечание: ранее данная диагностика содержала в себе дополнительный функционал, но позже было решено вынести его в отдельную диагностику \[V1086\]\(https://pvs\-studio\.ru/ru/docs/warnings/v1086/\)\\\. О причинах и последствиях такого решения можно прочитать в \[специальной заметке\]\(https://pvs\-studio\.ru/ru/blog/posts/cpp/0978/\)\\\.



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

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

```cpp
#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:

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

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

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

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

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

MyTime s;
time(&s.time);
```

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

Ранее диагностическое правило содержало в себе дополнительный функционал, который был перенесён в диагностику [V1086](https://pvs-studio.ru/ru/docs/warnings/v1086/)\. Новая диагностика выявляет случаи, когда буфер обработан не полностью\.

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

```cpp
//-V512_OVERFLOW_OFF
```

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

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

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

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

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

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

```cpp
//V_512_WARN_ON_UNKNOWN_FORMAT_ARGS
```

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

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

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

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

На первый взгляд может показаться, что функция должна скопировать только 2 байта \(символ 'X' и [терминальный ноль](https://pvs-studio.ru/ru/blog/terms/0088/)\)\. Но, на самом деле, здесь действительно произойдёт выход за пределы массива\. Причиной тому является важное свойство функции 'strncpy':


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



Более подробно с этим или другими свойствами функции 'strncpy' можно ознакомиться на [cppreference](https://en.cppreference.com/w/c/string/byte/strncpy)\.