@@ -22,6 +22,7 @@ public CustomAttributeDecoder(ICustomAttributeTypeProvider<TType> provider, Meta
22
22
public CustomAttributeValue < TType > DecodeValue ( EntityHandle constructor , BlobHandle value )
23
23
{
24
24
BlobHandle signature ;
25
+ BlobHandle attributeOwningTypeSpec = default ;
25
26
switch ( constructor . Kind )
26
27
{
27
28
case HandleKind . MethodDefinition :
@@ -32,6 +33,13 @@ public CustomAttributeValue<TType> DecodeValue(EntityHandle constructor, BlobHan
32
33
case HandleKind . MemberReference :
33
34
MemberReference reference = _reader . GetMemberReference ( ( MemberReferenceHandle ) constructor ) ;
34
35
signature = reference . Signature ;
36
+
37
+ // If this is a generic attribute, we'll need its instantiation to decode the signatures
38
+ if ( reference . Parent . Kind == HandleKind . TypeSpecification )
39
+ {
40
+ TypeSpecification genericOwner = _reader . GetTypeSpecification ( ( TypeSpecificationHandle ) reference . Parent ) ;
41
+ attributeOwningTypeSpec = genericOwner . Signature ;
42
+ }
35
43
break ;
36
44
37
45
default :
@@ -60,12 +68,38 @@ public CustomAttributeValue<TType> DecodeValue(EntityHandle constructor, BlobHan
60
68
throw new BadImageFormatException ( ) ;
61
69
}
62
70
63
- ImmutableArray < CustomAttributeTypedArgument < TType > > fixedArguments = DecodeFixedArguments ( ref signatureReader , ref valueReader , parameterCount ) ;
71
+ BlobReader genericContextReader = default ;
72
+ if ( ! attributeOwningTypeSpec . IsNil )
73
+ {
74
+ // If this is a generic attribute, grab the instantiation arguments so that we can
75
+ // interpret the constructor signature, should it refer to the generic context.
76
+ genericContextReader = _reader . GetBlobReader ( attributeOwningTypeSpec ) ;
77
+ if ( genericContextReader . ReadSignatureTypeCode ( ) == SignatureTypeCode . GenericTypeInstance )
78
+ {
79
+ int kind = genericContextReader . ReadCompressedInteger ( ) ;
80
+ if ( kind != ( int ) SignatureTypeKind . Class && kind != ( int ) SignatureTypeKind . ValueType )
81
+ {
82
+ throw new BadImageFormatException ( ) ;
83
+ }
84
+
85
+ genericContextReader . ReadTypeHandle ( ) ;
86
+
87
+ // At this point, the reader points to the "GenArgCount Type Type*" part of the signature.
88
+ }
89
+ else
90
+ {
91
+ // Some other invalid TypeSpec. Don't accidentally allow resolving generic parameters
92
+ // from the constructor signature into a broken blob.
93
+ genericContextReader = default ;
94
+ }
95
+ }
96
+
97
+ ImmutableArray < CustomAttributeTypedArgument < TType > > fixedArguments = DecodeFixedArguments ( ref signatureReader , ref valueReader , parameterCount , genericContextReader ) ;
64
98
ImmutableArray < CustomAttributeNamedArgument < TType > > namedArguments = DecodeNamedArguments ( ref valueReader ) ;
65
99
return new CustomAttributeValue < TType > ( fixedArguments , namedArguments ) ;
66
100
}
67
101
68
- private ImmutableArray < CustomAttributeTypedArgument < TType > > DecodeFixedArguments ( ref BlobReader signatureReader , ref BlobReader valueReader , int count )
102
+ private ImmutableArray < CustomAttributeTypedArgument < TType > > DecodeFixedArguments ( ref BlobReader signatureReader , ref BlobReader valueReader , int count , BlobReader genericContextReader )
69
103
{
70
104
if ( count == 0 )
71
105
{
@@ -76,7 +110,7 @@ private ImmutableArray<CustomAttributeTypedArgument<TType>> DecodeFixedArguments
76
110
77
111
for ( int i = 0 ; i < count ; i ++ )
78
112
{
79
- ArgumentTypeInfo info = DecodeFixedArgumentType ( ref signatureReader ) ;
113
+ ArgumentTypeInfo info = DecodeFixedArgumentType ( ref signatureReader , genericContextReader ) ;
80
114
arguments . Add ( DecodeArgument ( ref valueReader , info ) ) ;
81
115
}
82
116
@@ -124,7 +158,7 @@ private struct ArgumentTypeInfo
124
158
// better perf-wise, but even more important is that we can't actually reason about
125
159
// a method signature with opaque TType values without adding some unnecessary chatter
126
160
// with the provider.
127
- private ArgumentTypeInfo DecodeFixedArgumentType ( ref BlobReader signatureReader , bool isElementType = false )
161
+ private ArgumentTypeInfo DecodeFixedArgumentType ( ref BlobReader signatureReader , BlobReader genericContextReader , bool isElementType = false )
128
162
{
129
163
SignatureTypeCode signatureTypeCode = signatureReader . ReadSignatureTypeCode ( ) ;
130
164
@@ -170,12 +204,33 @@ private ArgumentTypeInfo DecodeFixedArgumentType(ref BlobReader signatureReader,
170
204
throw new BadImageFormatException ( ) ;
171
205
}
172
206
173
- var elementInfo = DecodeFixedArgumentType ( ref signatureReader , isElementType : true ) ;
207
+ var elementInfo = DecodeFixedArgumentType ( ref signatureReader , genericContextReader , isElementType : true ) ;
174
208
info . ElementType = elementInfo . Type ;
175
209
info . ElementTypeCode = elementInfo . TypeCode ;
176
210
info . Type = _provider . GetSZArrayType ( info . ElementType ) ;
177
211
break ;
178
212
213
+ case SignatureTypeCode . GenericTypeParameter :
214
+ if ( genericContextReader . Length == 0 )
215
+ {
216
+ throw new BadImageFormatException ( ) ;
217
+ }
218
+
219
+ int parameterIndex = signatureReader . ReadCompressedInteger ( ) ;
220
+ int numGenericParameters = genericContextReader . ReadCompressedInteger ( ) ;
221
+ if ( parameterIndex >= numGenericParameters )
222
+ {
223
+ throw new BadImageFormatException ( ) ;
224
+ }
225
+
226
+ while ( parameterIndex > 0 )
227
+ {
228
+ SkipType ( ref genericContextReader ) ;
229
+ parameterIndex -- ;
230
+ }
231
+
232
+ return DecodeFixedArgumentType ( ref genericContextReader , default , isElementType ) ;
233
+
179
234
default :
180
235
throw new BadImageFormatException ( ) ;
181
236
}
@@ -363,5 +418,95 @@ private TType GetTypeFromHandle(EntityHandle handle) =>
363
418
HandleKind . TypeReference => _provider . GetTypeFromReference ( _reader , ( TypeReferenceHandle ) handle , 0 ) ,
364
419
_ => throw new BadImageFormatException ( SR . NotTypeDefOrRefHandle ) ,
365
420
} ;
421
+
422
+ private static void SkipType ( ref BlobReader blobReader )
423
+ {
424
+ int typeCode = blobReader . ReadCompressedInteger ( ) ;
425
+
426
+ switch ( typeCode )
427
+ {
428
+ case ( int ) SignatureTypeCode . Boolean :
429
+ case ( int ) SignatureTypeCode . Char :
430
+ case ( int ) SignatureTypeCode . SByte :
431
+ case ( int ) SignatureTypeCode . Byte :
432
+ case ( int ) SignatureTypeCode . Int16 :
433
+ case ( int ) SignatureTypeCode . UInt16 :
434
+ case ( int ) SignatureTypeCode . Int32 :
435
+ case ( int ) SignatureTypeCode . UInt32 :
436
+ case ( int ) SignatureTypeCode . Int64 :
437
+ case ( int ) SignatureTypeCode . UInt64 :
438
+ case ( int ) SignatureTypeCode . Single :
439
+ case ( int ) SignatureTypeCode . Double :
440
+ case ( int ) SignatureTypeCode . IntPtr :
441
+ case ( int ) SignatureTypeCode . UIntPtr :
442
+ case ( int ) SignatureTypeCode . Object :
443
+ case ( int ) SignatureTypeCode . String :
444
+ case ( int ) SignatureTypeCode . Void :
445
+ case ( int ) SignatureTypeCode . TypedReference :
446
+ return ;
447
+
448
+ case ( int ) SignatureTypeCode . Pointer :
449
+ case ( int ) SignatureTypeCode . ByReference :
450
+ case ( int ) SignatureTypeCode . Pinned :
451
+ case ( int ) SignatureTypeCode . SZArray :
452
+ SkipType ( ref blobReader ) ;
453
+ return ;
454
+
455
+ case ( int ) SignatureTypeCode . FunctionPointer :
456
+ SignatureHeader header = blobReader . ReadSignatureHeader ( ) ;
457
+ if ( header . IsGeneric )
458
+ {
459
+ blobReader . ReadCompressedInteger ( ) ; // arity
460
+ }
461
+
462
+ int paramCount = blobReader . ReadCompressedInteger ( ) ;
463
+ SkipType ( ref blobReader ) ;
464
+ for ( int i = 0 ; i < paramCount ; i ++ )
465
+ SkipType ( ref blobReader ) ;
466
+ return ;
467
+
468
+ case ( int ) SignatureTypeCode . Array :
469
+ SkipType ( ref blobReader ) ;
470
+ blobReader . ReadCompressedInteger ( ) ; // rank
471
+ int boundsCount = blobReader . ReadCompressedInteger ( ) ;
472
+ for ( int i = 0 ; i < boundsCount ; i ++ )
473
+ {
474
+ blobReader . ReadCompressedInteger ( ) ;
475
+ }
476
+ int lowerBoundsCount = blobReader . ReadCompressedInteger ( ) ;
477
+ for ( int i = 0 ; i < lowerBoundsCount ; i ++ )
478
+ {
479
+ blobReader . ReadCompressedSignedInteger ( ) ;
480
+ }
481
+ return ;
482
+
483
+ case ( int ) SignatureTypeCode . RequiredModifier :
484
+ case ( int ) SignatureTypeCode . OptionalModifier :
485
+ blobReader . ReadTypeHandle ( ) ;
486
+ SkipType ( ref blobReader ) ;
487
+ return ;
488
+
489
+ case ( int ) SignatureTypeCode . GenericTypeInstance :
490
+ SkipType ( ref blobReader ) ;
491
+ int count = blobReader . ReadCompressedInteger ( ) ;
492
+ for ( int i = 0 ; i < count ; i ++ )
493
+ {
494
+ SkipType ( ref blobReader ) ;
495
+ }
496
+ return ;
497
+
498
+ case ( int ) SignatureTypeCode . GenericTypeParameter :
499
+ blobReader . ReadCompressedInteger ( ) ;
500
+ return ;
501
+
502
+ case ( int ) SignatureTypeKind . Class :
503
+ case ( int ) SignatureTypeKind . ValueType :
504
+ SkipType ( ref blobReader ) ;
505
+ break ;
506
+
507
+ default :
508
+ throw new BadImageFormatException ( ) ;
509
+ }
510
+ }
366
511
}
367
512
}
0 commit comments