Skip to content

Commit 9d3a62c

Browse files
committed
improved implementation of IsValidObj to avoid AVs on Windows (mostly annoying during debugging)
1 parent 8c81fb8 commit 9d3a62c

File tree

1 file changed

+43
-11
lines changed

1 file changed

+43
-11
lines changed

Source/Base/Spring.Events.Base.pas

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -112,23 +112,55 @@ implementation
112112
uses
113113
TypInfo;
114114

115-
function IsClassPtr(p: Pointer): Boolean;
116-
begin
117-
try
118-
Result := PPointer(NativeInt(p) + vmtSelfPtr)^ = p;
119-
except
120-
Result := False;
115+
function IsValidObj(p: PPointer): Boolean;
116+
{$IFDEF MSWINDOWS}
117+
var
118+
memInfo: TMemoryBasicInformation;
119+
{$ENDIF}
120+
121+
function IsValidPtr(address: Pointer): Boolean;
122+
begin
123+
// Must be above 64k and 4 byte aligned
124+
if (UIntPtr(address) > $FFFF) and (UIntPtr(address) and 3 = 0) then
125+
begin
126+
{$IFDEF MSWINDOWS}
127+
// do we need to recheck the virtual memory?
128+
if (UIntPtr(memInfo.BaseAddress) > UIntPtr(address))
129+
or ((UIntPtr(memInfo.BaseAddress) + memInfo.RegionSize) < (UIntPtr(address) + SizeOf(Pointer))) then
130+
begin
131+
// retrieve the status for the pointer
132+
memInfo.RegionSize := 0;
133+
VirtualQuery(address, memInfo, SizeOf(memInfo));
134+
end;
135+
// check the readability of the memory address
136+
Result := (memInfo.RegionSize >= SizeOf(Pointer))
137+
and (memInfo.State = MEM_COMMIT)
138+
and (memInfo.Protect and (PAGE_READONLY or PAGE_READWRITE
139+
or PAGE_WRITECOPY or PAGE_EXECUTE or PAGE_EXECUTE_READ
140+
or PAGE_EXECUTE_READWRITE or PAGE_EXECUTE_WRITECOPY) <> 0)
141+
and (memInfo.Protect and PAGE_GUARD = 0);
142+
{$ELSE}
143+
Result := True;
144+
{$ENDIF}
145+
end
146+
else
147+
Result := False;
121148
end;
122-
end;
123149

124-
function IsValidObj(p: Pointer): Boolean;
125150
begin
126151
Result := False;
127152
if Assigned(p) then
128153
try
129-
if not IsClassPtr(p) then
130-
if PNativeInt(p)^ > $FFFF then
131-
Result := PPointer(p)^ = PPointer(PNativeInt(p)^ + vmtSelfPtr)^;
154+
{$IFDEF MSWINDOWS}
155+
memInfo.RegionSize := 0;
156+
{$ENDIF}
157+
if IsValidPtr(PByte(p) + vmtSelfPtr)
158+
// not a class pointer - they point to themselves in the vmtSelfPtr slot
159+
and (p <> PPointer(PByte(p) + vmtSelfPtr)^) then
160+
if IsValidPtr(p) and IsValidPtr(PByte(p^) + vmtSelfPtr)
161+
// looks to be an object, it points to a valid class pointer
162+
and (p^ = PPointer(PByte(p^) + vmtSelfPtr)^) then
163+
Result := True;
132164
except
133165
end; //FI:W501
134166
end;

0 commit comments

Comments
 (0)