悬挂指向多态类的指针会导致未定义的行为.它是否可以成为任何可以想象的腐败的根源?

Ste*_*and 10 c++ undefined-behavior dangling-pointer

我知道Undefined Behavior,一旦发生,就不可能再考虑代码了.我完全相信.我甚至认为我不应该过多地理解UB:一个理智的C++程序不应该与UB,Period一起玩.

但是为了让我的同事和经理们相信它的真正危险,我试图找到一个具体的例子,我们在产品中有一个错误(他们认为这不是危险的,最糟糕的是它总会崩溃访问违规).


我主要担心的是在悬挂指向多态类的指针时调用虚拟成员函数.

删除指针时,Windows操作系统将在堆块的标题中写入几个字节,并且通常还会覆盖堆块本身的第一个字节.这是跟踪堆块的方法,将它们作为链表进行管理......操作系统的东西.

虽然它没有在C++标准中定义,但多态性是使用虚拟表AFAIK实现的.在windows下,指向虚拟表的指针位于堆块的第一个字节中,给定一个只继承一个基类的类.(多继承可能更复杂,但我不会考虑这一点.我们只考虑基类A,以及几个B,C,D继承A).


现在让我们考虑我有一个指向A的指针,它被实例化为D对象.并且D对象已经在代码中的其他位置删除了:所以堆块现在是一个空闲的堆块,它的第一个字节已被覆盖,因此虚拟表指针几乎随机指向内存中的某个位置,让我们说地址0x01234567.

当代码中的某个地方,我们称之为:

void test(A * pA)   
{
    # here we do not know that pA is dangling pointer
    # that memory address has been deleted by another thread, in another part of the code
    pA->SomeVirtualFunction();
}
Run Code Online (Sandbox Code Playgroud)

我正确地说:

  • 运行时将解释地址处的内存,0x01234567就好像它是一个虚拟表一样
  • 如果在错误地解释这个内存地址就像vtable一样,它不会进入禁止内存区域,也不会有任何访问冲突
  • 假设虚拟表将为虚拟函数提供一个随机地址,比如说 0x09876543
  • 随机地址的内存0x09876543将被解释为有效的二进制代码,并且EXECUTED为real
  • 这可能导致任何可以想象的腐败

我不想夸大其词,以便说服.那么,我所说的是正确的,可能的,可能的吗?

gna*_*729 3

你的例子是一种可能性。

然而,情况要糟糕得多。

如果有人攻击您的应用程序的用户,那么内存将不会包含随机数据。攻击者将尝试并可能设法影响该数据的内容。一旦发生这种情况,攻击者也许能够确定将执行哪些代码。一旦发生这种情况,除非您的应用程序被正确地沙箱化(我敢打赌,您的合作开发人员不会采取这种态度),否则攻击者可能能够接管用户的计算机。

这不是一种假设的可能性,而是已经发生并将再次发生的事情。