RTTI 访问 VCL 的私有方法,例如TCustomForm.SetWindowState
RTTI access to private methods of VCL, e.g. TCustomForm.SetWindowState
在 Delphi 10.1 Berlin 中关于关闭允许轻松访问 class 的私有成员(字段和方法)的 class helper 漏洞的辩论中,它是经常声称
- 扩展 RTTI 允许访问 class 的私有成员,该成员是在启用(扩展)RTTI 的情况下编译的,并且
- 所有 VCL/RTL/FMX class 都启用了此功能。
但是,如果我 运行 这个简单的单元(一个简单的表格,只有一个 TListBox,没有别的):
unit RttiAccessTest;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.Rtti, Vcl.StdCtrls;
type
TForm16 = class(TForm)
ListBox1: TListBox;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form16: TForm16;
implementation
{$R *.dfm}
function GetMethodString(const MethodName: string): string;
var
M: TRTTIMethod;
I: Integer;
begin
M := TRttiContext.Create.GetType(TCustomForm).GetMethod(MethodName);
if Assigned(M) then
Result := 'Method ' + MethodName + ': ''' + M.ToString + ';'''
else
Result := 'Method ' + MethodName + ' cannot be found';
end;
procedure TForm16.FormCreate(Sender: TObject);
begin
Listbox1.Items.Add(GetMethodString('SetWindowState'));
Listbox1.Items.Add(GetMethodString('ShowModal'));
end;
end.
列表框中的文字为:
Method SetWindowState cannot be found
Method ShowModal: 'function ShowModal: Integer;'
这意味着我无法访问 TCustomForm
的私有方法 SetWindowState
。这是因为并非 RTL/VCL/FMX 中的所有 class 都扩展了 RTTI,还是我做错了什么?
如果我做错了什么或忘记了什么,那怎么办?换句话说,我需要做什么才能让 RTTI 访问 SetWindowState
或 TCustomForm
?我在西雅图或更早的时候也无法获得此访问权限。
备注
我知道如何访问该方法,利用 class 助手仍然可以获得私有方法的 地址 的事实,但这不是我的题。 我特别想问一下如何使用 RTTI。
显而易见的结论是,虽然此类型是使用扩展 RTTI 编译的,但私有方法不包括 RTTI。
为了使用 RTTI 访问 严格的 private/private 方法,请使用编译器指令 {$RTTI}.
Syntax
The general syntax of the $RTTI directive can be split into three parts. The basic form of $RTTI is as follows:
{$RTTI INHERIT|EXPLICIT [visibility-clause]}
visibility-clause:
METHODS|PROPERTIES|FIELDS (visibility-expression)
visibility-expression:
[vcPrivate],[vcProtected], [vcPublic], [vcPublished];
示例:
{$RTTI EXPLICIT METHODS([vcPublic, vcProtected, vcPrivate])}
设置 public、受保护和私有方法的可见性
注意:这个指令的作用域是本地而RTL/VCL/FMX
关闭了这些选项,这意味着访问protected/private 无法使用 RTTI 方法。
在 Delphi 10.1 Berlin 中关于关闭允许轻松访问 class 的私有成员(字段和方法)的 class helper 漏洞的辩论中,它是经常声称
- 扩展 RTTI 允许访问 class 的私有成员,该成员是在启用(扩展)RTTI 的情况下编译的,并且
- 所有 VCL/RTL/FMX class 都启用了此功能。
但是,如果我 运行 这个简单的单元(一个简单的表格,只有一个 TListBox,没有别的):
unit RttiAccessTest;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, System.Rtti, Vcl.StdCtrls;
type
TForm16 = class(TForm)
ListBox1: TListBox;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form16: TForm16;
implementation
{$R *.dfm}
function GetMethodString(const MethodName: string): string;
var
M: TRTTIMethod;
I: Integer;
begin
M := TRttiContext.Create.GetType(TCustomForm).GetMethod(MethodName);
if Assigned(M) then
Result := 'Method ' + MethodName + ': ''' + M.ToString + ';'''
else
Result := 'Method ' + MethodName + ' cannot be found';
end;
procedure TForm16.FormCreate(Sender: TObject);
begin
Listbox1.Items.Add(GetMethodString('SetWindowState'));
Listbox1.Items.Add(GetMethodString('ShowModal'));
end;
end.
列表框中的文字为:
Method SetWindowState cannot be found
Method ShowModal: 'function ShowModal: Integer;'
这意味着我无法访问 TCustomForm
的私有方法 SetWindowState
。这是因为并非 RTL/VCL/FMX 中的所有 class 都扩展了 RTTI,还是我做错了什么?
如果我做错了什么或忘记了什么,那怎么办?换句话说,我需要做什么才能让 RTTI 访问 SetWindowState
或 TCustomForm
?我在西雅图或更早的时候也无法获得此访问权限。
备注
我知道如何访问该方法,利用 class 助手仍然可以获得私有方法的 地址 的事实,但这不是我的题。 我特别想问一下如何使用 RTTI。
显而易见的结论是,虽然此类型是使用扩展 RTTI 编译的,但私有方法不包括 RTTI。
为了使用 RTTI 访问 严格的 private/private 方法,请使用编译器指令 {$RTTI}.
Syntax
The general syntax of the $RTTI directive can be split into three parts. The basic form of $RTTI is as follows:
{$RTTI INHERIT|EXPLICIT [visibility-clause]}
visibility-clause:
METHODS|PROPERTIES|FIELDS (visibility-expression)
visibility-expression:
[vcPrivate],[vcProtected], [vcPublic], [vcPublished];
示例:
{$RTTI EXPLICIT METHODS([vcPublic, vcProtected, vcPrivate])}
设置 public、受保护和私有方法的可见性
注意:这个指令的作用域是本地而RTL/VCL/FMX
关闭了这些选项,这意味着访问protected/private 无法使用 RTTI 方法。