From b58eba3fda4f36f73500ff6d5a55de75d33b86dd Mon Sep 17 00:00:00 2001 From: Ankit Jain Date: Mon, 14 Sep 2020 15:12:21 -0400 Subject: [PATCH] [wasm][debugger] Avoid infinite loop when we have a boxed `new object` (#42059) * [wasm][debugger] Avoid infinite loop when we have a boxed `new object` Eg. `object o = new object(); object o1 = o;` - Avoid infinitely looping for `o1` * [wasm][debugger] Handle valuetypes boxed in classes that are not .. type `object`. Prompted by @lambdageek's comment - https://github.com/dotnet/runtime/pull/42059#issuecomment-690310274 --- src/mono/mono/mini/mini-wasm-debugger.c | 10 +++++ src/mono/wasm/debugger/DebuggerTestSuite/Tests.cs | 51 +++++++++++++++++++++++ src/mono/wasm/debugger/tests/debugger-test.cs | 47 +++++++++++++++++++++ 3 files changed, 108 insertions(+) diff --git a/src/mono/mono/mini/mini-wasm-debugger.c b/src/mono/mono/mini/mini-wasm-debugger.c index b978d60..c4f8031 100644 --- a/src/mono/mono/mini/mini-wasm-debugger.c +++ b/src/mono/mono/mini/mini-wasm-debugger.c @@ -928,6 +928,10 @@ describe_value(MonoType * type, gpointer addr, int gpflags) } type = m_class_get_byval_arg (klass); + if (type->type == MONO_TYPE_OBJECT) { + mono_wasm_add_obj_var ("object", "object", get_object_id (obj)); + break; + } // Boxed valuetype if (m_class_is_valuetype (klass)) @@ -965,6 +969,12 @@ describe_value(MonoType * type, gpointer addr, int gpflags) MonoObject *obj = *(MonoObject**)addr; MonoClass *klass = type->data.klass; + if (m_class_is_valuetype (mono_object_class (obj))) { + addr = mono_object_unbox_internal (obj); + type = m_class_get_byval_arg (mono_object_class (obj)); + goto handle_vtype; + } + char *class_name = mono_type_full_name (type); int obj_id = get_object_id (obj); diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/Tests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/Tests.cs index ad3fae9..16296b6 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/Tests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/Tests.cs @@ -1062,6 +1062,57 @@ namespace DebuggerTests }); [Theory] + [InlineData("BoxedTypeObjectTest", false)] + [InlineData("BoxedTypeObjectTestAsync", true)] + public async Task InspectBoxedTypeObject(string method_name, bool is_async) => await CheckInspectLocalsAtBreakpointSite( + "DebuggerTest", + method_name, + 9, + is_async ? "MoveNext" : method_name, + $"window.setTimeout(function() {{ invoke_static_method_async('[debugger-test] DebuggerTest:{method_name}'); }}, 1);", + wait_for_event_fn: async (pause_location) => + { + var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); + var dt = new DateTime(2310, 1, 2, 3, 4, 5); + await CheckProps(locals, new + { + i = TNumber(5), + o0 = TNumber(5), + o1 = TNumber(5), + o2 = TNumber(5), + o3 = TNumber(5), + + oo = TObject("object"), + oo0 = TObject("object"), + }, "locals"); + }); + + [Theory] + [InlineData("BoxedAsClass", false)] + [InlineData("BoxedAsClassAsync", true)] + public async Task InspectBoxedAsClassLocals(string method_name, bool is_async) => await CheckInspectLocalsAtBreakpointSite( + "DebuggerTest", + method_name, + 6, + is_async ? "MoveNext" : method_name, + $"window.setTimeout(function() {{ invoke_static_method_async('[debugger-test] DebuggerTest:{method_name}'); }}, 1);", + wait_for_event_fn: async (pause_location) => + { + var locals = await GetProperties(pause_location["callFrames"][0]["callFrameId"].Value()); + var dt = new DateTime(2310, 1, 2, 3, 4, 5); + Console.WriteLine (locals); + + await CheckProps(locals, new + { + vt_dt = TDateTime(new DateTime(4819, 5, 6, 7, 8, 9)), + vt_gs = TValueType("Math.GenericStruct"), + e = TEnum("System.IO.FileMode", "0"), + ee = TEnum("System.IO.FileMode", "Append") + }, "locals"); + }); + + + [Theory] [InlineData(false)] [InlineData(true)] public async Task InspectValueTypeMethodArgs(bool use_cfo) diff --git a/src/mono/wasm/debugger/tests/debugger-test.cs b/src/mono/wasm/debugger/tests/debugger-test.cs index 7de0554..ceb5500 100644 --- a/src/mono/wasm/debugger/tests/debugger-test.cs +++ b/src/mono/wasm/debugger/tests/debugger-test.cs @@ -382,6 +382,53 @@ public class DebuggerTest Console.WriteLine ($"break here"); await Task.CompletedTask; } + + public static void BoxedTypeObjectTest() + { + int i = 5; + object o0 = i; + object o1 = o0; + object o2 = o1; + object o3 = o2; + + object oo = new object(); + object oo0 = oo; + Console.WriteLine ($"break here"); + } + public static async Task BoxedTypeObjectTestAsync() + { + int i = 5; + object o0 = i; + object o1 = o0; + object o2 = o1; + object o3 = o2; + + object oo = new object(); + object oo0 = oo; + Console.WriteLine ($"break here"); + await Task.CompletedTask; + } + + public static void BoxedAsClass() + { + ValueType vt_dt = new DateTime(4819, 5, 6, 7, 8, 9); + ValueType vt_gs = new Math.GenericStruct { StringField = "vt_gs#StringField" }; + Enum e = new System.IO.FileMode(); + Enum ee = System.IO.FileMode.Append; + + Console.WriteLine ($"break here"); + } + + public static async Task BoxedAsClassAsync() + { + ValueType vt_dt = new DateTime(4819, 5, 6, 7, 8, 9); + ValueType vt_gs = new Math.GenericStruct { StringField = "vt_gs#StringField" }; + Enum e = new System.IO.FileMode(); + Enum ee = System.IO.FileMode.Append; + + Console.WriteLine ($"break here"); + await Task.CompletedTask; + } } public class MulticastDelegateTestClass -- 2.7.4