News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Help: How to implement safe memory

Started by Ar0n, August 10, 2014, 08:46:36 AM

Previous topic - Next topic

Ar0n

Hello MASM forum
I'm new here, well I want to know if you all can give me some ideas on how to implement a code, my scenario is this:
I have a program that does massive use of dynamic memory from heap by using HeapAlloc, HeapRealloc, etc. it allocates a lot of blocks of memory to store information and so, now I need to implement a code to write to the allocated memory safely because the project large and I find it difficult to detect memory leaks in the program, for example:

I use HeapAlloc to allocate a block of memory then copy information to it:

invoke GetProcessHeap
invoke HeapAlloc,eax,HEAP_ZERO_MEMORY,80 ;
mov PtrVar,eax
...
push 50
push Ptr2 ; some another pointer to memory with information
push PtrVar
call memcpy

First copy was ok, now I need to copy more information to it but for some reason I write more values ​​in the remaining space,
the reason may be wrong calculation (runtime), incorrect value when writing the code, etc.

push VarSize ; Wrong value,
push Ptr3 ; some another pointer to memory with information
push edi ; edi used as index: base pointer ( returned by HeapAlloc ) + bytes written above
call memcpy

also, problems like this:

invoke GetProcessHeap
invoke HeapAlloc,eax,HEAP_ZERO_MEMORY,Value ; Wrong value   
assume eax:TYPE_DEF ; some type definition
mov eax.dword_val1,Imm32
mov eax.dword_val2,Imm32
mov eax.dword_val3,Imm32

that value may be incorrect for the same reasons.
any ideas? thanks!







Zen

AR0N,
Good question. I was doing something similar in a program I was writing recently. The way I did it was to use lots of pointers (declared in my data section), using them each only once, and, comment the code extensively. And, then I called HeapAlloc repeatedly, as many times as were necessary for each individual memory write. When first developing an application, I don't use HeapRealloc, at all, because it gets too confusing. And, I call HeapSize all over the place to make sure that my HeapAlloc was big enough.
Once you get the code working to your satisfaction, then try to optimize.
This blog entry from Raymond Chen might help: Memory allocation functions can give you more memory than you ask for, and you are welcome to use the freebies too, but watch out for the free lunch
Zen

dedndave

allocating and reallocating small blocks like that seems like bad design

if it's practical to do so, allocate one reasonably large block at the beginning of the program
then, keep an array of pointers to manage it in smaller pieces

using HeapAlloc to get 80 bytes makes a mess out of the system heap
such small allocations can be made in the uninitialized data section
or, for temporary use, on the stack

Gunther

Hi Ar0n,

as Zen and Dave wrote: allocate an appropriate large memory block by starting your application and subdivide it in smaller pieces. That's the right strategy. And welcome to the forum.

Gunther
You have to know the facts before you can distort them.

K_F

'Sire, Sire!... the peasants are Revolting !!!'
'Yes, they are.. aren't they....'

TouEnMasm

The soluce is to have a routine who do the work,here is:

usage:
Choose the value for the mem  incrementation,defaut is 400h
more secure with  link /SAFESEH

.data
messages BLOCHEAP <,,,,1000h> ;incrément par 1000h
.code
;any size of data can be added to the bloc
;0 let the function find the lenght of a zero terminated string
invoke WriteToBlocHeap,addr messages,addr string,0
invoke WriteToBlocHeap,addr messages,addr string2,0





BLOCHEAP STRUCT
Hheap dd ? ;Handle heap,GetProcessHeap
Pheap dd ? ;Pointeur heap,HeapAlloc,Heapfree
TailleData dd ? ;size of data and offset of next element
TailleBloc dd ?  ;size of allocated mem
AllocBy dd ?  ;size to increase the size of mem by,optimize
BLOCHEAP ENDS
DefautAllocatedMem equ 400h

;used to make a single block of several data
;the data couldn't be retrieve by indice
;Arguments
;adresse of a BLOCHEAP structure,if BLOCHEAP.AllocBy == 0 ,incrément mem by 400h
;adresse of the data to write in heap memory
;Taille,size of data to write in heap memory.If zero,supposed to be a zero terminated data
;################################################################
WriteToBlocHeap PROC uses esi edi ebx pblocheap:DWORD,  pData:DWORD,  Taille:DWORD
Local   longueur:DWORD,sizemem
LOCAL   PointeurEcriture:DWORD
Local  retour:DWORD
mov esi,pblocheap
;------------ vérifier la validité des arguments ---------------
;-----pData NULL ,Taille== NULL libérer le tampon
.if pData == 0 && Taille == 0
.if dword ptr [esi][BLOCHEAP.Pheap] != 0
invoke HeapFree,dword ptr [esi][BLOCHEAP.Hheap],NULL,dword ptr [esi][BLOCHEAP.Pheap]
.if eax == NULL
;invoke RetrouveMessageErreur,addr erreurBlocHeapFree
mov retour,0
jmp FindeWriteToBlocHeap
.endif
xor eax,eax
mov dword ptr [esi][BLOCHEAP.Pheap],eax
mov dword ptr [esi][BLOCHEAP.TailleData],eax
mov dword ptr [esi][BLOCHEAP.TailleBloc],eax
mov retour,1
.else
mov retour,0
.endif
jmp FindeWriteToBlocHeap
.endif
;---- taille de la chaine a écrire,si NULL ,rechercher sa longueur
.if Taille == 0
invoke lstrlen,pData
mov longueur,eax
.if eax == 0
mov retour,0
jmp FindeWriteToBlocHeap ;rien à écrire
.endif
.else
Push Taille
Pop longueur
.endif
;---- handle heap ----------------------------------------------------
.if dword ptr [esi][BLOCHEAP.Hheap] == 0 ;pas de handle,le créer
invoke GetProcessHeap
mov   dword ptr [esi][BLOCHEAP.Hheap],eax
.if eax == NULL
;invoke RetrouveMessageErreur,addr erreurBlochandleheap
mov retour,0
jmp FindeWriteToBlocHeap
.endif
.endif
;vérifier l'incrément
.if dword ptr [esi].BLOCHEAP.AllocBy == 0
mov [esi].BLOCHEAP.AllocBy,DefautAllocatedMem
.endif
;---- pointeur heap first writing -------------------
.if dword ptr [esi][BLOCHEAP.Pheap] == 0
mov edx,longueur
inc edx ;pour le zero de fin de bloc data
mov ecx,[esi].BLOCHEAP.AllocBy
@@:
.if ecx < edx
add ecx,[esi].BLOCHEAP.AllocBy
jmp @B
.endif
mov sizemem,ecx
invoke HeapAlloc,dword ptr [esi][BLOCHEAP.Hheap],HEAP_ZERO_MEMORY,ecx
.if eax == 0
;invoke RetrouveMessageErreur,addr erreurBlocPointeheap
mov retour,0
jmp FindeWriteToBlocHeap
.endif
;sauvegarder le pointeur heap
mov dword ptr [esi][BLOCHEAP.Pheap],eax
;sauvegarder la taille de la mémoire allouée
Push sizemem
Pop [esi].BLOCHEAP.TailleBloc
;sauvegarder la taille de la data
mov eax,longueur
mov dword ptr [esi][BLOCHEAP.TailleData],eax
;écrire la data
mov ecx,longueur
mov edi,dword ptr [esi][BLOCHEAP.Pheap]
mov esi,pData
cld
rep movsb
mov retour,1
jmp FindeWriteToBlocHeap

.endif
;tout est valide et une premiere opération d'écriture à déja été faite
;la longueur à écrire est définie
mov edx,dword ptr [esi][BLOCHEAP.TailleData]
mov eax,longueur
add edx,eax
inc edx ;totale des données + le zero
mov ecx,dword ptr [esi].BLOCHEAP.TailleBloc
.if edx > ecx
@@:
add ecx,dword ptr [esi].BLOCHEAP.TailleBloc
.if edx > ecx
jmp @B
.endif
mov sizemem,ecx
invoke HeapReAlloc,dword ptr [esi][BLOCHEAP.Hheap],HEAP_ZERO_MEMORY,\
dword ptr [esi][BLOCHEAP.Pheap],sizemem
.if eax == 0
;invoke RetrouveMessageErreur,addr erreurBlocHeapReAlloc
mov retour,0
jmp FindeWriteToBlocHeap
.else
;l'éventuel nouveau pointeur
mov dword ptr [esi][BLOCHEAP.Pheap],eax

;sauvegarder la nouvelle taille de la mémoire allouée
Push sizemem
Pop [esi].BLOCHEAP.TailleBloc

.endif
.endif
;la taille mémoire est suffisante
;la nouvelle taille data
mov edx,dword ptr [esi][BLOCHEAP.TailleData]
mov PointeurEcriture,edx ;le décalage à l'écriture
mov eax,longueur
add edx,eax
;inc edx ;totale des données sans le zero
mov dword ptr [esi][BLOCHEAP.TailleData],edx
;recopier les données
mov edi,dword ptr [esi][BLOCHEAP.Pheap]
add edi,PointeurEcriture
mov ecx,longueur
mov esi,pData
cld
rep movsb
mov retour,1
FindeWriteToBlocHeap:
mov eax,retour
ret
WriteToBlocHeap endp
Fa is a musical note to play with CL

hutch--

The technique you use has a lot to do with the type and size of the data you wish to write to memory. If it is data that can be fitted into fixed length areas of memory, the task is simple, you allocate an array of pointers, then a block of memory and aim each pointer to each section of memory.

The task becomes a lot more complicated if you need variable length memory, you allocate an array of pointers them at each address you dynamically allocate the amount of memory you need for each item being written. Now what makes this complicated is when you have to de-allocate all of the separate blocks that were allocated for each pointer. You then need to write a procedure that scans the array and deallocated each block.

The second is a lot slower than the first and you only use techniques of this type if you really need variable length memory for each item.

With the first approach, what you need to do is keep track of the length of the data being written to fixed sizes so you do not overwrite the following block or blocks.

TouEnMasm

With the method I have posted,to create an array of data,there is just to add an array of:
Offset (relatives to the heap pointer,BLOCHEAP.Pheap)
         This pointer can change (the system do it),offset couldn't change
Size of datas

A couple of dword is needed for each variable.
you can create this array using the fonction

memarray BLOCHEAP <,,,,100h>  ;
Fa is a musical note to play with CL

Ar0n

Thanks guys I will post the result of this soon