Likely affecting the RC too / Found in 3.2.3 420f7af213

There is an issue in the code generator.
Under some circumstances inlined code will use the same physical memory in its stackframe for one of its own locals (params), as the containing code does use for one of its locals.

Actually, it overwrites the local var of the caller, that is the var the caller passed as arguments. So it behaves as if the param was a "var param" => but it is not...

This happens
- with peephole disabled. / also happens with its enabled.
- opt regvar can also be enabled or disabled


The following code is inlined

function TGenLazRoundList.GetItemPointerFast(Index: Integer): TPItemT;
var
  c: Cardinal;
  MPtr: TLazListClassesInternalMem.PMemRecord;
begin
  MPtr := FMem.FMem;
  assert(Cardinal(Index) <= MPtr^.Capacity, 'TGenLazRoundList.GetItemPointerFast: Index <= c');
  Index := MPtr^.FirstItem.Idx + Index;
  c := MPtr^.Capacity;
  if Cardinal(Index) >= c then
    Index := Index - c;
  Result := TPItemT(@MPtr^.Data + Index * FItemSize.ItemSize);
end;


The outer function (inlining the above) is also inlined, into its caller)

The caller does

    PSource := PByte(ItemPointerFast[Cnt]);

And when GetItemPointerFast does
  Index := MPtr^.FirstItem.Idx + Index;

then the memory in which the caller has its copy of "cnt" changes


----
More to follow.

I will be away most of next week.
I will try to get a snapshot for testing.


_______________________________________________
fpc-devel maillist  -  [email protected]
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply via email to