[英]Tweaking gets() to avoid buffer overflow
我正在编写一个小的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()的用法是否仍然存在缓冲区溢出问题? 因为,在上面我们根本没有声明一个固定大小的缓冲区...因此,没有缓冲区溢出是我所期望的。
如果我错过了某些东西,请纠正我!
char * temp_buffer_to_hold_user_input = NULL;
您将指针设置为NULL
。 因此,根本没有缓冲区,并且gets
将因未定义的行为而失败(实际上可能是分段错误)。
gets
要求您提供一个指向缓冲区的有效指针。 空指针不指向任何内容,因此不满足该前提条件。 由于所有缓冲区的长度都是有限的,并且用户输入的长度是未知的,因此根本无法避免潜在的缓冲区溢出(更不用说安全风险了)。 它是如此糟糕, gets
了来自官方的标准中删除 。
正确的方法是使用fgets
。 但是,处理可变大小的输入非常棘手,因此您有两个选择:
fgets
使用“我的所有情况都足够大”的缓冲区大小。 简单的出路。 最糟糕的情况是您会丢失一些输入。 fgets
并连接到一些动态分配的数组(不要忘记根据需要调整该数组的大小!),直到到达定界符为止。 注意:不过,根据对字符串的处理方式,您甚至可能不需要保留整个内容,从而简化了事情。 如果您不知道缓冲区的大小,可以看一下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;
}
调整gets()以避免缓冲区溢出
其他人已经解决了您体内的问题。 这是一个快速解答,用于解决标题中的问题。
标准C通过gets_s
提供了gets
的“更安全”的变体。 它已通过ISO / IEC TR 24731-1被添加到C标准中。 除其他外,TR 24731-1的安全功能检查目标缓冲区的大小,以避免其“不安全”副本的许多缓冲区溢出问题。
来自文档:
因此,您实际上不需要进行任何调整。 您只需要使用正确的功能即可;)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.