scanf Cppcheck警告

Ale*_*x F 7 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 ...

Mar*_*rio 6

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

首先,scanf()应该仅用于测试,而不是在现实世界的程序中由于几个问题而无法正常处理(例如,询问"%i"但用户输入"12345abc"("abc"将保留在标准输入和可能导致以下输入被填充,而用户无法更改它们).

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

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

  • Scanf确切知道指针的大小:`%d`是`sizeof(int)*8`-bit,`%ld`是`sizeof(long)*8`-bit,依此类推.所有这些在编译时都是已知的. (3认同)