Skip to content

Commit a90bb53

Browse files
committed
Prevent crashing due to VBA's insane behavior WRT 64-bit lpvarValue. Yaaay?
1 parent 5486415 commit a90bb53

File tree

1 file changed

+18
-1
lines changed

1 file changed

+18
-1
lines changed

Rubberduck.VBEEditor/ComManagement/TypeLibs/TypeInfoConstantsCollection.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,14 +47,31 @@ public TypeInfoConstantsCollection(ITypeInfo parent, TYPEATTR attributes) :
4747

4848
// VBA constants are "static".... go figure. We can still infer it is a
4949
// constant rather than a field by checking the lpvarValue
50-
if (varDesc.varkind == VARKIND.VAR_STATIC && varDesc.desc.lpvarValue != IntPtr.Zero)
50+
if (varDesc.varkind == VARKIND.VAR_STATIC && IsValidPointer(varDesc.desc.lpvarValue))
5151
{
5252
_mapper.Add(_mapper.Count, i);
5353
}
5454
parent.ReleaseVarDesc(ppVarDesc);
5555
}
5656
}
5757

58+
/// <remarks>
59+
/// On 64-bit platform, VBA seems to like putting random values in the high 32-bit part of the lpvarValue. Sometimes it does give out
60+
/// null pointer but when ti does has no apparent reason or rhyme. Thus, to help avoid erroneous resolution of lpvarValue for vars that
61+
/// shouldn't be resolved, we will need to mask the high word and assume that any valid constants will have a address that is also in the low
62+
/// 32-bit part of the lpvarValue. That does not seem to exist on 32-bit VBA. Whee!
63+
/// Ref: https://github.com/rubberduck-vba/Rubberduck/issues/5241
64+
/// </remarks>
65+
private bool IsValidPointer(IntPtr ptr)
66+
{
67+
if(IntPtr.Size == 8)
68+
{
69+
return ((ulong)ptr & 0x00000000ffffffff) != 0;
70+
}
71+
72+
return ptr != IntPtr.Zero;
73+
}
74+
5875
public override int Count => _mapper.Count;
5976

6077
public override ITypeInfoVariable GetItemByIndex(int index) =>

0 commit comments

Comments
 (0)