Incorrect handling of unnamed components in streaming
Summary
When reading a component from a stream by TStream.ReadComponent
the reader must make sure that the name of the read component is unique. An unnamed component is a special case since several components are allowed to have an empty Name
property. TReader.ReadRootComponent
, however, does not handle this correctly in some cases which can cause crashes in component streaming
System Information
- Operating system: Win-11
- Processor architecture: x86-64
- Compiler version: FPC 3.3.1 i386-win32-win32/win64
- Device: Computer
Steps to reproduce
Unfortunately this issue is hard to reproduce in FPC alone. I am attaching a Lazarus example in which a label with Hint is streamed; the project is taken from the Lazarus report freepascal.org/lazarus/lazarus#40138 (closed) which I closed to avoid confusion due to the introductory discussion.
To reproduce, run the project in Lazarus and follow the instructions.
Without the patch presented below the project will crash when the streamed label is inserted a second time.
Example Project
ComponentExistsIssue-Project.zip
Possible fixes
This patch adds a check against CompName=''
to TReader.ReadRootComponent
:
function TReader.ReadRootComponent(ARoot: TComponent): TComponent;
...
if not (csDesigning in Result.ComponentState) then
begin
Result.FComponentState :=
Result.FComponentState + [csLoading, csReading];
if CompName = '' then // <--- ADDED
Result.Name := '' // <--- ADDED
else
begin
{ We need an unique name }
i := 0;
{ Don't use Result.Name directly, as this would influence
FindGlobalComponent in successive loop runs }
ResultName := CompName;
Lock;
try
while Assigned(FindGlobalComponent(ResultName)) do
begin
Inc(i);
ResultName := CompName + '_' + IntToStr(i);
end;
Result.Name := ResultName;
finally
Unlock;
end;
end;
end;
end;