mountain 3 crash: rollingbouldermountain spawners end while their boulders still write parent.v13 (use after free), seen in game, one-word level fix tested; diag tooling in notes/dev
This commit is contained in:
1 parent
8b3c38fe56
commit
e36ff2d2c2
5 files changed
+537
No files matched your search
@@ -0,0 +1,285 @@
|
||||
; Mountain 3 crash diagnostics (German groove.exe). nasm -f bin -DCAVE=.. -DDATA=.. -DFIX=0/1
|
||||
bits 32
|
||||
org CAVE
|
||||
%define D(o) dword [DATA+o]
|
||||
; DATA layout: 0 magic, 16 cnt_parent_ok, 20 cnt_stale_addr, 24 cnt_stale_pop, 28 cnt_free, 32 cnt_anom,
|
||||
; 36 cnt_alloc, 40 stale ring idx, 44 all ring idx, 48 dummy, 52 last free ptr, 56 last alloc size, 60 tmp idx,
|
||||
; 64 stale ring 32x32, 1088 anomaly record 64 bytes, 1152 dump 256 bytes (hdr-128..+128), 1408 all-ring 64x32 (2048)
|
||||
; 3456 free history 64 x 16
|
||||
entry_addr: jmp near push_addr
|
||||
entry_pop: jmp near pop_var
|
||||
entry_free: jmp near free_hook
|
||||
entry_alloc: jmp near alloc_hook
|
||||
|
||||
push_addr:
|
||||
mov eax,[esp+4]
|
||||
mov ecx,[eax+0xc]
|
||||
mov edx,[esp+8]
|
||||
mov [DATA+60],edx
|
||||
mov edx,0x11
|
||||
call record_all
|
||||
test ecx,ecx
|
||||
jz .stale
|
||||
cmp dword [ecx+0xec],0
|
||||
jz .stale
|
||||
inc D(16)
|
||||
.ok:
|
||||
mov edx,[ecx+0xf4]
|
||||
mov ecx,[esp+8]
|
||||
lea edx,[edx+ecx*4]
|
||||
.push:
|
||||
push edx
|
||||
push eax
|
||||
call 0x54bbd0
|
||||
add esp,8
|
||||
ret
|
||||
.stale:
|
||||
inc D(20)
|
||||
mov edx,1
|
||||
call record
|
||||
call stale_info
|
||||
call check_heap
|
||||
%if FIX
|
||||
mov edx,DATA+48
|
||||
jmp .push
|
||||
%else
|
||||
test ecx,ecx
|
||||
jnz .ok
|
||||
mov edx,DATA+48
|
||||
jmp .push
|
||||
%endif
|
||||
|
||||
pop_var:
|
||||
push esi
|
||||
mov esi,[esp+8]
|
||||
push esi
|
||||
call 0x54bc00
|
||||
add esp,4
|
||||
mov ecx,[esi+0xc]
|
||||
mov edx,[esp+0xc]
|
||||
mov [DATA+60],edx
|
||||
push eax
|
||||
mov eax,esi
|
||||
mov edx,0x12
|
||||
call record_all
|
||||
pop eax
|
||||
test ecx,ecx
|
||||
jz .stale
|
||||
cmp dword [ecx+0xec],0
|
||||
jz .stale
|
||||
inc D(16)
|
||||
.ok:
|
||||
mov edx,[ecx+0xf4]
|
||||
mov ecx,[esp+0xc]
|
||||
lea edx,[edx+ecx*4]
|
||||
.store:
|
||||
pop esi
|
||||
mov [edx],eax
|
||||
ret
|
||||
.stale:
|
||||
inc D(24)
|
||||
push eax
|
||||
mov eax,esi
|
||||
mov edx,2
|
||||
call record
|
||||
call stale_info
|
||||
call check_heap
|
||||
pop eax
|
||||
%if FIX
|
||||
mov edx,DATA+48
|
||||
jmp .store
|
||||
%else
|
||||
test ecx,ecx
|
||||
jnz .ok
|
||||
mov edx,DATA+48
|
||||
jmp .store
|
||||
%endif
|
||||
|
||||
; record: eax strat, ecx parent, edx kind, [DATA+60] idx. Preserves eax, ecx.
|
||||
record:
|
||||
push esi
|
||||
push edi
|
||||
push ebx
|
||||
mov esi,[DATA+40]
|
||||
and esi,31
|
||||
shl esi,5
|
||||
lea edi,[DATA+64+esi]
|
||||
jmp rec_common
|
||||
record_all:
|
||||
push esi
|
||||
push edi
|
||||
push ebx
|
||||
mov esi,[DATA+44]
|
||||
and esi,63
|
||||
shl esi,5
|
||||
lea edi,[DATA+1408+esi]
|
||||
inc D(44)
|
||||
dec D(40) ; compensated below
|
||||
rec_common:
|
||||
inc D(40)
|
||||
mov [edi],eax
|
||||
mov [edi+4],ecx
|
||||
mov [edi+8],edx
|
||||
mov ebx,[DATA+60]
|
||||
mov [edi+12],ebx
|
||||
mov ebx,[eax+0x18]
|
||||
mov [edi+16],ebx
|
||||
mov dword [edi+20],0
|
||||
mov dword [edi+24],0
|
||||
mov dword [edi+28],0
|
||||
test ecx,ecx
|
||||
jz .np
|
||||
mov ebx,[ecx+0x18]
|
||||
mov [edi+20],ebx
|
||||
mov ebx,[ecx+0xf4]
|
||||
mov [edi+24],ebx
|
||||
mov ebx,[ecx+0xec]
|
||||
mov [edi+28],ebx
|
||||
.np:
|
||||
pop ebx
|
||||
pop edi
|
||||
pop esi
|
||||
ret
|
||||
|
||||
free_hook:
|
||||
pushad
|
||||
inc D(28)
|
||||
mov eax,[esp+36]
|
||||
mov [DATA+52],eax
|
||||
mov esi,[DATA+28]
|
||||
and esi,63
|
||||
shl esi,4
|
||||
mov [DATA+3456+esi],eax
|
||||
mov ebx,[esp+32] ; caller
|
||||
mov [DATA+3456+esi+4],ebx
|
||||
mov ebx,[eax-4] ; size|used
|
||||
mov [DATA+3456+esi+8],ebx
|
||||
mov ebx,[eax-12] ; next
|
||||
mov [DATA+3456+esi+12],ebx
|
||||
call check_heap
|
||||
popad
|
||||
mov eax,[esp+4]
|
||||
push esi
|
||||
jmp 0x41ada5
|
||||
|
||||
alloc_hook:
|
||||
pushad
|
||||
inc D(36)
|
||||
mov eax,[esp+36]
|
||||
mov [DATA+56],eax
|
||||
call check_heap
|
||||
popad
|
||||
mov ecx,[0x58499c]
|
||||
jmp 0x41ae26
|
||||
|
||||
; walks the local heap; on the first inconsistency records it (code in anomaly+0)
|
||||
check_heap:
|
||||
pushad
|
||||
mov esi,[0x58499c]
|
||||
test esi,esi
|
||||
jz .done
|
||||
xor edi,edi
|
||||
mov ecx,70000
|
||||
.loop:
|
||||
mov edx,1
|
||||
cmp [esi+4],edi
|
||||
jne .bad
|
||||
mov edx,2
|
||||
movzx eax,word [esi+10]
|
||||
cmp eax,1
|
||||
ja .bad
|
||||
mov ebx,[esi]
|
||||
test ebx,ebx
|
||||
jz .done
|
||||
mov edx,3
|
||||
movzx eax,word [esi+8]
|
||||
lea eax,[esi+eax*4+12]
|
||||
cmp ebx,eax
|
||||
jne .bad
|
||||
mov edi,esi
|
||||
mov esi,ebx
|
||||
dec ecx
|
||||
jnz .loop
|
||||
.done:
|
||||
popad
|
||||
ret
|
||||
.bad:
|
||||
inc D(32)
|
||||
cmp dword [DATA+32],1
|
||||
jne .done
|
||||
mov [DATA+1088],edx
|
||||
mov [DATA+1092],esi
|
||||
mov [DATA+1096],edi
|
||||
mov eax,[esi]
|
||||
mov [DATA+1100],eax
|
||||
mov eax,[esi+4]
|
||||
mov [DATA+1104],eax
|
||||
mov eax,[esi+8]
|
||||
mov [DATA+1108],eax
|
||||
mov eax,[DATA+28]
|
||||
mov [DATA+1112],eax
|
||||
mov eax,[DATA+36]
|
||||
mov [DATA+1116],eax
|
||||
mov eax,[DATA+40]
|
||||
mov [DATA+1120],eax
|
||||
mov eax,[esp+32] ; return address of check_heap caller
|
||||
mov [DATA+1124],eax
|
||||
mov eax,[DATA+52]
|
||||
mov [DATA+1128],eax
|
||||
mov eax,[DATA+56]
|
||||
mov [DATA+1132],eax
|
||||
; dump 256 bytes from edi (previous header) if set, else esi-128
|
||||
test edi,edi
|
||||
jnz .src
|
||||
lea edi,[esi-128]
|
||||
.src:
|
||||
mov esi,edi
|
||||
lea edi,[DATA+1152]
|
||||
mov ecx,64
|
||||
rep movsd
|
||||
jmp .done
|
||||
|
||||
; stale_info: ecx parent, [DATA+60] idx -> DATA+4480 + (n&31)*16: target, block hdr, size|used, value before
|
||||
stale_info:
|
||||
pushad
|
||||
test ecx,ecx
|
||||
jz .out
|
||||
mov edi,[ecx+0xf4]
|
||||
mov eax,[DATA+60]
|
||||
lea edi,[edi+eax*4]
|
||||
mov ebx,[DATA+40]
|
||||
dec ebx
|
||||
and ebx,31
|
||||
shl ebx,4
|
||||
lea ebx,[DATA+4480+ebx]
|
||||
mov [ebx],edi
|
||||
mov eax,[edi]
|
||||
mov [ebx+12],eax
|
||||
mov dword [ebx+4],0
|
||||
mov dword [ebx+8],0
|
||||
mov esi,[0x58499c]
|
||||
mov ecx,70000
|
||||
.l:
|
||||
test esi,esi
|
||||
jz .out
|
||||
mov edx,[esi]
|
||||
test edx,edx
|
||||
jnz .h
|
||||
movzx eax,word [esi+8]
|
||||
lea edx,[esi+eax*4+12]
|
||||
.h:
|
||||
cmp edi,esi
|
||||
jb .next
|
||||
cmp edi,edx
|
||||
jae .next
|
||||
mov [ebx+4],esi
|
||||
mov eax,[esi+8]
|
||||
mov [ebx+8],eax
|
||||
jmp .out
|
||||
.next:
|
||||
mov esi,[esi]
|
||||
dec ecx
|
||||
jnz .l
|
||||
.out:
|
||||
popad
|
||||
ret
|
||||
Reference in new issue
Block a user