scanf Cppcheck предупреждение
Cppcheck показывает следующее предупреждение для scanf:
Message: scanf without field width limits can crash with huge input data. To fix this error message add a field width specifier: %s => %20s %i => %3i Sample program that can crash: #include int main() { int a; scanf("%i", &a); return 0; } To make it crash: perl -e 'print "5"x2100000' | ./a.out
Я не могу разбить эту программу, набрав "огромное входных данных". Что именно я должен напечатать, чтобы получить эту аварию? Я также не понимаю значения последней строки в этом предупреждении:
на Perl -е ...
3 ответов
последняя строка является примером команды для запуска, чтобы продемонстрировать сбой с образцом программы. Это по существу заставляет perl печатать 2.100.000 раз "5", а затем передать это в stdin программы " 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++ и т. д.). Вероятно, вы можете найти безопасные альтернативы для "чистого" языка C тоже.