scanf Cppcheck предупреждение

Cppcheck показывает следующее предупреждение для scanf:

Сообщение: scanf без ограничений ширины поля может привести к сбою при огромных входных данных. Чтобы исправить это сообщение об ошибке, добавьте спецификатор ширины поля:
    %s => %20s
    %i => %3i

Пример программы, которая может привести к сбою:

#включают 
int main()
{
    int a;
    scanf("%i", &a);
    вернуть 0;
}

Чтобы сделать это сбой:
perl -e 'print "5"x2100000' | ./a.out

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

perl -e...

3 ответа

Решение

Последняя строка - это пример команды для запуска, чтобы продемонстрировать сбой с помощью примера программы. По сути, это заставляет perl печатать 2.100.000 раз "5", а затем передавать это в стандартный поток программы "a.out" (который должен быть скомпилированным примером программы).

Прежде всего, scanf() должен использоваться только для тестирования, а не в реальных программах из-за нескольких проблем, которые он не будет корректно обрабатывать (например, запрашивать "%i", но пользователь вводит "12345abc" ("abc" останется в stdin и может вызвать следующие вводы) быть заполненным без шансов для пользователя, чтобы изменить их).

По этому вопросу: scanf() будет знать, что должен прочитать целочисленное значение, однако он не будет знать, как долго это может быть. Указатель может указывать на 16-битное целое, 32-битное целое или 64-битное целое число или что-то еще большее (чего он не знает). Функции с переменным числом аргументов (определяется с помощью ...) не знаю точный тип передаваемых элементов, поэтому он должен полагаться на строку формата (причина, по которой теги формата не являются необязательными, как в C#, где вы просто нумеруете их, например, "{0} {1} {2}"). И без заданной длины он должен принимать некоторую длину, которая также может зависеть от платформы (что делает функцию еще более небезопасной для использования).

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

Я попытался запустить выражение perl для программы на C, и оно вылетело здесь в Linux (ошибка сегментации).

Использование функции 'scanf' (или fscanf и sscanf) в реальных приложениях обычно вообще не рекомендуется, потому что это небезопасно, и это обычно дыра для переполнения буфера, если будут предоставлены некоторые неверные входные данные. Есть много более безопасных способов ввода чисел во многих широко используемых библиотеках для C++ (QT, библиотеки времени выполнения для Microsoft Visual C++ и т. Д.). Вероятно, вы также можете найти безопасные альтернативы для "чистого" языка Си.

Другие вопросы по тегам