新指针(通过malloc)与其中一个释放/旧指针

时间:2017-12-20 04:46:10

标签: c pointers heap-memory

我正在尝试跟踪C中的释放后使用错误。 我的问题是,如果我有这样的代码:

A * ptrA = malloc(sizeof(A));
A * aliasA = ptrA;
// do something ' 
free(ptrA) 
// some other code
B * ptrB = malloc(sizeof(B)); // assume this return same pointer as ptrA
//trying to use aliasA here

只是想知道aliasA的使用是否是UAF错误? 如果是的话,这里出了什么问题?

要清除这个问题,我认为最好添加一个小例子:

int main(){
    int *ptr = (int *)malloc(4);
    *ptr = 5;
    int *ptr2 = ptr;
    printf("%d\n", *ptr);
    free(ptr);

    int *new_ptr = malloc(4);
    *new_ptr = 66;
    printf("%d\n", *ptr2);

    return 0;
}  

输出是:

5
66

(我检查了S2E中的ptrnew_ptrhttp://s2e.systems/,这两个指针实际上指向相同的地址。释放ptr后,相同的地址被分配给new_ptr。)< / p>

从上面的输出中,似乎ptr2的使用提供了与new_ptr相同的输出。

当我编写我的解决方案以检测UAF错误时,我会记录指针的信息。指针&#39;值存储为uint64_t,布尔类型flag用于声明指针是否处于活动状态。

因此,我认为当new_ptrptr指向同一地址时会出现问题,因为一旦malloc()被调用,flag的{​​{1}}就会转向new_ptr。之后,当我使用true时,我无法检测到此UAF错误,因为此地址已标记为活动。

提前致谢!

3 个答案:

答案 0 :(得分:3)

如果你没有取消引用指针aliasA,那么它取决于&#34;免费使用后的定义&#34;这是否构成&#34;免费使用&#34;。例如,CWE-416并未讨论使用指针值,而是解除引用它,即使用已释放的对象

然而,C标准表示即使使用指针值也有未定义的行为(Appendix J.2)

  
      
  1. 在以下情况下,行为未定义:

         

    [...]

         
        
    • 使用引用通过调用free或realloc函数释放的空间的指针的值(7.22.3)。
    •   
  2.   

这是因为value of the pointer becomes indeterminate

  

当指针指向(或刚刚过去)的对象到达其生命周期的末尾时,指针的值变得不确定。

因此,以下代码具有未定义的行为:

A *ptrA = malloc(sizeof(A));
A *aliasA = ptrA;
free(ptrA);
A *ptrB = malloc(sizeof(A));

if (aliasA == ptrB) { // undefined behaviour, as it might be a trap
    printf("We were given the same pointer");
}

比较没有意义,编译器可以自由地通过优化做任何事情,因为aliasA不再需要包含有效值。编译器甚至可以将陷阱设置为aliasA,这会导致程序在if语句中使用诊断消息中止。或者可能是这些似乎指向相同的地址,即使它们被赋予了不同的内存地址,反之亦然。

答案 1 :(得分:1)

是UAF错误。

实际上,第二个malloc()调用返回与aliasA相同的地址非常,因为行为无法保证。你不应该依赖它。

您可能会问:我可以比较它们以确保它们具有相同的地址吗?嗯,不。比较可能对您有所帮助,但它是未定义的行为,因为指针相等性比较仅在两个指针指向同一数组中的不同元素时才有效。在这种情况下,两个分配的块肯定不是相同的数组,因此这些指针之间的比较没有明确定义。

最后,您不应该依赖malloc()返回的地址。您所能做的就是在呼叫时请求的内存量内使用它。

在实践中,Thiru Shetty's answer是一种很好的追求方式。

答案 2 :(得分:0)

aliasA是UAF错误,它可能与ptrA保持相同的值,但不保证,建议重新分配释放的指针(两个aliasA和ptrA)到NULL以避免dangling pointer

在您的情况下,最好在NULL之后指定free

free(ptrA);
free(aliasA);
ptrA = NULL;
aliasA = NULL;