I have the following attribute SecurityPermission(SecurityAction.Assert)
on a method in my class. I compile it (debug build) and view the output in ildasm.exe by viewing the raw heaps and looking at the blob heap containing the PermissionSet blob. What I expect (per ECMA-335) is:
2e 01 80 84 53 79 73 74 65 6d 2e 53 65 63 75 72 >. System.Secur<
69 74 79 2e 50 65 72 6d 69 73 73 69 6f 6e 73 2e >ity.Permissions.<
53 65 63 75 72 69 74 79 50 65 72 6d 69 73 73 69 >SecurityPermissi<
6f 6e 41 74 74 72 69 62 75 74 65 2c 20 6d 73 63 >onAttribute, msc<
6f 72 6c 69 62 2c 20 56 65 72 73 69 6f 6e 3d 32 >orlib, Version=2<
2e 30 2e 30 2e 30 2c 20 43 75 6c 74 75 72 65 3d >.0.0.0, Culture=<
6e 65 75 74 72 61 6c 2c 20 50 75 62 6c 69 63 4b >neutral, PublicK<
65 79 54 6f 6b 65 6e 3d 62 37 37 61 35 63 35 36 >eyToken=b77a5c56<
31 39 33 34 65 30 38 39 00 00
But what I saw was this:
2e 01 80 84 53 79 73 74 65 6d 2e 53 65 63 75 72 >. System.Secur<
69 74 79 2e 50 65 72 6d 69 73 73 69 6f 6e 73 2e >ity.Permissions.<
53 65 63 75 72 69 74 79 50 65 72 6d 69 73 73 69 >SecurityPermissi<
6f 6e 41 74 74 72 69 62 75 74 65 2c 20 6d 73 63 >onAttribute, msc<
6f 72 6c 69 62 2c 20 56 65 72 73 69 6f 6e 3d 32 >orlib, Version=2<
2e 30 2e 30 2e 30 2c 20 43 75 6c 74 75 72 65 3d >.0.0.0, Culture=<
6e 65 75 74 72 61 6c 2c 20 50 75 62 6c 69 63 4b >neutral, PublicK<
65 79 54 6f 6b 65 6e 3d 62 37 37 61 35 63 35 36 >eyToken=b77a5c56<
31 39 33 34 65 30 38 39 01 00
In particular, note the 01 00
at the end where I expected a 00 00
. The spec says that after the counted string should be the number of named arguments. Since I am not passing in any named arguments I expected that number to be a 16-bit 0.
This is compiled against .NET 2.0 using Visual Studio 2013.
To complicate matters even more, if I add in a named argument I get this:
2e 01 80 84 53 79 73 74 65 6d 2e 53 65 63 75 72 >. System.Secur<
69 74 79 2e 50 65 72 6d 69 73 73 69 6f 6e 73 2e >ity.Permissions.<
53 65 63 75 72 69 74 79 50 65 72 6d 69 73 73 69 >SecurityPermissi<
6f 6e 41 74 74 72 69 62 75 74 65 2c 20 6d 73 63 >onAttribute, msc<
6f 72 6c 69 62 2c 20 56 65 72 73 69 6f 6e 3d 32 >orlib, Version=2<
2e 30 2e 30 2e 30 2c 20 43 75 6c 74 75 72 65 3d >.0.0.0, Culture=<
6e 65 75 74 72 61 6c 2c 20 50 75 62 6c 69 63 4b >neutral, PublicK<
65 79 54 6f 6b 65 6e 3d 62 37 37 61 35 63 35 36 >eyToken=b77a5c56<
31 39 33 34 65 30 38 39 12 01 54 02 0d 55 6e 6d >1934e089 T Unm<
61 6e 61 67 65 64 43 6f 64 65 01 >anagedCode <
Once again, look at the end of the counted string for the attribute and you can see the 12 01
followed by the named argument list (a list of one item). I expected this to be 01 00
, a 16-bit little endian 1 for the number of named arguments.
Based on this, I am assuming that the second byte after the counted string is the named parameter count but I still don't understand what that first byte is (0x01 in the first example, 0x12 in the next).
If I add a second named attribute the first byte changes to a 26, if I add a third named attribute it changes to a 33. I don't see an obvious pattern to the numbers other than the fact that they are increasing.
I am asking this question because I am attempting to build a PermissionSet blob by hand (I am writing a CLR profiler) and I need to know what to put in that byte.
I think you are correct in your dismay, I remember this from my previous experience with the named parameters - the
NumNamed
was implemented as a compressed int instead of int16 stated in the spec, and unlike the example given §VI.B.3. I don't know if this has changed in subsequent .NET 3.0+ implementations.For the PermissionSet you are looking for,
The
12 01
is the little endian integer "giving the number of properties that follow". One named property, and a total length of 18 (in decimal, inclusive).This total length is the pattern that you were looking for, but beware since I think this length is optional and sometimes the compiler manages to pack the number of properties in the preceding int16, discarding the length. You'll have to experiment with a different number of attributes to make sure you are correctly parsing all cases.