+ Add tail_size varaible to be able to adjust size of tail memory area.

* Correct computation of CRC for if add_tail is true:
    tail is before extra_info, not after.
    Use tail_size variable to cacluate CRC use the whole tail memory area.
  + New function released_modified. Checks if released memory
    was modified after it release (used if keep_released is true).
  * TraceGetMem,TraceFreeMem TraceReallocMem: adapt to new tail_size variable.
  * TraceInit: Store previous memory manager in local variable,
    to be able to restore it in TracExit call.
  * LoadEnvironment: Add parsing of tail_size=XXX, where XXX is a decimal value,
    rounded up to next multiple of sizeof(ptruint).

git-svn-id: trunk@34385 -
This commit is contained in:
pierre 2016-08-28 21:42:07 +00:00
parent 1612138071
commit b6b27f2fb7

View File

@ -82,6 +82,8 @@ const
{ add a small footprint at the end of memory blocks, this
can check for memory overwrites at the end of a block }
add_tail : boolean = true;
tail_size : longint = sizeof(ptruint);
{ put crc in sig
this allows to test for writing into that part }
usecrc : boolean = true;
@ -233,8 +235,8 @@ begin
if add_tail then
begin
{ Check also 4 bytes just after allocation !! }
pl:=pointer(p)+p^.extra_info_size+sizeof(theap_mem_info)+p^.size;
crc:=UpdateCrc32(crc,pl^,sizeof(ptruint));
pl:=pointer(p)+sizeof(theap_mem_info)+p^.size;
crc:=UpdateCrc32(crc,pl^,tail_size);
end;
calculate_sig:=crc;
end;
@ -258,7 +260,7 @@ begin
begin
{ Check also 4 bytes just after allocation !! }
pl:=pointer(p)+p^.extra_info_size+sizeof(theap_mem_info)+p^.size;
crc:=UpdateCrc32(crc,pl^,sizeof(ptruint));
crc:=UpdateCrc32(crc,pl^,tail_size);
end;
calculate_release_sig:=crc;
end;
@ -364,6 +366,40 @@ begin
dump_stack(ptext,1);
end;
function released_modified(p : pheap_mem_info;var ptext : text) : boolean;
var pl : pdword;
pb : pbyte;
i : longint;
begin
released_modified:=false;
{ Check tail_size bytes just after allocation !! }
pl:=pointer(p)+sizeof(theap_mem_info)+p^.size;
pb:=pointer(p)+sizeof(theap_mem_info);
for i:=0 to p^.size-1 do
if pb[i]<>$F0 then
begin
Writeln(ptext,'offset',i,':$',hexstr(i,2*sizeof(pointer)),'"',hexstr(pb[i],2),'"');
released_modified:=true;
end;
for i:=1 to (tail_size div sizeof(dword)) do
begin
if unaligned(pl^) <> AllocateSig then
begin
released_modified:=true;
writeln(ptext,'Tail modified after release at pos ',i*sizeof(ptruint));
printhex(pointer(p)+p^.extra_info_size+sizeof(theap_mem_info)+p^.size,tail_size,ptext);
break;
end;
inc(pointer(pl),sizeof(dword));
end;
if released_modified then
begin
dump_already_free(p,ptext);
if @stderr<>@ptext then
dump_already_free(p,stderr);
end;
end;
{$ifdef EXTRA}
procedure dump_change_after(p : pheap_mem_info;var ptext : text);
var pp : pchar;
@ -457,7 +493,7 @@ end;
Function TraceGetMem(size:ptruint):pointer;
var
allocsize : ptruint;
i, allocsize : ptruint;
pl : pdword;
p : pointer;
pp : pheap_mem_info;
@ -474,7 +510,7 @@ begin
allocsize:=size+sizeof(theap_mem_info)+extra_info_size;
{$endif cpuarm}
if add_tail then
inc(allocsize,sizeof(ptruint));
inc(allocsize,tail_size);
{ if ReturnNilIfGrowHeapFails is true
SysGetMem can return nil }
p:=SysGetMem(allocsize);
@ -515,8 +551,12 @@ begin
pp^.extra_info:=nil;
if add_tail then
begin
pl:=pointer(pp)+allocsize-pp^.extra_info_size-sizeof(ptruint);
unaligned(pl^):=longword(AllocateSig);
pl:=pointer(pp)+allocsize-pp^.extra_info_size-tail_size;
for i:=1 to tail_size div sizeof(dword) do
begin
unaligned(pl^):=dword(AllocateSig);
inc(pointer(pl),sizeof(dword));
end;
end;
{ clear the memory }
fillchar(p^,size,#255);
@ -658,7 +698,7 @@ begin
extra_size:=pp^.extra_info_size;
ppsize:= size+sizeof(theap_mem_info)+pp^.extra_info_size;
if add_tail then
inc(ppsize,sizeof(ptruint));
inc(ppsize,tail_size);
{ do various checking }
release_mem := CheckFreeMemSize(loc_info, pp, size, ppsize);
if release_todo_lock then
@ -670,7 +710,7 @@ begin
{ return the correct size }
dec(i,sizeof(theap_mem_info)+extra_size);
if add_tail then
dec(i,sizeof(ptruint));
dec(i,tail_size);
InternalFreeMemSize:=i;
end else
InternalFreeMemSize:=size;
@ -737,7 +777,7 @@ begin
l:=SysMemSize(pp);
dec(l,sizeof(theap_mem_info)+pp^.extra_info_size);
if add_tail then
dec(l,sizeof(ptruint));
dec(l,tail_size);
{ this can never happend normaly }
if pp^.size>l then
begin
@ -761,7 +801,7 @@ end;
function TraceReAllocMem(var p:pointer;size:ptruint):Pointer;
var
newP: pointer;
allocsize,
i, allocsize,
movesize : ptruint;
pl : pdword;
pp : pheap_mem_info;
@ -823,7 +863,7 @@ begin
allocsize:=size+sizeof(theap_mem_info)+pp^.extra_info_size;
{$endif cpuarm}
if add_tail then
inc(allocsize,sizeof(ptruint));
inc(allocsize,tail_size);
{ Try to resize the block, if not possible we need to do a
getmem, move data, freemem }
if not SysTryResizeMem(pp,allocsize) then
@ -867,9 +907,13 @@ begin
pp^.extra_info:=nil;
if add_tail then
begin
pl:=pointer(pp)+allocsize-pp^.extra_info_size-sizeof(ptruint);
unaligned(pl^):=longword(AllocateSig);
end;
pl:=pointer(pp)+allocsize-pp^.extra_info_size-tail_size;
for i:=1 to tail_size div sizeof(dword) do
begin
unaligned(pl^):=dword(AllocateSig);
inc(pointer(pl),sizeof(dword));
end;
end;
{ adjust like a freemem and then a getmem, so you get correct
results in the summary display }
inc(loc_info^.freemem_size,oldsize);
@ -1175,6 +1219,8 @@ begin
else if pp^.sig<>longword(ReleaseSig) then
begin
dump_error(pp,ptext^);
if @stderr<>ptext then
dump_error(pp,stderr);
{$ifdef EXTRA}
dump_error(pp,error_file);
{$endif EXTRA}
@ -1187,6 +1233,12 @@ begin
dump_change_after(pp,error_file);
loc_info^.error_in_heap:=true;
end
{$else not EXTRA}
else
begin
if released_modified(pp,ptext^) then
exitcode:=203;
end;
{$endif EXTRA}
;
pp:=pp^.previous;
@ -1364,6 +1416,9 @@ const
GetFPCHeapStatus : @TraceGetFPCHeapStatus;
);
var
PrevMemoryManager : TMemoryManager;
procedure TraceInit;
begin
textoutput := @stderr;
@ -1372,6 +1427,7 @@ begin
main_orig_todolist := @heap_info.heap_free_todo;
main_relo_todolist := nil;
TraceInitThread;
GetMemoryManager(PrevMemoryManager);
SetMemoryManager(TraceManager);
useownfile:=false;
if outputstr <> '' then
@ -1421,6 +1477,8 @@ begin
end;
exit;
end;
{ Disable heaptrc memory manager to avoid problems }
GetMemoryManager(PrevMemoryManager);
move_heap_info(@orphaned_info, @heap_info);
dumpheap;
if heap_info.error_in_heap and (exitcode=0) then
@ -1559,7 +1617,8 @@ end;
procedure LoadEnvironment;
var
i,j : ptruint;
s : string;
s,s2 : string;
err : word;
begin
s:=Getenv('HEAPTRC');
if pos('keepreleased',s)>0 then
@ -1572,6 +1631,22 @@ begin
HaltOnNotReleased :=true;
if pos('skipifnoleaks',s)>0 then
GlobalSkipIfNoLeaks :=true;
if pos('tail_size=',s)>0 then
begin
i:=pos('tail_size=',s)+length('tail_size=');
s2:='';
while (i<=length(s)) and (s[i] in ['0'..'9']) do
begin
s2:=s2+s[i];
inc(i);
end;
val(s2,tail_size,err);
if err=0 then
tail_size:=((tail_size + sizeof(ptruint)-1) div sizeof(ptruint)) * sizeof(ptruint)
else
tail_size:=sizeof(ptruint);
add_tail:=(tail_size > 0);
end;
i:=pos('log=',s);
if i>0 then
begin