Linux Ubuntu 3.13.0-48-lowlatency #80-Ubuntu SMP PREEMPT Thu Mar 12 11:33:22 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
FPC 2.6.4 [2015/02/21] for x86_64
No optimization, all checks and assertions on, debugging info for GDB Dwarf2 line numbers,
function UserString(Index:Integer):String;
var Str : string;
Section : String;
val : string;
I,N : Integer;
begin
Result:='';
if CurrentLanguage<>nil then
begin
Section:='User';
Val:=IntToStr(Index);
while length(val)<4 do val:='0'+val;
Val:='User'+Val;
...
And here, on last simple statement, it spoils completely different object in program!
Most interesting that address of that object is lower, so buffer overrun is not possible.
here when it enters into fpc_AnsiStr_Concat
and then into fpc_AnsiStr_SetLength
and then into reallocmem, MemoryManager.ReAllocMem
and then MemoryManager.GetMem returns new pointer.
This new pointer is larger than the pointer that will be spoiled by following Move (heap.inc, 1442).
p is $00007FFFEDD95C40
p2 is $00007FFFEDD80C80
minsize is 24
Move(p^,p2^,minsize);
causes another alive object with pointer $00007FFFEDCE7600 become pointer $00007F0030393230
Of course it destroys its data and causes access violation SIGSEGV later when program tries to access it.
I can work it around replacing
while length(val)<4 do val:='0'+val;
Val:='User'+Val;
with something different, like
Key := Copy('User0000',1,8-length(Val)) + Val;
But, why on the Earth Move() changes other objects?!