[英]Tweaking gets() to avoid buffer overflow
I am writing a small C code to take some user input, which would be a string. 我正在编写一个小的C代码以接受一些用户输入,这将是一个字符串。 Now I read at a lot of places that using gets() will be very unsafe as it may lead to buffer overflow attacks.
现在,我在很多地方读到,使用gets()将非常不安全,因为它可能导致缓冲区溢出攻击。 And in most of the places what I found as an alternative was using fgets() instead, which is safer as far as buffer overflows are concerned.
在大多数地方,我找到的替代方法是使用fgets(),就缓冲区溢出而言,这更安全。
Now I have a problem scenario, where in I do not know the buffer size before hand. 现在我有一个问题场景,在此之前我不知道缓冲区大小。 It just can not be determined.
只是无法确定。 It could be anything.
可能是任何东西。 So in this case, will fgets() be handy ?
因此,在这种情况下,fgets()会很方便吗?
Also, what is wrong if I make use of gets(), as shown below, to solve this problem ? 另外,如果我使用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 */
So does the above usage of gets() still have buffer overflow problem ? 那么上述gets()的用法是否仍然存在缓冲区溢出问题? Because, in the above we are not declaring a fixed size buffer at all in the first place... so no buffer overflow is what I am expecting.
因为,在上面我们根本没有声明一个固定大小的缓冲区...因此,没有缓冲区溢出是我所期望的。
Please correct me if I am missing out on something! 如果我错过了某些东西,请纠正我!
char * temp_buffer_to_hold_user_input = NULL;
You set the pointer to NULL
. 您将指针设置为
NULL
。 Hence there is no buffer at all and gets
will fail with undefined behavior (probably a segmentation fault in practice). 因此,根本没有缓冲区,并且
gets
将因未定义的行为而失败(实际上可能是分段错误)。
gets
requires that you present a valid pointer to a buffer. gets
要求您提供一个指向缓冲区的有效指针。 A null pointer doesn't point to anything, hence this pre-condition is not satisfied. 空指针不指向任何内容,因此不满足该前提条件。 Since all buffers have finite length and user input is of unknown length, there's just no way at all to avoid getting a potential buffer overflow (and not to mention security risk).
由于所有缓冲区的长度都是有限的,并且用户输入的长度是未知的,因此根本无法避免潜在的缓冲区溢出(更不用说安全风险了)。 It's so bad that
gets
has been removed from the official standard . 它是如此糟糕,
gets
了来自官方的标准中删除 。
The correct way is to use fgets
. 正确的方法是使用
fgets
。 Dealing with a variable-sized input is tricky though, so you have two options: 但是,处理可变大小的输入非常棘手,因此您有两个选择:
fgets
with a "large-enough for all my cases" buffer size. fgets
使用“我的所有情况都足够大”的缓冲区大小。 The easy way out. fgets
and concatenate to some dynamically allocated array (and don't forget to resize this array as needed!) until you reach the delimiter. fgets
并连接到一些动态分配的数组(不要忘记根据需要调整该数组的大小!),直到到达定界符为止。 Note: depending on what you're doing with the string though, you may not even need to hold the entire thing around, which simplifies things. If you don't know the buffer size before hand you can take a look to getline() , or build your own function and realloc
your string, something like: 如果您不知道缓冲区的大小,可以看一下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;
}
Without an intermediate buffer: 没有中间缓冲区:
#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;
}
Tweaking gets() to avoid buffer overflow
调整gets()以避免缓冲区溢出
Others have addressed your questions in the body. 其他人已经解决了您体内的问题。 Here's a quick answer that addresses the question in your title.
这是一个快速解答,用于解决标题中的问题。
Standard C provides a "safer" variant of gets
via gets_s
. 标准C通过
gets_s
提供了gets
的“更安全”的变体。 Its was added to the C Standard with ISO/IEC TR 24731-1 . 它已通过ISO / IEC TR 24731-1被添加到C标准中。 Among other things, the safer function of TR 24731-1 check the destination buffer size to avoid many of the buffer overflow problems of their "unsafe" counterparts.
除其他外,TR 24731-1的安全功能检查目标缓冲区的大小,以避免其“不安全”副本的许多缓冲区溢出问题。
Here's from the document: 来自文档:
So you really don't need to tweak anything. 因此,您实际上不需要进行任何调整。 You only need to use the correct function for the job ;)
您只需要使用正确的功能即可;)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.