我正在编写一个小的C代码来获取一些用户输入,这将是一个字符串。现在我在许多地方读到使用gets()将非常不安全,因为它可能导致缓冲区溢出攻击。在大多数地方,我发现替代方法是使用fgets(),就缓冲区溢出而言,这更安全。
现在我遇到了一个问题场景,其中我不知道手前的缓冲区大小。它只是无法确定。它可能是任何东西。那么在这种情况下,fgets()会派上用场吗?
另外,如果我使用gets()来解决这个问题会出现什么问题呢?
char * temp_buffer_to_hold_user_input = NULL;
cahr * actual_buffer_that_stores_user_input = NULL;
int length_of_user_input =0;
/* taking user input, irrespective of its length using gets() */
gets(temp_buffer_to_hold_user_input);
/* now finding the length of the user input string and allocating the required number of bytes for proper (safe) usage */
length_of_user_input=length(temp_buffer_to_hold_user_input);
actual_buffer_that_stores_user_input = (char*)malloc(length_of_user_input*sizeof(char));
strcpy(actual_buffer_that_stores_user_input, temp_buffer_to_hold_user_input);
/* and now we work with our actual buffer */
上面的gets()用法是否还有缓冲区溢出问题?因为,在上面我们根本没有声明一个固定大小的缓冲区......所以没有缓冲区溢出是我所期待的。
如果我错过了什么,请纠正我!
答案 0 :(得分:5)
char * temp_buffer_to_hold_user_input = NULL;
您将指针设置为NULL
。因此根本没有缓冲区而gets
会因未定义的行为而失败(实际上可能是分段错误)。
gets
要求您提供指向缓冲区的有效指针。空指针不指向任何内容,因此不满足此前提条件。由于所有缓冲区都具有有限长度且用户输入长度未知,因此根本无法避免潜在的缓冲区溢出(更不用说安全风险)了。这是非常糟糕的,gets
已从官方标准中删除。
正确的方法是使用fgets
。处理可变大小的输入很棘手,所以你有两个选择:
fgets
与“我所有情况下足够大”缓冲区大小一起使用。简单的出路。最糟糕的情况是你失去了一些投入。fgets
并连接到一些动态分配的数组(并且不要忘记根据需要调整此数组的大小!),直到到达分隔符。 注意:取决于您对字符串的操作,您甚至可能不需要保留整个内容,这简化了事情。答案 1 :(得分:2)
如果您事先不知道缓冲区大小,可以查看getline(),或构建自己的函数和realloc
字符串,如:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char buf[8], *s = NULL, *p;
size_t i = 0;
while (fgets(buf, sizeof buf, stdin)) {
if (i++ == 0) {
s = malloc(sizeof buf);
if (s == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
strcpy(s, buf);
} else {
s = realloc(s, (i + 1) * sizeof(buf));
if (s == NULL) {
perror("realloc");
exit(EXIT_FAILURE);
}
strcat(s, buf);
}
if ((p = strchr(s, '\n'))) {
*p = '\0';
break;
}
}
printf("%s\n", s);
free(s);
return 0;
}
没有中间缓冲区:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUF_LEN 8
int main(void)
{
size_t len = BUF_LEN;
char *s, *p;
p = s = malloc(len);
if (s == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
while (fgets(p, BUF_LEN, stdin)) {
if ((p = strchr(p, '\n'))) {
*p = '\0';
break;
} else {
len += BUF_LEN - 1;
s = realloc(s, len);
if (s == NULL) {
perror("realloc");
exit(EXIT_FAILURE);
}
p = s + len - BUF_LEN;
}
}
printf("%s\n", s);
free(s);
return 0;
}
答案 2 :(得分:0)
调整gets()以避免缓冲区溢出
其他人已经在身体上解决了你的问题。这是一个快速回答,解决了标题中的问题。
标准C通过gets
提供gets_s
的“更安全”变体。它被ISO/IEC TR 24731-1添加到C标准中。除此之外,TR 24731-1的更安全功能检查目标缓冲区大小,以避免其“不安全”对应物的许多缓冲区溢出问题。
以下是文件:
所以你真的不需要调整任何东西。您只需要为作业使用正确的功能;)