Sign in Join

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

Mailing lists / fpc-devel / 2009-08

Can someone confirm if this is a bug? (ancestor in TWRiter.WriteProperty)

5 messages · 3 people ·

Reply by email Subscribe to this list Your subscription

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

Martin

I am not very familiar with the code, so before reporting, I'd like to ask:

trunc\rtl\objpas\classes\writer.inc
procedure TWriter.WriteProperty(Instance: TPersistent; PropInfo: Pointer);

Imagine you a writing an Component, that does have an ancestor. The same component should have

   property Foo: TPersistentChild read FFoo write FFoo;
You should end up in the following code: (line 1091 in recent (a few
weeks) trunc )
// this is the last else, it's not a component, and it is not a collection
          else
            begin
            SavedAncestor := Ancestor;
            SavedPropPath := FPropPath;
            try
              FPropPath := FPropPath + PPropInfo(PropInfo)^.Name + '.';
              if HasAncestor then
                Ancestor := TPersistent(GetObjectProp(Ancestor,
PropInfo));
              WriteProperties(TPersistent(ObjValue));
            finally
              Ancestor := SavedAncestor;
              FPropPath := SavedPropPath;
            end;
            end;
--------------------------------------
              if HasAncestor then
                Ancestor := TPersistent(GetObjectProp(Ancestor,
PropInfo));

sets the ancestor to a persitent object

Now if TPersistentChild  itself has
  property Some: TComponent

then you end up again in TWriter.WriteProperty writing a tclass property

    tkClass:
      begin
        ObjValue := TObject(GetObjectProp(Instance, PropInfo));
        if HasAncestor then
        begin
          AncestorObj := TObject(GetObjectProp(Ancestor, PropInfo));
          if Assigned(AncestorObj) then
            if Assigned(ObjValue) and
              (TComponent(AncestorObj).Owner = FRootAncestor) and
              (TComponent(ObjValue).Owner = Root) and
              (UpperCase(TComponent(AncestorObj).Name) =
UpperCase(TComponent(ObjValue).Name)) then
              AncestorObj := ObjValue
//            else
//              AncestorObj := nil;
        end else
          AncestorObj := nil;

and this code assumes that the ancestor is a TComponent, but as seen before, the ancestor is not.

Shall I report a bug, or do I miss understand something? (is there a workaround?)

Martin

Reply by email

Martin
to Martin

I may have mis-judged t, but the problem is still the same:

when you get to write TPersistenChild you enter the following code

    tkClass:
      begin
        ObjValue := TObject(GetObjectProp(Instance, PropInfo));
        if HasAncestor then
        begin
          AncestorObj := TObject(GetObjectProp(Ancestor, PropInfo));
          if Assigned(AncestorObj) then
            if Assigned(ObjValue) and
              (TComponent(AncestorObj).Owner = FRootAncestor) and
              (TComponent(ObjValue).Owner = Root) and
              (UpperCase(TComponent(AncestorObj).Name) =
UpperCase(TComponent(ObjValue).Name)) then
              AncestorObj := ObjValue
//            else
//              AncestorObj := nil;
        end else
          AncestorObj := nil;
--------------

TObject(GetObjectProp(Ancestor, PropInfo)); returns the TpersistentChil as well as ObjValue being TPersistent

both get casted to TComponent with no check?

Martin wrote 71 lines
I am not very familiar with the code, so before reporting, I'd like to ask: trunc\rtl\objpas\classes\writer.inc procedure TWriter.WriteProperty(Instance: TPersistent; PropInfo: Pointer); Imagine you a writing an Component, that does have an ancestor. The same component should have property Foo: TPersistentChild read FFoo write FFoo; You should end up in the following code: (line 1091 in recent (a few weeks) trunc ) // this is the last else, it's not a component, and it is not a collection else begin SavedAncestor := Ancestor; SavedPropPath := FPropPath; try FPropPath := FPropPath + PPropInfo(PropInfo)^.Name + '.'; if HasAncestor then Ancestor := TPersistent(GetObjectProp(Ancestor, PropInfo)); WriteProperties(TPersistent(ObjValue)); finally Ancestor := SavedAncestor; FPropPath := SavedPropPath; end; end; -------------------------------------- if HasAncestor then Ancestor := TPersistent(GetObjectProp(Ancestor, PropInfo)); sets the ancestor to a persitent object Now if TPersistentChild itself has property Some: TComponent then you end up again in TWriter.WriteProperty writing a tclass property tkClass: begin ObjValue := TObject(GetObjectProp(Instance, PropInfo)); if HasAncestor then begin AncestorObj := TObject(GetObjectProp(Ancestor, PropInfo)); if Assigned(AncestorObj) then if Assigned(ObjValue) and (TComponent(AncestorObj).Owner = FRootAncestor) and (TComponent(ObjValue).Owner = Root) and (UpperCase(TComponent(AncestorObj).Name) = UpperCase(TComponent(ObjValue).Name)) then AncestorObj := ObjValue // else // AncestorObj := nil; end else AncestorObj := nil; and this code assumes that the ancestor is a TComponent, but as seen before, the ancestor is not. Shall I report a bug, or do I miss understand something? (is there a workaround?) Martin _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

Michael Van Canneyt
to Martin
Martin wrote 28 lines
I may have mis-judged t, but the problem is still the same: when you get to write TPersistenChild you enter the following code tkClass: begin ObjValue := TObject(GetObjectProp(Instance, PropInfo)); if HasAncestor then begin AncestorObj := TObject(GetObjectProp(Ancestor, PropInfo)); if Assigned(AncestorObj) then if Assigned(ObjValue) and (TComponent(AncestorObj).Owner = FRootAncestor) and (TComponent(ObjValue).Owner = Root) and (UpperCase(TComponent(AncestorObj).Name) = UpperCase(TComponent(ObjValue).Name)) then AncestorObj := ObjValue // else // AncestorObj := nil; end else AncestorObj := nil; -------------- TObject(GetObjectProp(Ancestor, PropInfo)); returns the TpersistentChil as well as ObjValue being TPersistent both get casted to TComponent with no check?

Ancestors can only be a TComponent.

Michael.

Show quoted text 76 lines
Martin wrote: > I am not very familiar with the code, so before reporting, I'd like to ask: > > trunc\rtl\objpas\classes\writer.inc > procedure TWriter.WriteProperty(Instance: TPersistent; PropInfo: Pointer); > > Imagine you a writing an Component, that does have an ancestor. > The same component should have > property Foo: TPersistentChild read FFoo write FFoo; > > You should end up in the following code: (line 1091 in recent (a few weeks) > trunc ) > // this is the last else, it's not a component, and it is not a collection > else > begin > SavedAncestor := Ancestor; > SavedPropPath := FPropPath; > try > FPropPath := FPropPath + PPropInfo(PropInfo)^.Name + '.'; > if HasAncestor then > Ancestor := TPersistent(GetObjectProp(Ancestor, PropInfo)); > WriteProperties(TPersistent(ObjValue)); > finally > Ancestor := SavedAncestor; > FPropPath := SavedPropPath; > end; > end; > -------------------------------------- > if HasAncestor then > Ancestor := TPersistent(GetObjectProp(Ancestor, PropInfo)); > sets the ancestor to a persitent object > > Now if TPersistentChild itself has > property Some: TComponent > > then you end up again in TWriter.WriteProperty writing a tclass property > > tkClass: > begin > ObjValue := TObject(GetObjectProp(Instance, PropInfo)); > if HasAncestor then > begin > AncestorObj := TObject(GetObjectProp(Ancestor, PropInfo)); > if Assigned(AncestorObj) then > if Assigned(ObjValue) and > (TComponent(AncestorObj).Owner = FRootAncestor) and > (TComponent(ObjValue).Owner = Root) and > (UpperCase(TComponent(AncestorObj).Name) = > UpperCase(TComponent(ObjValue).Name)) then > AncestorObj := ObjValue > // else > // AncestorObj := nil; > end else > AncestorObj := nil; > > > and this code assumes that the ancestor is a TComponent, but as seen > before, the ancestor is not. > > > Shall I report a bug, or do I miss understand something? > (is there a workaround?) > > Martin > > _______________________________________________ > fpc-devel maillist - > http://lists.freepascal.org/mailman/listinfo/fpc-devel _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

Paul Ishenin
to Michael Van Canneyt
Michael Van Canneyt wrote 30 lines
> > when you get to write TPersistenChild you enter the following code > > tkClass: > begin > ObjValue := TObject(GetObjectProp(Instance, PropInfo)); > if HasAncestor then > begin > AncestorObj := TObject(GetObjectProp(Ancestor, PropInfo)); > if Assigned(AncestorObj) then > if Assigned(ObjValue) and > (TComponent(AncestorObj).Owner = FRootAncestor) and > (TComponent(ObjValue).Owner = Root) and > (UpperCase(TComponent(AncestorObj).Name) = > UpperCase(TComponent(ObjValue).Name)) then > AncestorObj := ObjValue > // else > // AncestorObj := nil; > end else > AncestorObj := nil; > -------------- > > TObject(GetObjectProp(Ancestor, PropInfo)); returns the TpersistentChil > as well as ObjValue being TPersistent > > > both get casted to TComponent with no check? I may have mis-judged t, but the problem is still the same: Ancestors can only be a TComponent.

Ancestor (in this report http://bugs.freepascal.org/view.php?id=14364) is TLabel, HasAncestor = True (since Ancestor is TLabel and Instance.ClassType = Ancestor.ClassType) and both ObjValue and AncestorObj are TAnchorSide (descendant of TPersistent and not TComponent). Therefore it accessing TAnchorSide property (TPersistent) as TComponent and we have a crash.

But maybe the problem is somewhere else. For example can Ancestor be TLabel or it is usually some form, frame or datamodule?

Best regards,
Paul Ishenin.

Reply by email

Martin
to Paul Ishenin
Paul Ishenin wrote 41 lines
Michael Van Canneyt wrote: >> >> when you get to write TPersistenChild you enter the following code >> >> tkClass: >> begin >> ObjValue := TObject(GetObjectProp(Instance, PropInfo)); >> if HasAncestor then >> begin >> AncestorObj := TObject(GetObjectProp(Ancestor, PropInfo)); >> if Assigned(AncestorObj) then >> if Assigned(ObjValue) and >> (TComponent(AncestorObj).Owner = FRootAncestor) and >> (TComponent(ObjValue).Owner = Root) and >> (UpperCase(TComponent(AncestorObj).Name) = >> UpperCase(TComponent(ObjValue).Name)) then >> AncestorObj := ObjValue >> // else >> // AncestorObj := nil; >> end else >> AncestorObj := nil; >> -------------- >> >> TObject(GetObjectProp(Ancestor, PropInfo)); returns the >> TpersistentChil >> as well as ObjValue being TPersistent >> >> >> both get casted to TComponent with no check? > I may have mis-judged t, but the problem is still the same: > > Ancestors can only be a TComponent. Ancestor (in this report http://bugs.freepascal.org/view.php?id=14364) is TLabel, HasAncestor = True (since Ancestor is TLabel and Instance.ClassType = Ancestor.ClassType) and both ObjValue and AncestorObj are TAnchorSide (descendant of TPersistent and not TComponent). Therefore it accessing TAnchorSide property (TPersistent) as TComponent and we have a crash. But maybe the problem is somewhere else. For example can Ancestor be TLabel or it is usually some form, frame or datamodule?

and on top of that, Ancestor can be a TPersitent:
because if the AnchorSide writes it's properties, the following code, sts ancestor to anchorside:

      begin
            SavedAncestor := Ancestor;
            SavedPropPath := FPropPath;
            try
              FPropPath := FPropPath + PPropInfo(PropInfo)^.Name + '.';
              if HasAncestor then
                Ancestor := TPersistent(GetObjectProp(Ancestor,
PropInfo));  // <<<<<
              WriteProperties(TPersistent(ObjValue));
            finally
              Ancestor := SavedAncestor;
              FPropPath := SavedPropPath;
            end;

Reply by email