Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[verifier] Do method visibility checks for virtual final methods. Enable type visibility for all methods. Fixes #5644. #2880

Merged
merged 3 commits into from Apr 20, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion mcs/class/corlib/Test/System/DelegateTest.cs
Expand Up @@ -1251,7 +1251,7 @@ public class CreateDelegateBar : CreateDelegateMid, CreateDelegateIFoo {
}
}

delegate int IntNoArgs ();
public delegate int IntNoArgs ();

[Test]
public void CreateDelegateWithAbstractMethods ()
Expand Down
44 changes: 24 additions & 20 deletions mono/metadata/class.c
Expand Up @@ -10017,6 +10017,8 @@ is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
return FALSE;
}

static gboolean debug_check;

MonoClass *
mono_class_get_generic_type_definition (MonoClass *klass)
{
Expand Down Expand Up @@ -10160,6 +10162,9 @@ can_access_type (MonoClass *access_klass, MonoClass *member_klass)
{
int access_level;

if (access_klass == member_klass)
return TRUE;

if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
return TRUE;

Expand Down Expand Up @@ -10308,26 +10313,15 @@ mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
gboolean
mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
{
int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
if (!can) {
MonoClass *nested = method->klass->nested_in;
while (nested) {
can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
if (can)
return TRUE;
nested = nested->nested_in;
}
gboolean res = mono_method_can_access_method_full (method, called, NULL);
if (!res) {
printf ("FAILED TO VERIFY %s calling %s\n", mono_method_full_name (method, 1), mono_method_full_name (called, 1));
debug_check = TRUE;
mono_method_can_access_method_full (method, called, NULL);
debug_check = FALSE;
}
/*
* FIXME:
* with generics calls to explicit interface implementations can be expressed
* directly: the method is private, but we must allow it. This may be opening
* a hole or the generics code should handle this differently.
* Maybe just ensure the interface type is public.
*/
if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
return TRUE;
return can;

return res;
}

/*
Expand All @@ -10344,40 +10338,50 @@ mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
gboolean
mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
{
if (debug_check) printf ("CHECKING %s -> %s (%p)\n", mono_method_full_name (method, 1), mono_method_full_name (called, 1), context_klass);
MonoClass *access_class = method->klass;
MonoClass *member_class = called->klass;
int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
if (!can) {
if (debug_check) printf ("\tcan_access_member failed\n");
MonoClass *nested = access_class->nested_in;
while (nested) {
can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
if (can)
break;
nested = nested->nested_in;
}
if (!can && debug_check) printf ("\tcan_access_member nest check failed\n");
}

if (!can)
return FALSE;

if (debug_check) printf ("\ttype checking %s(%p) -> %s(%p)\n",
mono_type_get_full_name (access_class), access_class,
mono_type_get_full_name (member_class), member_class);
can = can_access_type (access_class, member_class);
if (!can) {
if (debug_check) printf ("\tcan_access_type check failed\n");
MonoClass *nested = access_class->nested_in;
while (nested) {
can = can_access_type (nested, member_class);
if (can)
break;
nested = nested->nested_in;
}
if (!can && debug_check) printf ("\tcan_access_type nest check failed\n");
}

if (!can)
return FALSE;

if (called->is_inflated) {
MonoMethodInflated * infl = (MonoMethodInflated*)called;
if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst)) {
if (debug_check) printf ("\tginst check failed\n");
return FALSE;
}
}

return TRUE;
Expand Down