【问题标题】:Interpreting App Verifier output: Heap corruption or misinterpreting stack address as heap address?解释 App Verifier 输出:堆损坏或将堆栈地址误解为堆地址?
【发布时间】:2011-06-29 11:38:13
【问题描述】:

我们有一个测试用例,它使我们基于 MFC 的大型应用程序因堆损坏错误而崩溃。

我使用 App Verifier 为有问题的 DLL 打开了页面堆(不幸的是,由于其他原因,为整个进程打开堆不可行。)验证器没有向我们提供比我们已经提供的更多信息有;它与原始崩溃在同一时间触发。

现在我有两个相互竞争的理论。您认为哪种理论更有可能是正确的,您的下一步是什么?

  1. 这确实是堆损坏。验证程序没有捕捉到原始损坏,因为它发生在另一个 DLL 中。我们应该尝试为更多 DLL 激活验证程序,并确定哪些代码正在破坏堆。
  2. 堆没问题;问题是我们将堆栈地址视为堆地址。我们应该进一步研究此调用堆栈中的代码,以找出问题所在。

我倾向于 #2,因为 free() 的参数看起来像一个堆栈地址,但到目前为止,还没有人对这怎么可能提出解释。

这是调用堆栈的 sn-p。 MyString 是 CString 的简单包装器。 MyAppDll 是设置为使用页堆的 DLL。

msvcr90.dll!free(void * pBlock=0x000000000012d6e8) 第 110 行
mfc90u.dll!ATL::CStringT > >::~CStringT > >() 第 1011 行 + 0x1e 字节
MyStringDll.dll!MyString::~MyString() 第 59 行
MyAppDll.dll!doStuffWithLotsOfStringInlining(MyClass* input=0x000000000012d6d0) 第 863 行 + 0x26 字节

这里是 free() 栈帧中的寄存器:

RAX = 0000000000000000 RBX = 000000000012D6E8 RCX = 0000000000000000 RDX = 0000000000000000 RSI = 000000000012D6D0 RDI = 00000000253C1090 R8 = 0000000000000000 R9 = 0000000000000000 R10 = 0000000000000000 R11 = 0000000000000000 R12 = 000000000012D7D0 R13 = 000007FFFFC04CE0 R14 = 0000000025196600 R15 = 0000000000000000 RIP = 00000000725BC7BC RSP = 000000000012D570 RBP = 000007FFF3670900 EFL = 00000000

这是应用验证程序消息:

验证器停止 0000000000000010:pid 0x1778:堆块的开始标记损坏。 00000000083B1000 :调用中使用的堆句柄。 000000006DD394E8 :操作中涉及的堆块。 54D32858A8747589 :堆块的大小。 000000005E33BA8D:损坏的戳值。

【问题讨论】:

    标签: winapi mfc heap-memory c-strings stack-memory


    【解决方案1】:

    我认为您的字符串或它的用户在某处溢出/下溢字符串的缓冲区,可能是针对字符串指针旁边的字段,然后您尝试释放该字段。

    您的 RSP 是 12D570,与您要释放的对象相差 94 个四边形(整数),因此介于两者之间的某个地方,缓冲区发生了一些不好的事情。

    确认您没有执行任何不安全的字符串操作,并且您正在正确阅读将缓冲区/字符串传递到您正在使用的 DLL 的文档。

    如果您想要更准确的答案,您的问题中可能需要更多代码。

    【讨论】:

    • 谢谢,这就是我正在寻找的答案。不幸的是,这里涉及的代码太多,无法给出完整的画面,我认为简短的摘录不会有帮助。
    • 您不能信任 x64 模式下调用堆栈中显示的参数值,它们是在寄存器中传递的。这些寄存器值已被长期覆盖。 RBP 看起来非常不高兴。
    • 原来我们的字符串包装类在放置 new 方面做了一些聪明的事情,导致 MFC 的 nil 字符串数据单例中的引用计数永久增加。最终(即,在 20 亿次错误代码调用之后)引用计数溢出并变为负数,并且 nil 缓冲区被删除!然后下一个要被破坏的空字符串执行双重释放。
    猜你喜欢
    • 1970-01-01
    • 2023-03-20
    • 2017-11-11
    • 2012-08-09
    • 2018-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-30
    相关资源
    最近更新 更多