[fpc-devel] DatabaseError/DatabaseErrorFmt with Component parameter, TParams.GetByName
Bram Kuijvenhoven
kuifwaremailinglists at xs4all.nl
Mon Sep 26 14:10:07 CEST 2005
Hi FPC,
I found that using a TParams.GetByName call using an invalid parameter name causes a crash when the TParams is not owned by a TDataset.
I'm not sure whether it is a requirement of TParams usage to have it owned by a TDataset object, but otherwise, below is an explanation of what is going wrong.
Now the details about the crash. Start by looking at
dsparams.inc, lin 146 to 151:
Function TParams.ParamByName(const Value: string): TParam;
begin
Result:=FindParam(Value);
If (Result=Nil) then
DatabaseErrorFmt(SParameterNotFound,[Value],Dataset);
end;
If no parameter with name Value is found, it calls DatabaseErrorFmt with its formal parameter Component getting the value that Dataset returns. Look at TParams.GetDataSet:
dsparams.inc, line 32 to 38:
Function TParams.GetDataSet: TDataSet;
begin
If (FOwner is TDataset) Then
Result:=TDataset(FOwner)
else
Result:=Nil;
end;
As you can see, Dataset will take value nil if the TParams instance has no Owner. Now look at DatabaseErrorFmt:
db.pp, line 1823 to 1827:
Procedure DatabaseErrorFmt (Const Fmt : String; Args : Array Of const;
Comp : TComponent);
begin
Raise EDatabaseError.CreateFmt(Format('%s : %s',[Comp.Name,Fmt]),Args);
end;
No check is done on Assigned(Comp), so the dereferencing Comp.Name will cause an Access Violation (instead of a nice 'Parameter blablabla not found' message).
Perhaps we should fix TParams.ParamByName to
Function TParams.ParamByName(const Value: string): TParam;
begin
Result:=FindParam(Value);
If (Result=Nil) then
begin
if DataSet<>nil then
DatabaseErrorFmt(SParameterNotFound,[Value],DataSet)
else
DatabaseErrorFmt(SParameterNotFound,[Value]);
end;
end;
or
Function TParams.ParamByName(const Value: string): TParam;
var
TmpDataset:TDataset;
begin
Result:=FindParam(Value);
If (Result=Nil) then
begin
TmpDataSet:=DataSet;
if TmpDataSet<>nil then
DatabaseErrorFmt(SParameterNotFound,[Value],TmpDataset)
else
DatabaseErrorFmt(SParameterNotFound,[Value]);
end;
end;
Regards,
Bram Kuijvenhoven
More information about the fpc-devel
mailing list