﻿# Функции с переменным количеством аргументов

Функцией с переменным количеством аргументов \(variadic функцией\) называют функцию, способную принимать заранее неопределённое количество входных аргументов\. Во многих языках программирования функции форматного вывода определены как variadic функции\.

В С\+\+ функции с переменным количеством аргументов объявляются с помощью многоточия \(\.\.\.\) в списке аргументов\. Компилятор осуществляет проверку типов только для явно заданных аргументов\. Для доступа к переменному списку аргументов используются макросы **va\_arg**, **va\_end**, и **va\_start** из заголовочного файла STDARG\.H\. Семейство функций **printf **является одним из распространённых примеров функций с переменным количеством аргументов\.

В некоторых языках использование функций с переменным количеством аргументов может приводить к  проблемам с безопасностью типов\. Например в С/C\+\+ функции семейства printf при неосторожном использовании могут создавать [уязвимости](https://pvs-studio.ru/ru/docs/warnings/v576/) неконтролируемого формата строки\. Несоответствие строки форматирования и переданных аргументов может приводить к непредсказуемому поведению, ошибкам переполнения буфера, повреждению стека и выполнению произвольного кода, приводить к разрушению областей динамической памяти\. 

Хотя о подобных проблемах с variadic функциями известно уже достаточно давно, только в 1999 году они были идентифицированы как серьёзная уязвимость для безопасности\. А в связи с тем, что достаточно долго подобные уязвимости считались относительно безобидными, сейчас они являются одними из самых распространённых ошибок\.

Для исправления и предотвращения ошибок с использованием variadic функций можно использовать предупреждения от компилятора или сторонние статические анализаторы исходного кода\. Стоит помнить, что [статический анализ](https://pvs-studio.ru/ru/blog/terms/0046/) позволяет выявлять некорректные строки форматирования только если они известны в момент компиляции\. Поэтому особую осторожность стоит проявлять в случае, если программа динамически формирует строку форматирования во время выполнения или получает её от пользователя\.

Далее приведём несколько примеров ошибок использования функций с переменным количеством аргументов, найденных в известных open\-source проектах с помощью статического анализатора [PVS\-Studio](https://pvs-studio.ru/ru/pvs-studio/)\.

Проект ReactOS\. Некорректная печать символа типа WCHAR\.

```cpp
static void REGPROC_unescape_string(WCHAR* str)
{
  ...
  default:
    fprintf(stderr,
      "Warning! Unrecognized escape sequence: \\%c'\n",
      str[str_idx]);
  ...
}
```

Функция fprinf\(\) должна распечатать символ типа char\. Но третьим аргументов является символ типа WCHAR\. Пользователю будет выдано некорректно сформированное сообщение\. Чтобы код стал корректен, в строке, задающей формат, следует заменить '%c' на '%C'\.

Проект Intel AMT SDK\. Неиспользуемый аргумент\.

```cpp
bool GetUserValues(...)
{
  ...
  printf("Error: illegal value. Aborting.\n", tmp);
  return false;
}
```

Ошибка в том, что переменная 'tmp' никак не используется при выводе информационного сообщения\.

## Библиографический список

1. Wikipedia\. [Variadic function\.](https://en.wikipedia.org/wiki/Variadic_function)
1. Wikipedia\. [Format string attack\.](https://en.wikipedia.org/wiki/Uncontrolled_format_string)
1. MSDN Library\. [Functions with Variable Argument Lists\.](https://msdn.microsoft.com/en-us/library/fxhdxye9(v=vs.100).aspx)
1. MSDN Library\. [va\_arg, va\_end, va\_start\.](https://msdn.microsoft.com/en-us/library/kb57fad8(v=vs.100).aspx)
1. Андрей Карпов\. [Не зная брода, не лезь в воду\. Часть вторая\.](https://pvs-studio.ru/ru/blog/posts/cpp/0129/)