Skip to content

Commit

Permalink
Throw MemberAccessException when abstract class is used with newobj i…
Browse files Browse the repository at this point in the history
…nstruction
  • Loading branch information
joncham committed Apr 5, 2018
1 parent 13e9761 commit d1feca2
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 1 deletion.
1 change: 1 addition & 0 deletions mono/metadata/class-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ typedef enum {
MONO_EXCEPTION_OUT_OF_MEMORY = 14,
MONO_EXCEPTION_INLINE_FAILED = 15,
MONO_EXCEPTION_MONO_ERROR = 16,
MONO_EXCEPTION_MEMBER_ACCESS = 17,
/* add other exception type */
} MonoExceptionType;

Expand Down
8 changes: 8 additions & 0 deletions mono/mini/method-to-ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -3653,6 +3653,14 @@ handle_alloc (MonoCompile *cfg, MonoClass *klass, gboolean for_box, int context_
MonoInst *iargs [2];
void *alloc_ftn;

if (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_ABSTRACT) {
char* full_name = mono_type_get_full_name (klass);
cfg->exception_message = g_strdup_printf ("Cannot create an abstract class: %s", full_name);
g_free (full_name);
mono_cfg_set_exception (cfg, MONO_EXCEPTION_MEMBER_ACCESS);
return NULL;
}

if (context_used) {
MonoInst *data;
MonoRgctxInfoType rgctx_info;
Expand Down
3 changes: 3 additions & 0 deletions mono/mini/mini.c
Original file line number Diff line number Diff line change
Expand Up @@ -4187,6 +4187,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
case MONO_EXCEPTION_TYPE_LOAD:
case MONO_EXCEPTION_MISSING_FIELD:
case MONO_EXCEPTION_MISSING_METHOD:
case MONO_EXCEPTION_MEMBER_ACCESS:
case MONO_EXCEPTION_FILE_NOT_FOUND:
case MONO_EXCEPTION_BAD_IMAGE:
case MONO_EXCEPTION_INVALID_PROGRAM: {
Expand All @@ -4206,6 +4207,8 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
ex = mono_get_exception_bad_image_format (cfg->exception_message);
else if (cfg->exception_type == MONO_EXCEPTION_INVALID_PROGRAM)
ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", cfg->exception_message);
else if (cfg->exception_type == MONO_EXCEPTION_MEMBER_ACCESS)
ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MemberAccessException", cfg->exception_message);
else
g_assert_not_reached ();
}
Expand Down
3 changes: 2 additions & 1 deletion mono/tests/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,8 @@ TESTS_IL_SRC= \
gsharing-valuetype-layout.il \
invalid_generic_instantiation.il \
bug-45841-fpstack-exceptions.il \
instance_tailrec.il
instance_tailrec.il \
newobj-abstract.il

TESTS_GSHARED_SRC = \
generics-sharing.2.cs \
Expand Down
61 changes: 61 additions & 0 deletions mono/tests/newobj-abstract.il
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
.assembly extern mscorlib {}

.assembly 'newobj-abstract' {}

.class private auto ansi beforefieldinit Program
extends [mscorlib]System.Object
{
.method public hidebysig static int32 Main() cil managed
{
.entrypoint
.locals init (int32 V_0)

ldc.i4.1
stloc.0
.try
{
call void Program::NewAbstract()
leave.s leavetarget

} // end .try
catch [mscorlib]System.MemberAccessException
{
pop
ldc.i4.0
stloc.0
leave.s leavetarget
}
leavetarget:
ldloc.0
ret
} // end of method Program::Main

.method public hidebysig static void NewAbstract() cil managed
{
newobj instance void Foo::.ctor()
call void [mscorlib]System.GC::KeepAlive(object)
ret
}

.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void [mscorlib]System.Object::.ctor()
ret
}

}

.class private abstract auto ansi beforefieldinit Foo
extends [mscorlib]System.Object
{
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
ldarg.0
call instance void [mscorlib]System.Object::.ctor()
ret
}

}

0 comments on commit d1feca2

Please sign in to comment.