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++ и т. Д.). Вероятно, вы также можете найти безопасные альтернативы для "чистого" языка Си.