From 1d0f7d93f19d8a93f4897c4f35687ebbd8e70631 Mon Sep 17 00:00:00 2001 From: kumpera Date: Tue, 15 Dec 2009 19:04:11 +0000 Subject: [PATCH] 2009-12-15 Rodrigo Kumpera * mini-x86.c (mono_arch_allocate_vars): Fail compilation if the frame size is bigger than MONO_ARCH_MAX_FRAME_SIZE. * mini-x86.c (mono_arch_emit_prolog): Handle huge frames. * mini-x86.h: Define MONO_ARCH_MAX_FRAME_SIZE to be 1Mb. * mini-amd64.c / mini-amd64.h: Same fixes as of above. * mini.c (mini_method_compile): Check if mono_arch_allocate_vars failed the compilation. git-svn-id: svn+ssh://mono-cvs.ximian.com/source/trunk/mono@148502 e3ebcda4-bce8-0310-ba0a-eca2169e7518 --- mono/mini/ChangeLog | 14 ++++++++++++++ mono/mini/mini-amd64.c | 19 +++++++++++++++++++ mono/mini/mini-amd64.h | 3 +++ mono/mini/mini-x86.c | 17 +++++++++++++++++ mono/mini/mini-x86.h | 3 +++ mono/mini/mini.c | 5 ++++- 6 files changed, 60 insertions(+), 1 deletion(-) diff --git a/mono/mini/ChangeLog b/mono/mini/ChangeLog index fc5b24051..13c792e4f 100644 --- a/mono/mini/ChangeLog +++ b/mono/mini/ChangeLog @@ -1,3 +1,17 @@ +2009-12-15 Rodrigo Kumpera + + * mini-x86.c (mono_arch_allocate_vars): Fail compilation if the frame size is + bigger than MONO_ARCH_MAX_FRAME_SIZE. + + * mini-x86.c (mono_arch_emit_prolog): Handle huge frames. + + * mini-x86.h: Define MONO_ARCH_MAX_FRAME_SIZE to be 1Mb. + + * mini-amd64.c / mini-amd64.h: Same fixes as of above. + + * mini.c (mini_method_compile): Check if mono_arch_allocate_vars failed + the compilation. + 2009-12-14 Miguel de Icaza * method-to-ir.c (mono_method_to_ir): CEE_UNUSUED opcodes now diff --git a/mono/mini/mini-amd64.c b/mono/mini/mini-amd64.c index eb9b3cede..30df6fac5 100644 --- a/mono/mini/mini-amd64.c +++ b/mono/mini/mini-amd64.c @@ -1423,6 +1423,14 @@ mono_arch_allocate_vars (MonoCompile *cfg) /* Allocate locals */ if (!cfg->globalra) { offsets = mono_allocate_stack_slots_full (cfg, cfg->arch.omit_fp ? FALSE: TRUE, &locals_stack_size, &locals_stack_align); + if (locals_stack_size > MONO_ARCH_MAX_FRAME_SIZE) { + char *mname = mono_method_full_name (cfg->method, TRUE); + cfg->exception_type = MONO_EXCEPTION_INVALID_PROGRAM; + cfg->exception_message = g_strdup_printf ("Method %s stack is too big.", mname); + g_free (mname); + return; + } + if (locals_stack_align) { offset += (locals_stack_align - 1); offset &= ~(locals_stack_align - 1); @@ -5727,6 +5735,17 @@ mono_arch_emit_prolog (MonoCompile *cfg) /* See mono_emit_stack_alloc */ #if defined(HOST_WIN32) || defined(MONO_ARCH_SIGSEGV_ON_ALTSTACK) guint32 remaining_size = alloc_size; + /*FIXME handle unbounded code expansion, we should use a loop in case of more than X interactions*/ + guint32 required_code_size = ((remaining_size / 0x1000) + 1) * 10; /*10 is the max size of amd64_alu_reg_imm + amd64_test_membase_reg*/ + guint32 offset = code - cfg->native_code; + if (G_UNLIKELY (required_code_size >= (cfg->code_size - offset))) { + while (required_code_size >= (cfg->code_size - offset)) + cfg->code_size *= 2; + cfg->native_code = g_realloc (cfg->native_code, cfg->code_size); + code = cfg->native_code + offset; + mono_jit_stats.code_reallocs++; + } + while (remaining_size >= 0x1000) { amd64_alu_reg_imm (code, X86_SUB, AMD64_RSP, 0x1000); if (cfg->arch.omit_fp) { diff --git a/mono/mini/mini-amd64.h b/mono/mini/mini-amd64.h index 334e802e7..67751176e 100644 --- a/mono/mini/mini-amd64.h +++ b/mono/mini/mini-amd64.h @@ -131,6 +131,9 @@ struct sigcontext { #define MONO_ARCH_RETREG1 X86_EAX #define MONO_ARCH_RETREG2 X86_EDX +/*This is the max size of the locals area of a given frame. I think 1MB is a safe default for now*/ +#define MONO_ARCH_MAX_FRAME_SIZE 0x100000 + struct MonoLMF { /* * If the lowest bit is set to 1, then this LMF has the rip field set. Otherwise, diff --git a/mono/mini/mini-x86.c b/mono/mini/mini-x86.c index 07de7c4b1..b79dd56b1 100644 --- a/mono/mini/mini-x86.c +++ b/mono/mini/mini-x86.c @@ -990,6 +990,13 @@ mono_arch_allocate_vars (MonoCompile *cfg) /* Allocate locals */ offsets = mono_allocate_stack_slots (cfg, &locals_stack_size, &locals_stack_align); + if (locals_stack_size > MONO_ARCH_MAX_FRAME_SIZE) { + char *mname = mono_method_full_name (cfg->method, TRUE); + cfg->exception_type = MONO_EXCEPTION_INVALID_PROGRAM; + cfg->exception_message = g_strdup_printf ("Method %s stack is too big.", mname); + g_free (mname); + return; + } if (locals_stack_align) { offset += (locals_stack_align - 1); offset &= ~(locals_stack_align - 1); @@ -4636,6 +4643,16 @@ mono_arch_emit_prolog (MonoCompile *cfg) /* See mono_emit_stack_alloc */ #if defined(TARGET_WIN32) || defined(MONO_ARCH_SIGSEGV_ON_ALTSTACK) guint32 remaining_size = alloc_size; + /*FIXME handle unbounded code expansion, we should use a loop in case of more than X interactions*/ + guint32 required_code_size = ((remaining_size / 0x1000) + 1) * 8; /*8 is the max size of x86_alu_reg_imm + x86_test_membase_reg*/ + guint32 offset = code - cfg->native_code; + if (G_UNLIKELY (required_code_size >= (cfg->code_size - offset))) { + while (required_code_size >= (cfg->code_size - offset)) + cfg->code_size *= 2; + cfg->native_code = g_realloc (cfg->native_code, cfg->code_size); + code = cfg->native_code + offset; + mono_jit_stats.code_reallocs++; + } while (remaining_size >= 0x1000) { x86_alu_reg_imm (code, X86_SUB, X86_ESP, 0x1000); x86_test_membase_reg (code, X86_ESP, 0, X86_ESP); diff --git a/mono/mini/mini-x86.h b/mono/mini/mini-x86.h index f0ac298c0..72be2e799 100644 --- a/mono/mini/mini-x86.h +++ b/mono/mini/mini-x86.h @@ -123,6 +123,9 @@ LONG CALLBACK seh_handler(EXCEPTION_POINTERS* ep); #define MONO_ARCH_RETREG1 X86_EAX #define MONO_ARCH_RETREG2 X86_EDX +/*This is the max size of the locals area of a given frame. I think 1MB is a safe default for now*/ +#define MONO_ARCH_MAX_FRAME_SIZE 100000 + struct MonoLMF { /* * If the lowest bit is set to 1, then this is a trampoline LMF frame. diff --git a/mono/mini/mini.c b/mono/mini/mini.c index 9aaab81e2..3500edac3 100644 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -3789,8 +3789,11 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool //print_dfn (cfg); /* variables are allocated after decompose, since decompose could create temps */ - if (!cfg->globalra && !COMPILE_LLVM (cfg)) + if (!cfg->globalra && !COMPILE_LLVM (cfg)) { mono_arch_allocate_vars (cfg); + if (cfg->exception_type) + return cfg; + } { MonoBasicBlock *bb; -- 2.11.4.GIT