paavohtl Claude Opus 4.6 commited on
Commit
ec26eaa
·
1 Parent(s): e007c5c

fix(hooks): correct vtable hook parameter counts from RET analysis

Browse files

ProcessFrame: RET 0x4 = 1 stack param (flags), was 0 — stack corruption
HandleMessage: RET 0x10 = 4 stack params (sender, msg_type, size, data), was 2

These wrong parameter counts caused stack corruption on every virtual
call, crashing when returning from a match to the main menu.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

crates/openwa-validator/src/hooks/vtable.rs CHANGED
@@ -76,23 +76,26 @@ impl VtableHook {
76
  static ORIG_CTASK_PROCESS_FRAME: AtomicU32 = AtomicU32::new(0);
77
 
78
  /// Hook for CTask::ProcessFrame (vtable slot 7).
79
- /// thiscall convention: ECX = this. We use fastcall (ECX = arg1, EDX = arg2).
80
- unsafe extern "fastcall" fn hook_ctask_process_frame(this: u32, _edx: u32) -> u32 {
81
- // Call original
82
- let orig: unsafe extern "fastcall" fn(u32, u32) -> u32 =
83
  core::mem::transmute(ORIG_CTASK_PROCESS_FRAME.load(Ordering::Relaxed));
84
- orig(this, 0)
85
  }
86
 
87
  /// Original CTask::HandleMessage function pointer
88
  static ORIG_CTASK_HANDLE_MESSAGE: AtomicU32 = AtomicU32::new(0);
89
 
90
  /// Hook for CTask::HandleMessage (vtable slot 2).
91
- /// thiscall(this, msg_id, param) — ECX = this, two stack params
92
- unsafe extern "fastcall" fn hook_ctask_handle_message(this: u32, _edx: u32, msg_id: u32, param: u32) -> u32 {
93
- let orig: unsafe extern "fastcall" fn(u32, u32, u32, u32) -> u32 =
 
 
 
94
  core::mem::transmute(ORIG_CTASK_HANDLE_MESSAGE.load(Ordering::Relaxed));
95
- orig(this, 0, msg_id, param)
96
  }
97
 
98
  // ---------------------------------------------------------------------------
 
76
  static ORIG_CTASK_PROCESS_FRAME: AtomicU32 = AtomicU32::new(0);
77
 
78
  /// Hook for CTask::ProcessFrame (vtable slot 7).
79
+ /// thiscall(this, flags) — RET 0x4 confirms 1 stack param.
80
+ /// flags bit 0: if set, frees `this` (scalar deleting destructor pattern).
81
+ unsafe extern "fastcall" fn hook_ctask_process_frame(this: u32, _edx: u32, flags: u32) -> u32 {
82
+ let orig: unsafe extern "fastcall" fn(u32, u32, u32) -> u32 =
83
  core::mem::transmute(ORIG_CTASK_PROCESS_FRAME.load(Ordering::Relaxed));
84
+ orig(this, 0, flags)
85
  }
86
 
87
  /// Original CTask::HandleMessage function pointer
88
  static ORIG_CTASK_HANDLE_MESSAGE: AtomicU32 = AtomicU32::new(0);
89
 
90
  /// Hook for CTask::HandleMessage (vtable slot 2).
91
+ /// thiscall(this, sender, msg_type, size, data) — RET 0x10 confirms 4 stack params.
92
+ /// Iterates children list and forwards message to each child's HandleMessage.
93
+ unsafe extern "fastcall" fn hook_ctask_handle_message(
94
+ this: u32, _edx: u32, sender: u32, msg_type: u32, size: u32, data: u32,
95
+ ) -> u32 {
96
+ let orig: unsafe extern "fastcall" fn(u32, u32, u32, u32, u32, u32) -> u32 =
97
  core::mem::transmute(ORIG_CTASK_HANDLE_MESSAGE.load(Ordering::Relaxed));
98
+ orig(this, 0, sender, msg_type, size, data)
99
  }
100
 
101
  // ---------------------------------------------------------------------------