Bug 57691 - InternalsVisibleTo doesn't work with 2048-bit SNK files
Summary: InternalsVisibleTo doesn't work with 2048-bit SNK files
Alias: None
Product: Runtime
Classification: Mono
Component: Reflection ()
Version: 5.2 (2017-04)
Hardware: PC Windows
: --- normal
Target Milestone: ---
Assignee: Aleksey Kliger
Depends on:
Reported: 2017-06-22 15:40 UTC by duncanp
Modified: 2017-07-14 19:12 UTC (History)
4 users (show)

Is this bug a regression?: ---
Last known good build:

Repro solution (42.11 KB, application/x-zip-compressed)
2017-06-22 15:40 UTC, duncanp
Console reproduction (3.94 KB, application/zip)
2017-07-13 15:24 UTC, Aleksey Kliger

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description duncanp 2017-06-22 15:40:14 UTC
Created attachment 23060 [details]
Repro solution


A solution has two projects: an App that references a Library (VS2017, using templates "Blank App (Android) C#" and "Class Library (Android) C#").

The Library has an internal method, and an [InternalsVisibleTo] attribute to make it visible to the App.

The runtime behaviour of the app differs depending on which key the app is signed with.
Signed with the 1024 bit SNK: the app can call the library internal method correctly.
Signed with the 2048 bit SNK: calling the internal method fails at runtime with the following error:

Error message:
"Method `XamarinAndroidApp.MainActivity:OnCreate (Android.OS.Bundle)' is inaccessible from method `XamarinAndroidLib.Class1:InternalMethod ()'"

Stack trace:
"  at (wrapper managed-to-native) System.Object:__icall_wrapper_mono_throw_method_access (intptr,intptr)
  at XamarinAndroidApp.MainActivity.OnCreate (Android.OS.Bundle bundle) [0x0003d] in D:\\Code\\VS2017\\XamarinAndroidApp\\XamarinAndroidApp\\MainActivity.cs:34 "

Note: the error message seems to be the wrong way round too: it says "OnCreate is inaccessible from InternalMethod" i.e. it is saying that "InternalMethod" is the caller, when in fact "OnCreate" is the caller.
Comment 1 Zoltan Varga 2017-06-26 22:27:35 UTC
The "the error message seems to be the wrong way round too: it says "OnCreate is inaccessible from InternalMethod" i.e. it is saying that "InternalMethod" is the caller, when in fact "OnCreate" is the caller." problem is fixed in recent mono versions.
Comment 2 Aleksey Kliger 2017-07-13 15:24:44 UTC
Created attachment 23537 [details]
Console reproduction

Also fails in a console app (Mono (2017-04/4a0006f Wed May 10 05:06:51 EDT 2017)).
Comment 3 Aleksey Kliger 2017-07-13 17:49:08 UTC
mono_assembly_load_friends is computing the public key token from an InternalsVisibleTo attribute incorrectly:

sn -tp 2048Bit.snk prints
    Public Key Token: ce4fac203c2524eb

in lldb, I can see that mono_assembly_load_friends() set friend_assembly_names->data to 

(MonoAssemblyName) $5 = {
  name = 0x0000000104b00ac0 "App"
  culture = 0x0000000000000000 <no value available>
  hash_value = 0x0000000000000000 <no value available>
  public_key = 0x0000000104b00c60 "\xffffff80 "
  public_key_token = {
    [0] = '6'
    [1] = 'f'
    [2] = '8'
    [3] = 'b'
    [4] = '3'
    [5] = '5'
    [6] = 'a'
    [7] = 'e'
    [8] = 'e'
    [9] = '7'
    [10] = 'a'
    [11] = 'f'
    [12] = '2'
    [13] = '8'
    [14] = '1'
    [15] = '7'
    [16] = '\0'
  hash_alg = 0
  hash_len = 0
  flags = 0
  major = 0
  minor = 0
  build = 0
  revision = 0
  arch = 0

Later in can_access_internals() we check whether the public keys match, and they clearly don't.