我有一个函数,它接受包含敏感数据的struct *
指针(在char
数组中)作为参数(有点像小库)。两个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("%cn", s->str[i]);
}
}
我担心的是,由于str_length参数是一个任意值,人们可能会故意将其设置为导致缓冲区溢出(实际上是有人愚蠢到故意在自己的程序中创建安全漏洞,但我觉得我必须考虑到这种情况)。然而,通过使用struct1模型,我可以简单地通过使用来检查可能的缓冲区溢出
if (s->str_length > sizeof(s->str)) {
/* ERROR */
}
问题是,长度数组在编译时实际上是未知的。因此,我不知道是使用char *
指针(struct2样式,因此没有溢出检查)还是定义一个非常大的数组(struct1),这会限制最大长度(我想避免这一点),并且大多数时候会分配不必要的空间(我想这在内存不足的嵌入式系统中可能会有问题)。我知道我必须做出妥协,我个人会使用struct2模型,但我不确定这是否是一个安全方面的好选择。
库的用户从哪里获得要传递给函数的struct2实例?我不认为他自己创建它,然后将它的地址传递给你的函数,这将是一种传递参数的奇怪方式。它很可能是从库中的另一个函数返回的,在这种情况下,您可以使struct2成为一种不透明的数据类型,用户无法直接更改(或只能以黑客的方式更改):
/* 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;
};
将大数组放在末尾。。
struct struct1 {
anyType thisVar;
someType anotherVar
size_t str_length;
char str[10240000]; /
}
让用户将其malloc为他们想要的任何"实际"大小。如果他们把"str_length"设置错了,那么,不管你做什么,你都无能为力:(