Skip to content

Commit bb02552

Browse files
authored
Don't expose a memory reference for non-pointer evaluation results (#1601)
Gate the memoryReference on pointer and array types in OpenDebugAD7 A non-pointer scalar shown in a data tip or the Variables view carried a memoryReference, so VS Code rendered the "view binary data" icon and navigated to an address equal to the value (hovering a uint32_t of 1 opened a memory view at 0x1). The earlier approach gated AD7Property.GetMemoryContext in the engine, but that method is shared with Visual Studio, where the Memory and Disassembly windows resolve a typed address expression through it. Restricting it there breaks entering a scalar or address expression into those windows. Move the restriction to the DAP layer: in AD7Utils.GetMemoryReferenceFromIDebugProperty, emit a memoryReference only when the property type is a pointer or an array. GetMemoryContext is left unchanged, so the Visual Studio memory and disassembly navigation keep working, while VS Code no longer offers a memory view for scalars. VS Code has no free-form address entry, so gating the reference removes no entry point there.
1 parent a5d90d8 commit bb02552

1 file changed

Lines changed: 42 additions & 2 deletions

File tree

src/OpenDebugAD7/AD7Utils.cs

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Microsoft. All rights reserved.
1+
// Copyright (c) Microsoft. All rights reserved.
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

44
using System;
@@ -20,7 +20,23 @@ public static bool IsAnnotatedFrame(ref FRAMEINFO frameInfo)
2020

2121
public static string GetMemoryReferenceFromIDebugProperty(IDebugProperty2 property)
2222
{
23-
if (property != null && property.GetMemoryContext(out IDebugMemoryContext2 memoryContext) == HRConstants.S_OK)
23+
if (property == null)
24+
{
25+
return null;
26+
}
27+
28+
// Only a pointer or an array holds an address a memoryReference can point at.
29+
// For any other type the value is not an address, so a memoryReference would
30+
// make the client show a memory view that navigates to the value itself. The
31+
// engine's GetMemoryContext still resolves an address for any type, which the
32+
// Visual Studio Memory and Disassembly windows rely on; the restriction here
33+
// applies only to the reference reported over DAP.
34+
if (!IsPointerOrArray(property))
35+
{
36+
return null;
37+
}
38+
39+
if (property.GetMemoryContext(out IDebugMemoryContext2 memoryContext) == HRConstants.S_OK)
2440
{
2541
CONTEXT_INFO[] contextInfo = new CONTEXT_INFO[1];
2642
if (memoryContext.GetInfo(enum_CONTEXT_INFO_FIELDS.CIF_ADDRESS, contextInfo) == HRConstants.S_OK)
@@ -34,5 +50,29 @@ public static string GetMemoryReferenceFromIDebugProperty(IDebugProperty2 proper
3450

3551
return null;
3652
}
53+
54+
private static bool IsPointerOrArray(IDebugProperty2 property)
55+
{
56+
DEBUG_PROPERTY_INFO[] propertyInfo = new DEBUG_PROPERTY_INFO[1];
57+
if (property.GetPropertyInfo(enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_TYPE, Constants.EvaluationRadix, Constants.EvaluationTimeout, null, 0, propertyInfo) != HRConstants.S_OK)
58+
{
59+
return false;
60+
}
61+
62+
if (!propertyInfo[0].dwFields.HasFlag(enum_DEBUGPROP_INFO_FLAGS.DEBUGPROP_INFO_TYPE))
63+
{
64+
return false;
65+
}
66+
67+
string typeName = propertyInfo[0].bstrType;
68+
if (string.IsNullOrEmpty(typeName))
69+
{
70+
return false;
71+
}
72+
73+
typeName = typeName.TrimEnd();
74+
return typeName.EndsWith("*", StringComparison.Ordinal) // pointer, e.g. "int *"
75+
|| typeName.EndsWith("]", StringComparison.Ordinal); // array, e.g. "int [10]"
76+
}
3777
}
3878
}

0 commit comments

Comments
 (0)