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 ...
答案 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语言的安全替代品。