警告:gets函数存在安全隐患。

17

当我使用gets函数时,gcc会给出一个警告:

warning:the `gets' function is dangerous and should not be used.

为什么gets()和puts()函数是危险的?


19
"puts()" 函数并不危险。你为什么也要问关于 "puts()" 的问题? - Greg Hewgill
6个回答

50
如果你有这样的代码:
char s[10];
gets( s );

如果在程序运行时输入超过10个字符,您将会溢出缓冲区,导致未定义的行为。gets()函数无法阻止您输入字符,因此应该避免使用它。相反,您应该使用fgets()函数,它允许您限制读取的字符数,以避免缓冲区溢出。
char s[10];
fgets( s, 10, stdin );

puts() 函数非常安全,前提是你要输出的字符串必须以空字符结尾。


6
fgets 不会丢弃字符,它会将它们留下未读。后续调用 fgets 或任何其他读取函数可以读取剩余的字符。 - R.. GitHub STOP HELPING ICE
@R. 确实 - 我会编辑我的回答。顺便说一下,R. 不是一个好的或明智的 SO 用户名。 - anon

5

gets函数无法限制其读取数据的数量,因此容易受到缓冲区溢出攻击。@Neil的答案提供了适当的解决方案。

puts函数在我看来并不危险,除非你忘记给它加上空字符终止符。


3

缓冲区溢出是非常危险的。以下是定义:

/* Get a line from the stdin stream. */
char *gets(char *buffer);

缓冲区有多大?如果用户输入的数据超出了缓冲区的容量,程序可能会崩溃并易受到黑客攻击。


2
根据维基百科的文章所述,gets()因其只使用char *作为参数而本质上不安全。
这很危险,因为在任何情况下该方法都无法知道已分配给该char *的空间大小。 因此,gets 行为就像它拥有一个空白支票,可以尽可能多地写入数据,这可能导致缓冲区溢出。
替代方案是fgets ,它不仅需要字符数组,还需要最大长度和流指针。 gets 仅为与旧代码向后兼容而保留。

1

Gets函数不检查缓冲区溢出,可能会导致代码受到攻击。


你好!如果使用gcc选项-fno-stack-protector进行构建,则使用gets()没有问题。之后,像这样的代码似乎是可以接受的: char ch[] = {0}; gets(ch); - Олег Сидоров

1

gets 函数将数据读入内存区域,直到遇到换行符或文件结束符。如果输入(例如由用户提供的输入)包含比 gets 提供的缓冲区大小更长的行,则会发生溢出,并且 gets 将写入缓冲区外部的内存。最坏的情况是,这可能允许恶意用户编写更改程序行为甚至执行具有该程序特权的任意代码(例如,在远程服务器上运行或使用其他用户的特权),即使是意外的溢出也很可能破坏软件。

应改用 fgets,因为它需要一个额外的参数来限制输入的大小。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接