scanf Cppcheck警告

时间:2011-08-11 07:43:48

标签: c 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 -e ...

3 个答案:

答案 0 :(得分:6)

最后一行是一个示例命令,用于演示示例程序的崩溃。它本质上导致perl打印2.100.000次“5”,然后将其传递给程序“a.out”的stdin(这是编译的示例程序)。

首先,scanf()应仅用于测试,而不是在现实世界的程序中,因为它无法正常处理多个问题(例如,询问“%i”但用户输入“12345abc”( “abc”将保留在stdin中并可能导致后续输入被填充,而用户无法更改它们。)

关于这个问题:scanf()会知道它应该读取一个整数值,但它不会知道它可以多长时间。指针可以指向16位整数,32位整数,或64位整数或更大的东西(它不知道关闭)。具有可变数量的参数(用...定义)的函数不知道传递的元素的确切数据类型,因此它必须依赖于格式字符串(格式标记的原因不是像C#中那样是可选的你只需要编号,例如"{0} {1} {2}")。如果没有给定的长度,它必须假设一些可能与平台相关的长度(使得该函数更难以使用)。

通常,认为它可能有害并且是缓冲区溢出攻击的起点。如果您想保护并优化您的计划,请先将其替换为替代方案。

答案 1 :(得分:0)

我尝试对C程序运行perl表达式,它在Linux上崩溃了(分段错误)。

答案 2 :(得分:0)

通常不推荐在实际应用中使用'scanf'(或fscanf和sscanf)功能,因为它不安全,如果提供了一些不正确的输入数据,它通常是缓冲区溢出的漏洞。 在许多常用的C ++库(QT,Microsoft Visual C ++运行时库等)中输入数字有更安全的方法。也许你可以找到“纯”C语言的安全替代品。