2016-03-25 26 views
0

我有一个函数,它接受包含敏感数据(在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),这将限制最大长度(我想避免的东西)和大部分时间都会分配不必要的空间(这在嵌入式系统中可能存在问题,我猜想)。我知道我必须作出妥协,我个人使用struct2模型,但我不确定这是否是一个安全明智的选择。

+1

如果你想有一个填充阶段教练与全功能的范围检查,你应该明确不使用C.如果用户改变了实例的指针? – Olaf

+0

习惯于此在结构的最后定义一个绝对巨大的数组以供您的lib使用,并让用户管理它的实际分配并传递一个指针和“实际”大小。您保持灵活性,不会浪费实际空间。当然,你不能直接拷贝结构体! –

+1

安全?这是C - 你已经没有安全:) –

回答

0

你的库的用户从哪里得到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; 
}; 
+0

其实我正在考虑传递结构地址,但是你的解决方案让我重新考虑了这个选项,但是这样,图书馆也应该照顾整个数据采集。我想要的只是传递char数组以便被函数处理。我希望我解释得很好...... – lorenzownd

0

把大阵在结束..

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

让它到任何“真实”的大小,他们希望用户的malloc。如果他们设置'str_length'是错误的,那么无论你做什么都没什么可做的:无论你做什么:(

+0

然而,在这种情况下,用户仍然完全能够通过传递错误的* str_length *值来溢出缓冲区。我认为你是对的,这不是一个简单的解决方案:( – lorenzownd