【问题标题】:scanf Cppcheck warningscanf Cppcheck 警告
【发布时间】:2011-10-24 17:56:35
【问题描述】:

Cppcheck 显示以下 scanf 警告:

消息:没有字段宽度限制的 scanf 可能会因大量输入数据而崩溃。要修复此错误消息,请添加字段宽度说明符: %s => %20s %i => %3i 可能崩溃的示例程序: #包括 主函数() { 诠释一个; scanf("%i", &a); 返回0; } 让它崩溃: perl -e '打印“5”x2100000' | ./a.out

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

perl -e ...

【问题讨论】:

  • "按任意键继续。" “any key呢??”
  • @Dave:??????您的评论看起来像垃圾邮件:(
  • 什么?不。根据您问题的措辞,您似乎误解了“大量输入数据”这个短语——这不是您输入的内容,而是输入的属性。这与经典的任何关键笑话相同的场景,我用它来比喻你的问题。
  • @Dave:嗯,现在我明白了,我的问题看起来很有趣......只有一个人真正回答了它。 Mybe这是“巨大的输入数据在哪里”的问题:)

标签: c scanf cppcheck


【解决方案1】:

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

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

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

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

【讨论】:

  • Scanf 确切地知道指针的大小:%dsizeof(int)*8-bit,%ldsizeof(long)*8-bit,等等。所有这些在编译时都是已知的。
  • @Dave: int n[SIZE]; memset(n, 0, sizeof(n)*sizeof(int));
  • 我不明白为什么这个答案被接受。它没有回答这个问题。答案是 scanf() 假设输入字符串位数定义了它正在读取的整数的位宽(cppreference 不同意)?还是某些 scanf() 实现有内部溢出?
  • @Arvid 虽然我的回答有点离题,但这不是带有可变参数的函数的工作方式。参数编号和类型本质上是“丢失”的,必须根据格式字符串(或通过某些其他机制,具体取决于函数)进行重构。我不能 100% 确定标准的规定,但是如果输入的时间超过变量可以接受的时间,您可能会进入未定义的行为领域。
  • @CodeAbominator 那么如何编辑答案(如果可以)或发布自己的答案?只是抱怨没有提到的事情对任何人都没有帮助。随意发布替代且更完整的答案,然后在评论中提及问题的原始创建者,以考虑交换接受的答案。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-05
      • 1970-01-01
      • 1970-01-01
      • 2015-06-21
      • 2012-01-19
      • 2021-11-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多