0,0 → 1,448 |
format PE console 4.0 |
entry start |
|
include 'win32a.inc' |
include '../../struct.inc' |
include '../../proc32.inc' |
include 'fpo.inc' |
|
FS_ERRNO equ dword [errno] |
ENOMEM = 12 |
include 'malloc.inc' |
|
start: |
cinvoke fopen, logfile_name, logfile_mode |
mov [logfile], eax |
mov edx, 1 ;shl 25 |
malloc_init |
call run_test |
set_default_heap |
stdcall destroy_mspace, ebp |
cinvoke fclose, [logfile] |
ret |
|
FS_SYSCALL_PTR: |
cmp eax, 68 |
jnz unknown_syscall |
cmp ebx, 12 |
jz syscall_malloc |
cmp ebx, 13 |
jz syscall_free |
cmp ebx, 20 |
jz syscall_realloc |
cmp ebx, 26 |
jz syscall_trim |
|
unknown_syscall: |
int3 |
jmp $ |
|
syscall_malloc: |
push ecx edx |
invoke VirtualAlloc, 0, ecx, MEM_COMMIT, PAGE_READWRITE |
pop edx ecx |
ret |
syscall_free: |
push ecx edx |
invoke VirtualFree, ecx, 0, MEM_RELEASE |
test eax, eax |
jz @f |
pop edx ecx |
ret |
@@: |
int3 |
jmp $ |
syscall_realloc: |
push esi edi |
push ecx edx |
mov esi, edx |
call syscall_malloc |
mov edi, eax |
sub esp, 1Ch |
mov edx, esp |
invoke VirtualQuery, esi, edx, 1Ch |
mov ecx, [esp+0Ch] |
add esp, 1Ch |
cmp ecx, [esp+4] |
jb @f |
mov ecx, [esp+4] |
@@: |
shr ecx, 2 |
push esi edi |
rep movsd |
pop edi ecx |
call syscall_free |
mov eax, edi |
pop edx ecx |
pop edi esi |
ret |
syscall_trim: |
push eax ecx edi |
lea edi, [ecx+edx] |
mov ecx, esi |
shr ecx, 2 |
xor eax, eax |
rep stosd |
pop edi ecx eax |
ret |
|
macro next_random |
{ |
imul edi, 1103515245 |
add edi, 12345 |
} |
|
macro call_and_check_regs what |
{ |
push ebx edi |
what |
cmp edi, [esp] |
jnz edi_destroyed |
cmp ebx, [esp+4] |
jnz ebx_destroyed |
add esp, 8 |
} |
|
get_malloc_size: |
and eax, 1023 |
jnz @f |
next_random |
mov eax, edi |
shr eax, 16 |
shl eax, 8 |
@@: |
ret |
|
get_and_validate_memory: |
xor edx, edx |
div esi |
mov eax, [esp+edx*8+4] |
mov ecx, [esp+edx*8+8] |
push edi eax |
mov edi, eax |
mov al, [edi] |
repz scasb |
jnz memory_destroyed |
pop ecx edi |
ret |
|
run_test: |
; 65536 times run random operation. |
; Randomly select malloc(random size from 1 to 1023 or from 256 to 16M), |
; free(random of previously allocated areas), |
; realloc(random of previously allocated areas, random size from 1 to 1023 or from 256 to 16M), |
; realloc_in_place(<same as realloc>), |
; memalign(random size from 1 to 1023 or from 256 to 16M, random power of 2 from 8 to 1024) |
mov edi, 0x12345678 |
xor esi, esi ; 0 areas allocated |
mov ebx, 65536 |
.loop: |
; call validate_release_chain |
next_random |
mov eax, edi |
shr eax, 16 |
mov ecx, eax |
shr eax, 3 |
and ecx, 7 |
jz .memalign |
dec ecx |
jz .realloc_in_place |
dec ecx |
jz .realloc |
test ebx, 64 |
jz .prefer_free |
.prefer_malloc: |
dec ecx |
jz .free |
jmp .malloc |
.prefer_free: |
dec ecx |
jnz .free |
.malloc: |
call get_malloc_size |
jz .loop |
push eax |
call_and_check_regs <stdcall malloc,eax> |
pop ecx |
pushad |
cinvoke fprintf, [logfile], malloc_str, ecx, eax |
popad |
test eax, eax |
jz generic_malloc_failure |
inc esi |
push ecx eax |
push edi |
mov edi, eax |
mov eax, esi |
rep stosb |
pop edi |
jmp .common |
.free: |
test esi, esi |
jz .loop |
call get_and_validate_memory |
push edx |
pushad |
cinvoke fprintf, [logfile], free_str, ecx |
popad |
call_and_check_regs <stdcall free,ecx> |
; call validate_release_chain |
pop edx |
dec esi |
pop eax ecx |
push edi |
lea edi, [esp+4] |
@@: |
dec edx |
js @f |
xchg eax, [edi] |
xchg ecx, [edi+4] |
add edi, 8 |
jmp @b |
@@: |
pop edi |
jmp .common |
.realloc: |
test esi, esi |
jz .loop |
call get_and_validate_memory |
push eax |
next_random |
mov eax, edi |
shr eax, 16 |
call get_malloc_size |
jnz @f |
pop eax |
jmp .loop |
@@: |
push eax edx |
pushad |
cinvoke fprintf, [logfile], realloc_str1, ecx, eax |
popad |
call_and_check_regs <stdcall realloc,ecx,eax> |
pop edx ecx |
pushad |
cinvoke fprintf, [logfile], realloc_str2, eax |
popad |
test eax, eax |
jz generic_malloc_failure |
push ebx edi ecx |
mov ebx, [esp+edx*8+20] |
mov [esp+edx*8+16], eax |
mov [esp+edx*8+20], ecx |
cmp ebx, ecx |
jae @f |
mov ecx, ebx |
@@: |
mov edi, eax |
mov eax, [esp+12] |
repz scasb |
jnz memory_destroyed |
pop ecx |
sub ecx, ebx |
jbe @f |
rep stosb |
@@: |
pop edi ebx eax |
jmp .common |
.realloc_in_place: |
test esi, esi |
jz .loop |
call get_and_validate_memory |
push eax |
next_random |
mov eax, edi |
shr eax, 16 |
call get_malloc_size |
jnz @f |
pop eax |
jmp .loop |
@@: |
push eax edx |
pushad |
cinvoke fprintf, [logfile], realloc_in_place_str1, ecx, eax |
popad |
call_and_check_regs <stdcall realloc_in_place,ecx,eax> |
pushad |
cinvoke fprintf, [logfile], realloc_in_place_str2, eax |
popad |
pop edx ecx |
test eax, eax |
jnz @f |
pop eax |
jmp .common |
@@: |
cmp [esp+edx*8+4], eax |
jnz generic_malloc_failure |
push ebx edi ecx |
mov ebx, [esp+edx*8+20] |
mov [esp+edx*8+20], ecx |
cmp ebx, ecx |
jae @f |
mov ecx, ebx |
@@: |
mov edi, eax |
mov eax, [esp+12] |
repz scasb |
jnz memory_destroyed |
pop ecx |
sub ecx, ebx |
jbe @f |
rep stosb |
@@: |
pop edi ebx eax |
jmp .common |
.memalign: |
call get_malloc_size |
jz .loop |
next_random |
mov ecx, edi |
shr ecx, 29 |
mov edx, 8 |
shl edx, cl |
push eax edx |
pushad |
cinvoke fprintf, [logfile], memalign_str1, edx, eax |
popad |
call_and_check_regs <stdcall memalign, edx, eax> |
pushad |
cinvoke fprintf, [logfile], memalign_str2, eax |
popad |
dec dword [esp] |
test eax, [esp] |
jnz memalign_invalid |
add esp, 4 |
pop ecx |
test eax, eax |
jz generic_malloc_failure |
inc esi |
push ecx eax |
push edi |
mov edi, eax |
mov eax, esi |
rep stosb |
pop edi |
.common: |
cinvoke fflush, [logfile] |
dec ebx |
jnz .loop |
@@: |
dec esi |
js @f |
pop eax ecx |
stdcall free, eax |
jmp @b |
@@: |
ret |
|
generic_malloc_failure: |
mov eax, 1 |
int3 |
jmp $ |
|
memory_destroyed: |
mov eax, 2 |
int3 |
jmp $ |
|
edi_destroyed: |
mov eax, 3 |
int3 |
jmp $ |
|
ebx_destroyed: |
mov eax, 4 |
int3 |
jmp $ |
|
memalign_invalid: |
mov eax, 5 |
int3 |
jmp $ |
|
validate_release_chain: |
push ebx ebp |
set_default_heap |
lea ecx, [ebp+malloc_state.release_list-tchunk_release_fd] |
mov eax, ecx |
mov edx, [ecx+tchunk_release_fd] |
@@: |
cmp [edx+tchunk_release_bk], eax |
jnz .fail |
cmp edx, ecx |
jz @f |
mov eax, edx |
mov edx, [edx+tchunk_release_fd] |
jmp @b |
@@: |
lea eax, [ebp-3] |
add eax, [ebp-4] |
cmp eax, [ebp+malloc_state.top] |
jz .ok |
.chunk_loop: |
mov ecx, [eax-4] |
test ecx, CINUSE_BIT |
jnz .next_chunk |
cmp ecx, 0x100 |
jb .next_chunk |
mov edx, ecx |
and edx, not FLAG_BITS |
lea edx, [eax+edx] |
cmp [edx+tchunk_release_fd], edx |
jnz @f |
cmp [edx+tchunk_release_bk], edx |
jnz .fail |
jmp .next_chunk |
@@: |
mov ebx, [ebp+malloc_state.release_list] |
@@: |
cmp edx, ebx |
jz .next_chunk |
mov ebx, [ebx+tchunk_release_fd] |
cmp ebx, [ebp+malloc_state.release_list] |
jnz @b |
jmp .fail |
.next_chunk: |
and ecx, not FLAG_BITS |
add eax, ecx |
cmp eax, [ebp+malloc_state.top] |
jb .chunk_loop |
ja .fail |
.ok: |
pop ebp ebx |
ret |
.fail: |
int3 |
jmp $ |
|
align 4 |
data import |
library kernel32,'kernel32.dll',msvcrt,'msvcrt.dll' |
import kernel32,\ |
VirtualAlloc, 'VirtualAlloc', \ |
VirtualFree, 'VirtualFree', \ |
VirtualQuery, 'VirtualQuery' |
import msvcrt,\ |
fopen,'fopen',\ |
fclose,'fclose',\ |
fprintf,'fprintf',\ |
fflush,'fflush' |
end data |
|
malloc_str db 'malloc(0x%X) = 0x%X',10,0 |
free_str db 'free(0x%X)',10,0 |
realloc_str1 db 'realloc(0x%X,0x%X)',0 |
realloc_str2 db ' = 0x%X',10,0 |
realloc_in_place_str1 db 'realloc_in_place(0x%X,0x%X)',0 |
realloc_in_place_str2 db ' = 0x%X',10,0 |
memalign_str1 db 'memalign(0x%X,0x%X)',0 |
memalign_str2 db ' = 0x%X',10,0 |
|
logfile_name db 'test.log',0 |
logfile_mode db 'w',0 |
|
align 4 |
logfile dd ? |
errno dd ? |
FS_PROCESS_DATA = process_data |
process_data rd 1024 |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |