#! /bin/sh /usr/share/dpatch/dpatch-run ## fix_bound_checking_r98524_r98527.dpatch by Jo Shields ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: Pull in two SVN changesets to fix bound checking, which manifests itself ## DP: as XSP failing to compile on amd64. Changelog entries and init_trampoline ## DP: routine changes snipped to apply cleanly against 1.9.1 @DPATCH@ Index: mono/mono/mini/tramp-ia64.c =================================================================== --- mono/mono/mini/tramp-ia64.c (revision 98523) +++ mono/mono/mini/tramp-ia64.c (revision 98524) @@ -76,7 +76,7 @@ } void -mono_arch_patch_callsite (guint8 *code, guint8 *addr) +mono_arch_patch_callsite (guint8 *method_start, guint8 *code, guint8 *addr) { guint8 *callsite_begin; guint64 *callsite = (guint64*)(gpointer)(code - 16); Index: mono/mono/mini/tramp-arm.c =================================================================== --- mono/mono/mini/tramp-arm.c (revision 98523) +++ mono/mono/mini/tramp-arm.c (revision 98524) @@ -75,7 +75,7 @@ } void -mono_arch_patch_callsite (guint8 *code_ptr, guint8 *addr) +mono_arch_patch_callsite (guint8 *method_start, guint8 *code_ptr, guint8 *addr) { guint32 *code = (guint32*)code_ptr; Index: mono/mono/mini/mini.h =================================================================== --- mono/mono/mini/mini.h (revision 98523) +++ mono/mono/mini/mini.h (revision 98524) @@ -1254,7 +1254,7 @@ void mono_arch_save_unwind_info (MonoCompile *cfg) MONO_INTERNAL; void mono_arch_register_lowlevel_calls (void) MONO_INTERNAL; gpointer mono_arch_get_unbox_trampoline (MonoMethod *m, gpointer addr) MONO_INTERNAL; -void mono_arch_patch_callsite (guint8 *code, guint8 *addr) MONO_INTERNAL; +void mono_arch_patch_callsite (guint8 *method_start, guint8 *code, guint8 *addr) MONO_INTERNAL; void mono_arch_patch_plt_entry (guint8 *code, guint8 *addr) MONO_INTERNAL; void mono_arch_nullify_class_init_trampoline(guint8 *code, gssize *regs) MONO_INTERNAL; void mono_arch_nullify_plt_entry (guint8 *code) MONO_INTERNAL; Index: mono/mono/mini/tramp-alpha.c =================================================================== --- mono/mono/mini/tramp-alpha.c (revision 98523) +++ mono/mono/mini/tramp-alpha.c (revision 98524) @@ -523,7 +523,7 @@ } void -mono_arch_patch_callsite (guint8 *code, guint8 *addr) +mono_arch_patch_callsite (guint8 *method_start, guint8 *code, guint8 *addr) { unsigned long *p = (unsigned int *)(code-12); Index: mono/mono/mini/tramp-s390.c =================================================================== --- mono/mono/mini/tramp-s390.c (revision 98523) +++ mono/mono/mini/tramp-s390.c (revision 98524) @@ -128,7 +128,7 @@ /*------------------------------------------------------------------*/ void -mono_arch_patch_callsite (guint8 *orig_code, guint8 *addr) +mono_arch_patch_callsite (guint8 *method_start, guint8 *orig_code, guint8 *addr) { gint32 displace; unsigned short opcode; Index: mono/mono/mini/tramp-amd64.c =================================================================== --- mono/mono/mini/tramp-amd64.c (revision 98523) +++ mono/mono/mini/tramp-amd64.c (revision 98524) @@ -69,7 +69,7 @@ * points to the pc right after the call. */ void -mono_arch_patch_callsite (guint8 *orig_code, guint8 *addr) +mono_arch_patch_callsite (guint8 *method_start, guint8 *orig_code, guint8 *addr) { guint8 *code; guint8 buf [16]; Index: mono/mono/mini/tramp-ppc.c =================================================================== --- mono/mono/mini/tramp-ppc.c (revision 98523) +++ mono/mono/mini/tramp-ppc.c (revision 98524) @@ -85,7 +85,7 @@ } void -mono_arch_patch_callsite (guint8 *code_ptr, guint8 *addr) +mono_arch_patch_callsite (guint8 *method_start, guint8 *code_ptr, guint8 *addr) { guint32 *code = (guint32*)code_ptr; /* This is the 'blrl' instruction */ Index: mono/mono/mini/tramp-hppa.c =================================================================== --- mono/mono/mini/tramp-hppa.c (revision 98523) +++ mono/mono/mini/tramp-hppa.c (revision 98524) @@ -77,7 +77,7 @@ } void -mono_arch_patch_callsite (guint8 *p, guint8 *addr) +mono_arch_patch_callsite (guint8 *method_start, guint8 *p, guint8 *addr) { guint32 *code = (void *)p; /* Search for and patch the calling sequence Index: mono/mono/mini/mini-trampolines.c =================================================================== --- mono/mono/mini/mini-trampolines.c (revision 98523) +++ mono/mono/mini/mini-trampolines.c (revision 98524) @@ -251,7 +251,7 @@ mono_jit_info_table_find (mono_domain_get (), mono_get_addr_from_ftnptr (addr)); if (mono_method_same_domain (ji, target_ji)) - mono_arch_patch_callsite (code, addr); + mono_arch_patch_callsite (ji->code_start, code, addr); } } Index: mono/mono/mini/tramp-x86.c =================================================================== --- mono/mono/mini/tramp-x86.c (revision 98523) +++ mono/mono/mini/tramp-x86.c (revision 98524) @@ -58,7 +58,7 @@ } void -mono_arch_patch_callsite (guint8 *orig_code, guint8 *addr) +mono_arch_patch_callsite (guint8 *method_start, guint8 *orig_code, guint8 *addr) { guint8 *code; guint8 buf [8]; Index: mono/mono/mini/tramp-s390x.c =================================================================== --- mono/mono/mini/tramp-s390x.c (revision 98523) +++ mono/mono/mini/tramp-s390x.c (revision 98524) @@ -128,7 +128,7 @@ /*------------------------------------------------------------------*/ void -mono_arch_patch_callsite (guint8 *orig_code, guint8 *addr) +mono_arch_patch_callsite (guint8 *method_start, guint8 *orig_code, guint8 *addr) { gint32 displace; unsigned short opcode; Index: mono/mono/mini/tramp-sparc.c =================================================================== --- mono/mono/mini/tramp-sparc.c (revision 98523) +++ mono/mono/mini/tramp-sparc.c (revision 98524) @@ -58,7 +58,7 @@ } void -mono_arch_patch_callsite (guint8 *code, guint8 *addr) +mono_arch_patch_callsite (guint8 *method_start, guint8 *code, guint8 *addr) { if (sparc_inst_op (*(guint32*)code) == 0x1) { sparc_call_simple (code, (guint8*)addr - (guint8*)code); Index: mono/mono/mini/mini.h =================================================================== --- mono/mono/mini/mini.h (revision 98526) +++ mono/mono/mini/mini.h (revision 98527) @@ -1318,7 +1318,7 @@ extern gssize mono_breakpoint_info_index [MONO_BREAKPOINT_ARRAY_SIZE]; -gboolean mono_breakpoint_clean_code (guint8 *code, guint8 *buf, int size); +gboolean mono_breakpoint_clean_code (guint8 *method_start, guint8 *code, int offset, guint8 *buf, int size); /* Mono Debugger support */ void mono_debugger_init (void); Index: mono/mono/mini/mini-amd64.c =================================================================== --- mono/mono/mini/mini-amd64.c (revision 98526) +++ mono/mono/mini/mini-amd64.c (revision 98527) @@ -5494,12 +5494,33 @@ return 3; } +/** + * mono_breakpoint_clean_code: + * + * Copy @size bytes from @code - @offset to the buffer @buf. If the debugger inserted software + * breakpoints in the original code, they are removed in the copy. + * + * Returns TRUE if no sw breakpoint was present. + */ gboolean -mono_breakpoint_clean_code (guint8 *code, guint8 *buf, int size) +mono_breakpoint_clean_code (guint8 *method_start, guint8 *code, int offset, guint8 *buf, int size) { int i; gboolean can_write = TRUE; - memcpy (buf, code, size); + /* + * If method_start is non-NULL we need to perform bound checks, since we access memory + * at code - offset we could go before the start of the method and end up in a different + * page of memory that is not mapped or read incorrect data anyway. We zero-fill the bytes + * instead. + */ + if (!method_start || code - offset >= method_start) { + memcpy (buf, code - offset, size); + } else { + int diff = code - method_start; + memset (buf, 0, size); + memcpy (buf + offset - diff, method_start, diff + size - offset); + } + code -= offset; for (i = 0; i < MONO_BREAKPOINT_ARRAY_SIZE; ++i) { int idx = mono_breakpoint_info_index [i]; guint8 *ptr; @@ -5524,8 +5545,8 @@ gint32 disp; guint8 rex = 0; - mono_breakpoint_clean_code (code - 10, buf, sizeof (buf)); - code = buf + 10; + mono_breakpoint_clean_code (NULL, code, 9, buf, sizeof (buf)); + code = buf + 9; *displacement = 0; Index: mono/mono/mini/mini-x86.c =================================================================== --- mono/mono/mini/mini-x86.c (revision 98526) +++ mono/mono/mini/mini-x86.c (revision 98527) @@ -4570,12 +4570,33 @@ } } +/** + * mono_breakpoint_clean_code: + * + * Copy @size bytes from @code - @offset to the buffer @buf. If the debugger inserted software + * breakpoints in the original code, they are removed in the copy. + * + * Returns TRUE if no sw breakpoint was present. + */ gboolean -mono_breakpoint_clean_code (guint8 *code, guint8 *buf, int size) +mono_breakpoint_clean_code (guint8 *method_start, guint8 *code, int offset, guint8 *buf, int size) { int i; gboolean can_write = TRUE; - memcpy (buf, code, size); + /* + * If method_start is non-NULL we need to perform bound checks, since we access memory + * at code - offset we could go before the start of the method and end up in a different + * page of memory that is not mapped or read incorrect data anyway. We zero-fill the bytes + * instead. + */ + if (!method_start || code - offset >= method_start) { + memcpy (buf, code - offset, size); + } else { + int diff = code - method_start; + memset (buf, 0, size); + memcpy (buf + offset - diff, method_start, diff + size - offset); + } + code -= offset; for (i = 0; i < MONO_BREAKPOINT_ARRAY_SIZE; ++i) { int idx = mono_breakpoint_info_index [i]; guint8 *ptr; @@ -4599,7 +4620,7 @@ guint8 reg = 0; gint32 disp = 0; - mono_breakpoint_clean_code (code - 8, buf, sizeof (buf)); + mono_breakpoint_clean_code (NULL, code, 8, buf, sizeof (buf)); code = buf + 8; *displacement = 0; Index: mono/mono/mini/tramp-amd64.c =================================================================== --- mono/mono/mini/tramp-amd64.c (revision 98526) +++ mono/mono/mini/tramp-amd64.c (revision 98527) @@ -73,7 +73,7 @@ { guint8 *code; guint8 buf [16]; - gboolean can_write = mono_breakpoint_clean_code (orig_code - 14, buf, sizeof (buf)); + gboolean can_write = mono_breakpoint_clean_code (method_start, orig_code, 14, buf, sizeof (buf)); code = buf + 14; Index: mono/mono/mini/tramp-x86.c =================================================================== --- mono/mono/mini/tramp-x86.c (revision 98526) +++ mono/mono/mini/tramp-x86.c (revision 98527) @@ -62,7 +62,7 @@ { guint8 *code; guint8 buf [8]; - gboolean can_write = mono_breakpoint_clean_code (orig_code - 8, buf, sizeof (buf)); + gboolean can_write = mono_breakpoint_clean_code (method_start, orig_code, 8, buf, sizeof (buf)); code = buf + 8; if (mono_running_on_valgrind ())