Jump to content
dmitrybv

CaretPositionRTTIProp.GetValue(Memo1) raises AV

Recommended Posts

Hello

 

I can't figure out why the following code causes an AV error.


 

procedure TFormSimpleDraw2.Button2Click(Sender: TObject);
var
  Value: TValue;
  LType: TRttiType;
  RttiContext: TRttiContext;
  CaretPositionProp: TRttiProperty;
  CaretPosition: TCaretPosition;
begin
  RttiContext := TRttiContext.Create;
  LType := RttiContext.GetType(Memo1.ClassInfo);

  CaretPosition := Memo1.CaretPosition;

  CaretPositionProp := LType.GetProperty('CaretPosition');
  Value := CaretPositionProp.GetValue(Memo1); //AV is here
end;

 

Embarcadero® RAD Studio 12 Version 29.0.55362.2017 

 

1. Create FMX Form.

2. Put TButton and TMemo on the Form.

3. Write TButton.OnClick as written above

4.  Run and click Button

Share this post


Link to post

You are not checking if either TRttiContext.GetType() or TRttiType.GetProperty() are returning nil before accessing the objects they return.

procedure TFormSimpleDraw2.Button2Click(Sender: TObject);
var
  Value: TValue;
  LType: TRttiType;
  RttiContext: TRttiContext;
  CaretPositionProp: TRttiProperty;
  CaretPosition: TCaretPosition;
begin
  RttiContext := TRttiContext.Create;

  LType := RttiContext.GetType(Memo1.ClassInfo);
  if LType = nil then Exit; // <-- add this

  CaretPosition := Memo1.CaretPosition;

  CaretPositionProp := LType.GetProperty('CaretPosition');
  if CaretPositionProp = nil then Exit; // <-- add this
  
  Value := CaretPositionProp.GetValue(Memo1);
  ...
end;

Share this post


Link to post

CaretPositionProp is not nil, however when invoking the GetValyue in CaretPositionProp.GetValue self is an Inaccessible value:

 

FMX.Memo.TCustomMemo.GetCaretPosition
:00cfcac8 RawInvoke + $40
System.Rtti.RawInvoke(???,???)
:00cfcead Invoke + $249
System.Rtti.Invoke(nil,(),???,???,True,True)
:00cf5689 TRttiInstanceProperty.DoGetValue + $DD
System.Rtti.TRttiInstanceProperty.DoGetValue(???)
:00cf54ae TRttiProperty.GetValue + $26

 

Since it is pointing to an invalid address the Access Violation is when the code tries to execute Model.CaretPosition.

Edited by Lajos Juhász

Share this post


Link to post

If this issue is related to a bug in RTTI or TMemo, then a new bug report should be added to the Embarcadero Quality Portal.


If this issue is related to the fact that the CaretPosition property cannot be read via RTTI, then is there a way to check this.

Share this post


Link to post

Okay, the reason is because the CaretPosition getter is declared as cdecl (I have no clue why that is the case - I would assume some C++ compat because the result is a record) and the code for getting properties does not know about the calling conventions  of their setter and getter (because that is not part of their RTTI but only the code pointer to them) and thus always assumes standard calling convention.

Edited by Stefan Glienke
  • Confused 1

Share this post


Link to post
10 hours ago, Stefan Glienke said:

the code for getting properties does not know about the calling conventions  of their setter and getter (because that is not part of their RTTI but only the code pointer to them) and thus always assumes standard calling convention.

Actually, calling convention is part of the RTTI for invokable types, including class methods. But TRttiInstanceProperty.DoGetValue() (and DoSetValue()) are ignoring that fact and just assume Delphi's default Register convention when invoking the property getter/setter.  If I change the invocation to specify Cdecl instead of Register, then no crash occurs.

 

I have opened a bug ticket for this:

RSS-3574: AV in TRttiProperty if getter/setter does not use Register calling convention

Edited by Remy Lebeau

Share this post


Link to post

"Just curious — how did you specify the calling convention cdecl? After all, DoGetValue doesn't contain any parameters for specifying the calling convention."

Share this post


Link to post
42 minutes ago, dmitrybv said:

"Just curious — how did you specify the calling convention cdecl? After all, DoGetValue doesn't contain any parameters for specifying the calling convention."

I simply used the debugger at runtime to modify the CallingConvention parameter of the internal System.Rtti.Invoke() function that DoGetValue() calls for a getter method.  DoGetValue() is hard-coded to pass in a value of ccReg, I just changed that to ccCdecl instead, and then the AV went away.  That is at least a POC that the issue could be fixed if DoGetValue() were made to be more sensitive to the getter's actual RTTI. And likewise for DoSetValue(), too.

Edited by Remy Lebeau
  • Thanks 1

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×