1 | // Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team |
---|
2 | // |
---|
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this |
---|
4 | // software and associated documentation files (the "Software"), to deal in the Software |
---|
5 | // without restriction, including without limitation the rights to use, copy, modify, merge, |
---|
6 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons |
---|
7 | // to whom the Software is furnished to do so, subject to the following conditions: |
---|
8 | // |
---|
9 | // The above copyright notice and this permission notice shall be included in all copies or |
---|
10 | // substantial portions of the Software. |
---|
11 | // |
---|
12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, |
---|
13 | // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR |
---|
14 | // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE |
---|
15 | // FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
---|
16 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
---|
17 | // DEALINGS IN THE SOFTWARE. |
---|
18 | |
---|
19 | using System; |
---|
20 | using System.Collections.Generic; |
---|
21 | using System.Diagnostics; |
---|
22 | using ICSharpCode.NRefactory.Semantics; |
---|
23 | |
---|
24 | namespace ICSharpCode.NRefactory.TypeSystem.Implementation |
---|
25 | { |
---|
26 | [Serializable] |
---|
27 | public sealed class UnresolvedSecurityDeclarationBlob |
---|
28 | { |
---|
29 | static readonly ITypeReference securityActionTypeReference = typeof(System.Security.Permissions.SecurityAction).ToTypeReference(); |
---|
30 | static readonly ITypeReference permissionSetAttributeTypeReference = typeof(System.Security.Permissions.PermissionSetAttribute).ToTypeReference(); |
---|
31 | |
---|
32 | readonly IConstantValue securityAction; |
---|
33 | readonly byte[] blob; |
---|
34 | readonly IList<IUnresolvedAttribute> unresolvedAttributes = new List<IUnresolvedAttribute>(); |
---|
35 | |
---|
36 | public UnresolvedSecurityDeclarationBlob(int securityAction, byte[] blob) |
---|
37 | { |
---|
38 | BlobReader reader = new BlobReader(blob, null); |
---|
39 | this.securityAction = new SimpleConstantValue(securityActionTypeReference, securityAction); |
---|
40 | this.blob = blob; |
---|
41 | if (reader.ReadByte() == '.') { |
---|
42 | // binary attribute |
---|
43 | uint attributeCount = reader.ReadCompressedUInt32(); |
---|
44 | for (uint i = 0; i < attributeCount; i++) { |
---|
45 | unresolvedAttributes.Add(new UnresolvedSecurityAttribute(this, (int)i)); |
---|
46 | } |
---|
47 | } else { |
---|
48 | // for backward compatibility with .NET 1.0: XML-encoded attribute |
---|
49 | var attr = new DefaultUnresolvedAttribute(permissionSetAttributeTypeReference); |
---|
50 | attr.ConstructorParameterTypes.Add(securityActionTypeReference); |
---|
51 | attr.PositionalArguments.Add(this.securityAction); |
---|
52 | string xml = System.Text.Encoding.Unicode.GetString(blob); |
---|
53 | attr.AddNamedPropertyArgument("XML", new SimpleConstantValue(KnownTypeReference.String, xml)); |
---|
54 | unresolvedAttributes.Add(attr); |
---|
55 | } |
---|
56 | } |
---|
57 | |
---|
58 | public IList<IUnresolvedAttribute> UnresolvedAttributes { |
---|
59 | get { return unresolvedAttributes; } |
---|
60 | } |
---|
61 | |
---|
62 | public IList<IAttribute> Resolve(IAssembly currentAssembly) |
---|
63 | { |
---|
64 | // TODO: make this a per-assembly cache |
---|
65 | // CacheManager cache = currentAssembly.Compilation.CacheManager; |
---|
66 | // IList<IAttribute> result = (IList<IAttribute>)cache.GetShared(this); |
---|
67 | // if (result != null) |
---|
68 | // return result; |
---|
69 | |
---|
70 | ITypeResolveContext context = new SimpleTypeResolveContext(currentAssembly); |
---|
71 | BlobReader reader = new BlobReader(blob, currentAssembly); |
---|
72 | if (reader.ReadByte() != '.') { |
---|
73 | // should not use UnresolvedSecurityDeclaration for XML secdecls |
---|
74 | throw new InvalidOperationException(); |
---|
75 | } |
---|
76 | ResolveResult securityActionRR = securityAction.Resolve(context); |
---|
77 | uint attributeCount = reader.ReadCompressedUInt32(); |
---|
78 | IAttribute[] attributes = new IAttribute[attributeCount]; |
---|
79 | try { |
---|
80 | ReadSecurityBlob(reader, attributes, context, securityActionRR); |
---|
81 | } catch (NotSupportedException ex) { |
---|
82 | // ignore invalid blobs |
---|
83 | Debug.WriteLine(ex.ToString()); |
---|
84 | } |
---|
85 | for (int i = 0; i < attributes.Length; i++) { |
---|
86 | if (attributes[i] == null) |
---|
87 | attributes[i] = new CecilResolvedAttribute(context, SpecialType.UnknownType); |
---|
88 | } |
---|
89 | return attributes; |
---|
90 | // return (IList<IAttribute>)cache.GetOrAddShared(this, attributes); |
---|
91 | } |
---|
92 | |
---|
93 | void ReadSecurityBlob(BlobReader reader, IAttribute[] attributes, ITypeResolveContext context, ResolveResult securityActionRR) |
---|
94 | { |
---|
95 | for (int i = 0; i < attributes.Length; i++) { |
---|
96 | string attributeTypeName = reader.ReadSerString(); |
---|
97 | ITypeReference attributeTypeRef = ReflectionHelper.ParseReflectionName(attributeTypeName); |
---|
98 | IType attributeType = attributeTypeRef.Resolve(context); |
---|
99 | |
---|
100 | reader.ReadCompressedUInt32(); // ?? |
---|
101 | // The specification seems to be incorrect here, so I'm using the logic from Cecil instead. |
---|
102 | uint numNamed = reader.ReadCompressedUInt32(); |
---|
103 | |
---|
104 | var namedArgs = new List<KeyValuePair<IMember, ResolveResult>>((int)numNamed); |
---|
105 | for (uint j = 0; j < numNamed; j++) { |
---|
106 | var namedArg = reader.ReadNamedArg(attributeType); |
---|
107 | if (namedArg.Key != null) |
---|
108 | namedArgs.Add(namedArg); |
---|
109 | |
---|
110 | } |
---|
111 | attributes[i] = new DefaultAttribute( |
---|
112 | attributeType, |
---|
113 | positionalArguments: new ResolveResult[] { securityActionRR }, |
---|
114 | namedArguments: namedArgs); |
---|
115 | } |
---|
116 | } |
---|
117 | } |
---|
118 | |
---|
119 | [Serializable] |
---|
120 | sealed class UnresolvedSecurityAttribute : IUnresolvedAttribute, ISupportsInterning |
---|
121 | { |
---|
122 | readonly UnresolvedSecurityDeclarationBlob secDecl; |
---|
123 | readonly int index; |
---|
124 | |
---|
125 | public UnresolvedSecurityAttribute(UnresolvedSecurityDeclarationBlob secDecl, int index) |
---|
126 | { |
---|
127 | Debug.Assert(secDecl != null); |
---|
128 | this.secDecl = secDecl; |
---|
129 | this.index = index; |
---|
130 | } |
---|
131 | |
---|
132 | DomRegion IUnresolvedAttribute.Region { |
---|
133 | get { return DomRegion.Empty; } |
---|
134 | } |
---|
135 | |
---|
136 | IAttribute IUnresolvedAttribute.CreateResolvedAttribute(ITypeResolveContext context) |
---|
137 | { |
---|
138 | return secDecl.Resolve(context.CurrentAssembly)[index]; |
---|
139 | } |
---|
140 | |
---|
141 | int ISupportsInterning.GetHashCodeForInterning() |
---|
142 | { |
---|
143 | return index ^ secDecl.GetHashCode(); |
---|
144 | } |
---|
145 | |
---|
146 | bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) |
---|
147 | { |
---|
148 | UnresolvedSecurityAttribute attr = other as UnresolvedSecurityAttribute; |
---|
149 | return attr != null && index == attr.index && secDecl == attr.secDecl; |
---|
150 | } |
---|
151 | } |
---|
152 | } |
---|