多年来,gets它一直被普遍贬低为不安全的功能。(典型的问题是为什么 gets 函数如此危险以至于不应该使用它?)。该gets函数太糟糕了,以至于它已从 C11 语言标准中删除。支持者gets(如果有的话,也很少)会争辩说,如果您了解输入的结构,那么使用它是完全可以的。
为什么那些贬低gets并承认依赖输入结构的愚蠢的人允许使用%d用作scanf转换说明符?这是一个社会学问题,真正的问题是:为什么%d格式scanf字符串不安全?
如果格式字符串scanf包含原始%d转换说明符(“raw”表示“没有最大字段宽度”),并且输入流包含的字符串是无法放入int. 例如,字符串不能在平台 where 中5294967296表示。该语言仅保证 an足够大以容纳 -32767 到 +32767 的范围,因此包含该字符串的任何输入流都可能导致未定义的行为。这种潜在的未定义行为可以通过使用来避免。大多数现代平台的 INT_MAX 值远大于 32767,因此实际上转换说明符上的宽度修饰符可以大于 4,但应该根据平台确定(在编译时或运行时) ,并且它必须出现在格式字符串中。intsizeof(int) == 4Cint32768%4d
如果您不添加宽度修饰符,您也可以只使用将gets一行读入缓冲区并用于sscanf解析值。这(也许)会使错误对读者来说更加明显。
不,scanf("%d", \xe2\x80\xa6)没有那么糟糕gets。
gets之所以如此糟糕,是因为几乎不可能在任何环境中安全地使用它。缓冲区溢出是有可能发生的,无法避免,并且很可能导致任意严重的后果。
scanf("%d", \xe2\x80\xa6)另一方面,可能发生的最糟糕的事情是整数溢出。虽然这在理论上也是未定义的行为,但实际上它总是会导致(a)安静的环绕,(b)溢出到INT_MAX或INT_MIN,或 (c) 可能终止调用程序的运行时异常。
很难想象攻击者可以利用使用scanf("%d", \xe2\x80\xa6). 涉及的漏洞gets另一方面,
(虽然不是问的问题,但这确实scanf("%s", \xe2\x80\xa6)和gets。这是一个公平的问题,为什么前者并不总是像后者一样受到强烈贬低。)