Skip to content

Commit 18ff075

Browse files
committed
fix: fix hasVtable false positive on address reuse
Fix hasVtable function to properly detect when object addresses are reused by different objects after multiple create/destroy cycles. Previously, the function only checked if the address existed in the mapping table, which could cause false positives when memory addresses were reused. The fix adds vtable pointer validation to ensure the current object's vtable matches the recorded ghost vtable. When a mismatch is detected, it logs a warning and cleans up stale mappings to prevent incorrect behavior. This prevents the resetVtable function from being called incorrectly on reused addresses. Log: Fixed vtable detection issue that could occur with object address reuse Influence: 1. Test creating and destroying objects multiple times to verify address reuse handling 2. Verify hasVtable returns correct results for both hooked and non- hooked objects 3. Test resetVtable functionality with objects that have been properly hooked 4. Check for any memory leaks or cleanup issues after multiple object cycles 5. Verify warning logs are generated when address reuse is detected fix: 修复地址重用时hasVtable误判问题 修复hasVtable函数,使其能正确检测在多次创建销毁对象后地址被不同对象重用 时的情况。之前函数仅检查地址是否在映射表中,这会在内存地址被重用时导致 误判。 修复增加了虚表指针验证,确保当前对象的虚表与记录的ghost虚表匹配。当 检测到不匹配时,会记录警告并清理过时的映射以防止错误行为。这防止了 resetVtable函数在重用的地址上被错误调用。 Log: 修复了对象地址重用时可能出现的虚表检测问题 Influence: 1. 测试多次创建和销毁对象以验证地址重用处理 2. 验证hasVtable对已挂钩和未挂钩对象返回正确结果 3. 测试已正确挂钩对象的resetVtable功能 4. 检查多次对象循环后是否存在内存泄漏或清理问题 5. 验证检测到地址重用时是否生成警告日志 PMS: BUG-329331 BUG-334591
1 parent 2dc1098 commit 18ff075

File tree

1 file changed

+32
-2
lines changed

1 file changed

+32
-2
lines changed

src/vtablehook.cpp

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,12 +238,42 @@ bool VtableHook::ensureVtable(const void *obj, std::function<void ()> destoryObj
238238
* \brief VtableHook::hasVtable 对象的虚表已经被覆盖时返回true,否则返回false
239239
* \param obj
240240
* \return
241+
*
242+
* 修复: 不仅检查地址是否在映射表中,还要验证当前对象的 vtable 是否与记录的 ghost vtable 匹配
243+
* 防止地址重用导致误判
241244
*/
242245
bool VtableHook::hasVtable(const void *obj)
243246
{
244247
quintptr **_obj = (quintptr**)(obj);
245-
246-
return objToGhostVfptr.contains(_obj);
248+
249+
if (!objToGhostVfptr.contains(_obj)) {
250+
return false;
251+
}
252+
253+
// 验证 vtable 是否匹配
254+
quintptr *ghost_vtable = objToGhostVfptr.value(obj);
255+
if (!ghost_vtable) {
256+
return false;
257+
}
258+
259+
// 检查当前对象的 vtable 指针是否指向我们记录的 ghost vtable
260+
if (*_obj != adjustToEntry(ghost_vtable)) {
261+
// vtable 不匹配,说明地址被重用了
262+
qCWarning(vtableHook) << "hasVtable: vtable mismatch! Address reused by different object."
263+
<< "obj:" << QString("0x%1").arg((quintptr)obj, 0, 16)
264+
<< "expected vtable:" << QString("0x%1").arg((quintptr)adjustToEntry(ghost_vtable), 0, 16)
265+
<< "actual vtable:" << QString("0x%1").arg((quintptr)*_obj, 0, 16);
266+
267+
// 清理旧的映射,避免后续误用
268+
// 注意:不要删除 ghost_vtable 内存,可能还在其他地方使用
269+
objToGhostVfptr.remove(obj);
270+
objToOriginalVfptr.remove(_obj);
271+
objDestructFun.remove(obj);
272+
273+
return false;
274+
}
275+
276+
return true;
247277
}
248278

249279
void VtableHook::resetVtable(const void *obj)

0 commit comments

Comments
 (0)