Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2005-09

DatabaseError/DatabaseErrorFmt with Component parameter, TParams.GetByName

2 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Bram Kuijvenhoven

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. :

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 DataSetnil 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 TmpDataSetnil then
        DatabaseErrorFmt(SParameterNotFound,[Value],TmpDataset)
      else
        DatabaseErrorFmt(SParameterNotFound,[Value]);
      end;
  end;

Regards,

Bram Kuijvenhoven

Reply by email

Michael Van Canneyt
to Bram Kuijvenhoven
Bram Kuijvenhoven wrote 17 lines
or Function TParams.ParamByName(const Value: string): TParam; var TmpDataset:TDataset; begin Result:=FindParam(Value); If (Result=Nil) then begin TmpDataSet:=DataSet; if TmpDataSetnil then DatabaseErrorFmt(SParameterNotFound,[Value],TmpDataset) else DatabaseErrorFmt(SParameterNotFound,[Value]); end; end;

I'll implement this latter option.

Michael.

Reply by email