我在这里有缓冲区溢出的风险吗?如何避免?

时间:2018-12-08 10:39:37

标签: c string c-strings string-literals

我实现了一个简单的列表结构,其中单个列表元素由以下结构定义:

struct list_elem {
    struct list_elem *next;  // ptr to the next element
    char             *data;  // ptr to data
};

现在,我要执行以下操作:

struct list_elem *elem;
int main() {
    elem->data = "some_string";
    strcat(elem->data, "another_string");
}

我担心超载,因为strcat的手册页指出:

  

char *strcat(char *dest, const char *src)函数将src字符串追加到dest字符串,覆盖dest末尾的终止空字节('\ 0'),然后添加一个终止的空字节。这些字符串可能不会重叠,并且dest字符串必须有足够的空间用于结果。 如果dest不够大,则程序行为无法预测;缓冲区溢出是攻击安全程序的常用途径。

基本上我不知道为列表元素分配了多少内存。

2 个答案:

答案 0 :(得分:3)

此声明:

elem->data = "some_string";

使data指针指向字符串文字"some_string"
在这里:

strcat(elem->data, "another_string");

您正在尝试将字符串文字"another_string"复制到指向另一个字符串文字的指针。按照标准,尝试修改字符串文字会导致未定义的行为,因为它可能存储在只读存储器中。

您应将内存分配给data,如下所示:

elem->data = calloc(50, 1); // sizeof (char) is 1

然后将"some_string"复制到其中;

strcpy (elem->data, "some_string");

然后将"another_string"连接到它:

strcat (elem->data, "another_string");

或者,您也可以使用snprintf()

snprintf (elem->data, 49, "%s%s", "some_string", "another_string");

编辑:

感谢@alk指出这一点。

elem指针未指向有效内存。 您应该首先将内存分配给struct list_elem指针elem,如下所示:

elem = malloc (sizeof (struct list_elem));
if (elem == NULL)
    exit(EXIT_FAILURE);

答案 1 :(得分:1)

您可以搜索astrxxx函数(不是标准C函数)。它们在操作时动态分配内存。 Github example implementations

  • astrcat已在上面实现。
  • asprintf是sprintf的动态版本。
  • 一些GNU编译器提供了更多

注意:您应该免费分配动态分配的内存!

另外,您应该这样使用它:

struct list_elem elem;    //removed *, as it can cause seg fault if not initialized. you have to initialize by using struct list_elem * elem=malloc(sizeof(struct list_elem)); or something.
int main() {
    elem.data = strdup("some_string");//you must free data later
    astrcat(&elem.data, "another_string");
    //use it
    free(elem.data);
}

首先,struct list_elem* elem初始化为NULL,因此必须在->语句之前使用有效地址进行初始化。 您可以将指向数据部分的指针分配给data,该指针不能正常修改。