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


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

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

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

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

Для исправления и предотвращения ошибок с использованием variadic функций можно использовать предупреждения от компилятора или сторонние статические анализаторы исходного кода. Стоит помнить, что статический анализ позволяет выявлять некорректные строки форматирования только если они известны в момент компиляции. Поэтому особую осторожность стоит проявлять в случае, если программа динамически формирует строку форматирования во время выполнения или получает её от пользователя.

Далее приведём несколько примеров ошибок использования функций с переменным количеством аргументов, найденных в известных open-source проектах с помощью статического анализатора PVS-Studio.

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

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. Неиспользуемый аргумент.

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

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

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


Найденные ошибки

Проверено проектов
361
Собрано ошибок
13 428

А ты совершаешь ошибки в коде?

Проверь с помощью
PVS-Studio

Статический анализ
кода для C, C++, C#
и Java

goto PVS-Studio;