8

Cppcheck 对 scanf 显示以下警告:

消息:没有字段宽度限制的 scanf 可能会因大量输入数据而崩溃。要修复此错误消息,请添加字段宽度说明符:
    %s => %20s
    %i => %3i

可能崩溃的示例程序:

#包括
主函数()
{
    诠释一个;
    scanf("%i", &a);
    返回0;
}

让它崩溃:
perl -e '打印“5”x2100000' | ./a.out

我不能让这个程序在输入“大量输入数据”时崩溃。我到底应该输入什么来导致这个崩溃?我也不明白此警告中最后一行的含义:

perl -e ...

4

3 回答 3

6

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

首先,scanf()应该只用于测试,而不是在现实世界的程序中,因为它不能很好地处理一些问题(例如要求“%i”但用户输入“12345abc”(“abc”将保留在标准输入和可能会导致以下输入被填充,而用户没有机会更改它们)。

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

一般来说,认为它可能有害并且是缓冲区溢出攻击的起点。如果您想保护和优化您的程序,请先用替代方案替换它。

于 2011-08-11T07:57:26.723 回答
0

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

于 2011-08-11T07:51:31.647 回答
0

通常根本不建议在实际应用程序中使用“scanf”(或 fscanf 和 sscanf)函数,因为它不安全,而且如果提供了一些不正确的输入数据,通常会导致缓冲区溢出。在许多常用的 C++ 库(QT、Microsoft Visual C++ 的运行时库等)中,有更安全的方法可以输入数字。可能您也可以找到“纯”C 语言的安全替代方案。

于 2011-08-11T07:52:41.157 回答