防止结构中的字符指针溢出

Preventing char pointer overflow in struct

我有一个函数接受包含敏感数据(在 char 数组中)的 struct * 指针作为参数(类似于小型库)。 两个struct型号如下:

struct struct1 {
    char str[1024]; /* maybe even 4096 or 10KB+ */
    size_t str_length;
}

struct struct2 {
    char *str;
    size_t str_length;
}

测试函数为:

/* Read str_length bytes from the char array. */
void foo(struct struct1/struct2 *s) {
    int i;
    for (i = 0; i < s->str_length; i++) {
        printf("%c\n", s->str[i]);
    }
}

我担心的是,由于 str_length 参数是一个任意值,有人可能故意将其设置为导致缓冲区溢出(实际上有人愚蠢到故意在它自己的程序中创建一个安全漏洞,但我觉得我必须考虑到这种情况)。但是,通过使用 struct1 模型,我可以通过使用以下命令简单地检查可能的缓冲区溢出:

if (s->str_length > sizeof(s->str)) {
    /* ERROR */
}

问题是长度数组在编译时实际上是未知。所以我不知道是使用 char * 指针(struct2 样式,所以没有溢出检查)还是定义一个非常大的数组(struct1),这会限制最大长度(这是我想避免的)并且大多数时候会分配不必要的 space(我想这在内存不足的嵌入式系统中可能会出现问题)。我知道我必须做出妥协,我个人会使用 struct2 模型,但我不确定它是否是安全方面的好选择。

把大数组放在最后..

struct struct1 {
    anyType thisVar;
    someType anotherVar
    size_t str_length;
    char str[10240000]; /
}

让用户将其 malloc 到他们想要的任何 'real' 大小。如果他们设置 'str_length' 错误,那么,无论您做什么,您都无能为力:(

您的库的用户从哪里获取要传递给函数的 struct2 实例?我认为他不会自己创建它然后将其地址传递给您的函数,那将是一种奇怪的传递参数的方式。它很可能是从您的库中的另一个函数返回的,在这种情况下,您可以使 struct2 成为用户无法直接更改(或只能以 hacky 方式)更改的不透明数据类型:

/* in the header file */
typedef struct2_s struct2;

/* in the implementation file, where allocation is handled as well 
 * so you know str_length is set to the proper value.
 */
struct struct2_s {
  char *str;
  size_t str_length;
};