繁体   English   中英

调整gets()以避免缓冲区溢出

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM