Skip to content

Commit defef06

Browse files
authored
Merge pull request #1331 from Unity-Technologies/unity-master-debugger-fix-1269030
[debugger] Access invalid memory address using PointerValue Command. …
2 parents 1a38e7f + 6cd09dc commit defef06

File tree

4 files changed

+119
-3
lines changed

4 files changed

+119
-3
lines changed

mcs/class/Mono.Debugger.Soft/Mono.Debugger.Soft/PointerValue.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,19 @@ public TypeMirror Type {
5151
// Since protocol version 2.46
5252
public Value Value {
5353
get {
54+
ValueImpl value;
5455
if (Address == 0)
5556
return null;
56-
57-
return vm.DecodeValue (vm.conn.Pointer_GetValue (Address, Type));
57+
try {
58+
value = vm.conn.Pointer_GetValue (Address, Type);
59+
}
60+
catch (CommandException ex) {
61+
if (ex.ErrorCode == ErrorCode.INVALID_ARGUMENT)
62+
throw new ArgumentException ("Invalid pointer address.");
63+
else
64+
throw;
65+
}
66+
return vm.DecodeValue (value);
5867
}
5968
}
6069

mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,11 @@ public static int Main (String[] args) {
377377
test_async_debug_generics();
378378
test_invalid_argument_assembly_get_type ();
379379

380+
if (args.Length >0 && args [0] == "pointer_arguments2") {
381+
pointers2 ();
382+
return 0;
383+
}
384+
380385
return 3;
381386
}
382387

@@ -1787,6 +1792,17 @@ public static ref string get_ref_string() {
17871792
public static ref BlittableStruct get_ref_struct () {
17881793
return ref ref_return_struct;
17891794
}
1795+
1796+
public static unsafe void pointer_arguments2 (int* a) {
1797+
*a = 0;
1798+
}
1799+
1800+
[MethodImplAttribute (MethodImplOptions.NoInlining)]
1801+
public static unsafe void pointers2 () {
1802+
int[] a = new [] {1,2,3};
1803+
fixed (int* pa = a)
1804+
pointer_arguments2 (pa);
1805+
}
17901806
}
17911807

17921808
public class SentinelClass : MarshalByRefObject {

mcs/class/Mono.Debugger.Soft/Test/dtest.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4470,5 +4470,30 @@ public void DebuggerBreakInFieldDoesNotHang () {
44704470
Value v = o.InvokeMethod (e.Thread, m, null, InvokeOptions.DisableBreakpoints);
44714471
AssertValue ("Foo", v);
44724472
}
4473+
4474+
[Test]
4475+
public void InvalidPointer_GetValue () {
4476+
vm.Detach ();
4477+
Start (dtest_app_path, "pointer_arguments2");
4478+
Event e = run_until ("pointer_arguments2");
4479+
var frame = e.Thread.GetFrames () [0];
4480+
4481+
var param = frame.Method.GetParameters()[0];
4482+
Assert.AreEqual("Int32*", param.ParameterType.Name);
4483+
4484+
var pointerValue = frame.GetValue(param) as PointerValue;
4485+
Assert.AreEqual("Int32*", pointerValue.Type.Name);
4486+
4487+
4488+
var pointerValue2 = new PointerValue (pointerValue.VirtualMachine, pointerValue.Type, 200);
4489+
4490+
try {
4491+
var val = pointerValue2.Value;
4492+
}
4493+
catch (ArgumentException ex) {
4494+
Assert.IsInstanceOfType (typeof (ArgumentException), ex);
4495+
}
4496+
}
4497+
44734498
} // class DebuggerTests
44744499
} // namespace

mono/mini/debugger-agent.c

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#include <process.h>
4646
#endif
4747
#include <ws2tcpip.h>
48+
#include <windows.h>
4849
#endif
4950

5051
#ifdef HOST_ANDROID
@@ -108,6 +109,13 @@
108109

109110
#include <mono/utils/mono-os-mutex.h>
110111

112+
#include <fcntl.h>
113+
#include <sys/stat.h>
114+
115+
#ifndef S_IWUSR
116+
#define S_IWUSR S_IWRITE
117+
#endif
118+
111119
#define THREAD_TO_INTERNAL(thread) (thread)->internal_thread
112120

113121
#include "debugger-agent.h"
@@ -709,6 +717,10 @@ static MonoThreadHandle *debugger_thread_handle;
709717

710718
static int log_level;
711719

720+
static int file_check_valid_memory = -1;
721+
722+
static char* filename_check_valid_memory;
723+
712724
static gboolean embedding;
713725

714726
static FILE *log_file;
@@ -1281,6 +1293,12 @@ mono_debugger_agent_cleanup (void)
12811293
breakpoints_cleanup ();
12821294
objrefs_cleanup ();
12831295
ids_cleanup ();
1296+
1297+
if (file_check_valid_memory != -1) {
1298+
remove (filename_check_valid_memory);
1299+
g_free (filename_check_valid_memory);
1300+
close (file_check_valid_memory);
1301+
}
12841302
}
12851303

12861304
/*
@@ -11711,13 +11729,56 @@ string_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
1171111729
return ERR_NONE;
1171211730
}
1171311731

11732+
#ifndef _MSC_VER
11733+
static void
11734+
create_file_to_check_memory_address (void)
11735+
{
11736+
if (file_check_valid_memory != -1)
11737+
return;
11738+
char *file_name = g_strdup_printf ("debugger_check_valid_memory.%d", getpid());
11739+
filename_check_valid_memory = g_build_filename (g_get_tmp_dir (), file_name, (const char*)NULL);
11740+
file_check_valid_memory = open(filename_check_valid_memory, O_CREAT | O_WRONLY | O_APPEND, S_IWUSR);
11741+
g_free (file_name);
11742+
}
11743+
#endif
11744+
11745+
static gboolean
11746+
valid_memory_address (gpointer addr, gint size)
11747+
{
11748+
#ifndef _MSC_VER
11749+
gboolean ret = TRUE;
11750+
create_file_to_check_memory_address ();
11751+
if(file_check_valid_memory < 0) {
11752+
return TRUE;
11753+
}
11754+
write (file_check_valid_memory, (gpointer)addr, 1);
11755+
if (errno == EFAULT) {
11756+
ret = FALSE;
11757+
}
11758+
#else
11759+
int i = 0;
11760+
gboolean ret = FALSE;
11761+
__try {
11762+
for (i = 0; i < size; i++)
11763+
*((volatile char*)addr+i);
11764+
ret = TRUE;
11765+
} __except(1) {
11766+
return ret;
11767+
}
11768+
#endif
11769+
return ret;
11770+
}
11771+
1171411772
static ErrorCode
1171511773
pointer_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
1171611774
{
1171711775
ErrorCode err;
1171811776
gint64 addr;
1171911777
MonoClass* klass;
1172011778
MonoDomain* domain = NULL;
11779+
MonoType *type = NULL;
11780+
int align;
11781+
int size = 0;
1172111782

1172211783
switch (command) {
1172311784
case CMD_POINTER_GET_VALUE:
@@ -11729,8 +11790,13 @@ pointer_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
1172911790
if (mono_class_get_type (klass)->type != MONO_TYPE_PTR)
1173011791
return ERR_INVALID_ARGUMENT;
1173111792

11732-
buffer_add_value (buf, mono_class_get_type (mono_class_get_element_class (klass)), (gpointer)addr, domain);
11793+
type = mono_class_get_type (mono_class_get_element_class(klass));
11794+
size = mono_type_size (type, &align);
11795+
11796+
if (!valid_memory_address((gpointer)addr, size))
11797+
return ERR_INVALID_ARGUMENT;
1173311798

11799+
buffer_add_value (buf, type, (gpointer)addr, domain);
1173411800
break;
1173511801
default:
1173611802
return ERR_NOT_IMPLEMENTED;

0 commit comments

Comments
 (0)