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 тоже.