forked from KolibriOS/kolibrios
449 lines
10 KiB
NASM
449 lines
10 KiB
NASM
|
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
|