在我看来,两者都有可能溢出缓冲区。但我建议永远不要使用gets()但仍然鼓励使用scanf()。
是否仅仅是因为scanf()中允许的格式化参数,还是有其他原因?
答案 0 :(得分:9)
gets
函数不受缓冲区溢出的保护。
使用scanf
格式字符串,您可以定义要从标准输入读取的字符串的最大长度,并将其存储在给定的内存缓冲区中。例如,使用scanf("%10s\n", str);
,最多可读取10个字符。 str
缓冲区应该是11个字节来存储NULL终止字符。
性能方面,如果您仅使用scanf
来解决gets
的缓冲区溢出问题,请使用fgets
函数。
答案 1 :(得分:2)
因为你可以输入比缓冲区大小更多的字符,而gets()会很乐意允许它。此外,不推荐使用gets()(在C11中)。因此与scanf()的比较不再有效。除了scanf()在处理无格式数据时也有自己的问题。
因此,更好的选择是fgets(),然后根据您的需要进行处理。
答案 2 :(得分:1)
因为没有办法防止缓冲区溢出。由于指定了最大缓冲区长度,因此fgets更安全。
答案 3 :(得分:1)
使用gets
时,如果输入格式错误,则无法防止缓冲区溢出。 scanf
允许控制读取的数据量。
答案 4 :(得分:1)
仍然鼓励使用scanf()。
谷歌快速搜索“scanf security”会产生〜212k的结果。第一个是Wikipedia,其中说明了
使用没有长度说明符的
%s
占位符本质上是不安全的,可用于缓冲区溢出。
因此,有足够的关于网络上scanf
安全性的信息。与gets
的区别在于scanf
具有安全用途,而使用gets
实际上总是一个坏主意。
答案 5 :(得分:1)
gets()的名义任务是从流中读取字符串。调用者告诉它将传入的字符放在哪里。但是gets()不检查缓冲区空间。如果调用者提供指向堆栈的指针,并且输入多于缓冲区空间,则gets()将覆盖堆栈。大多数系统都容易被覆盖堆叠中间的现有条目覆盖更大的东西,这也会覆盖相邻的条目。一个malefactor可以通过在参数字符串中存储正确的二进制模式来修改堆栈中的过程激活记录中的返回地址。这会将执行流程转移回其来源,而是转移到一个特殊的指令序列,该序列调用execv()以用shell替换正在运行的映像。此shell可以发出命令以将病毒副本拖到系统中。所以gets()不安全。