summaryrefslogtreecommitdiff
path: root/src/vm/invokeutil.h
blob: ec8114f76a191dc4f670412ebc61d0cd16a78e6a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//

//
////////////////////////////////////////////////////////////////////////////////
// This module defines a Utility Class used by reflection
//
//  

////////////////////////////////////////////////////////////////////////////////


#ifndef __INVOKEUTIL_H__
#define __INVOKEUTIL_H__

// The following class represents the value class
#include <pshpack1.h>

struct InterfaceMapData
{
    REFLECTCLASSBASEREF     m_targetType;
    REFLECTCLASSBASEREF     m_interfaceType;
    PTRARRAYREF             m_targetMethods;
    PTRARRAYREF             m_interfaceMethods;
};

// Calling Conventions
// NOTE: These are defined in CallingConventions.cs They must match up.
#define Standard_CC     0x0001
#define VarArgs_CC      0x0002
#define Any_CC          (Standard_CC | VarArgs_CC)

#define PRIMITIVE_TABLE_SIZE  ELEMENT_TYPE_STRING
#define PT_Primitive    0x01000000

// Define the copy back constants.
#define COPYBACK_PRIMITIVE      1
#define COPYBACK_OBJECTREF      2
#define COPYBACK_VALUECLASS     3

#include <poppack.h>

class ReflectMethodList;
class ArgDestination;

// Structure used to track security access checks efficiently when applied
// across a range of methods, fields etc.
//
class RefSecContext : public AccessCheckContext
{
public:
    RefSecContext(AccessCheckOptions::AccessCheckType accessCheckType)
        : m_fCheckedCaller(false),
          m_fCheckedPerm(false),
          m_fCallerHasPerm(false),
          m_pCaller(NULL),
          m_pCallerDomain(NULL),
          m_accessCheckType(accessCheckType)
    {
        LIMITED_METHOD_CONTRACT;
    }

    virtual MethodTable* GetCallerMT();
    virtual MethodDesc* GetCallerMethod();
    virtual Assembly* GetCallerAssembly();
    virtual bool IsCalledFromInterop();
    
    AccessCheckOptions::AccessCheckType GetAccessCheckType() const
    {
        LIMITED_METHOD_CONTRACT;
        return m_accessCheckType;
    }

    AppDomain* GetCallerDomain();

private:    
    bool            m_fCheckedCaller;
    bool            m_fCheckedPerm;
    bool            m_fCallerHasPerm;
	
    
    // @review GENERICS: 
    // These method descriptors may be shared between compatible instantiations
    // Check that this does not open any security holes
    MethodDesc*     m_pCaller;
    AppDomain*      m_pCallerDomain;

    AccessCheckOptions::AccessCheckType m_accessCheckType;

    void FindCaller();
};

// This class abstracts the functionality which creats the
//  parameters on the call stack and deals with the return type
//  inside reflection.
//
class InvokeUtil
{

public:
    static void CopyArg(TypeHandle th, OBJECTREF *obj, ArgDestination *argDest);
   
    // Given a type, this routine will convert an return value representing that
    //  type into an ObjectReference.  If the type is a primitive, the 
    //  value is wrapped in one of the Value classes.
    static OBJECTREF CreateObject(TypeHandle th, void * pValue);

    // This is a special purpose Exception creation function.  It
    //  creates the TargetInvocationExeption placing the passed
    //  exception into it.
    static OBJECTREF CreateTargetExcept(OBJECTREF* except);

    // This is a special purpose Exception creation function.  It
    //  creates the ReflectionClassLoadException placing the passed
    //  classes array and exception array into it.
    static OBJECTREF CreateClassLoadExcept(OBJECTREF* classes,OBJECTREF* except);

    // Validate that the field can be widened for Set
    static void ValidField(TypeHandle th, OBJECTREF* value);

    // ChangeType
    // This method will invoke the Binder change type method on the object
    //  binder -- The Binder object
    //  srcObj -- The source object to be changed
    //  th -- The TypeHandel of the target type
    //  locale -- The locale passed to the class.
    static OBJECTREF ChangeType(OBJECTREF binder,OBJECTREF srcObj,TypeHandle th,OBJECTREF locale);

    // CreatePrimitiveValue
    // This routine will validate the object and then place the value into 
    //  the destination
    //  dstType -- The type of the destination
    //  srcType -- The type of the source
    //  srcObj -- The Object containing the primitive value.
    //  pDst -- poiner to the destination
    static void CreatePrimitiveValue(CorElementType dstType, CorElementType srcType, OBJECTREF srcObj, ARG_SLOT* pDst);

    // CreatePrimitiveValue
    // This routine will validate the object and then place the value into 
    //  the destination
    //  dstType -- The type of the destination
    //  srcType -- The type of the source
    //  pSrc -- pointer to source data.
    //  pSrcMT - MethodTable of source type
    //  pDst -- poiner to the destination
    static void CreatePrimitiveValue(CorElementType dstType,CorElementType srcType,
        void *pSrc, MethodTable *pSrcMT, ARG_SLOT* pDst);

    // IsPrimitiveType
    // This method will verify the passed in type is a primitive or not
    //	type -- the CorElementType to check for
    inline static DWORD IsPrimitiveType(const CorElementType type)
    {
        LIMITED_METHOD_CONTRACT;
        
        if (type >= PRIMITIVE_TABLE_SIZE)
        {
            if (ELEMENT_TYPE_I==type || ELEMENT_TYPE_U==type)
            {
                return TRUE;
            }
            return 0;
        }

        return (PT_Primitive & PrimitiveAttributes[type]);
    }

    static BOOL IsVoidPtr(TypeHandle th);

    // CanPrimitiveWiden
    // This method determines if the srcType and be widdened without loss to the destType
    //  destType -- The target type
    //  srcType -- The source type.
    inline static DWORD CanPrimitiveWiden(const CorElementType destType, const CorElementType srcType)
    {
        LIMITED_METHOD_CONTRACT;
        
        if (destType >= PRIMITIVE_TABLE_SIZE || srcType >= PRIMITIVE_TABLE_SIZE)
        {
            if ((ELEMENT_TYPE_I==destType && ELEMENT_TYPE_I==srcType) ||
                (ELEMENT_TYPE_U==destType && ELEMENT_TYPE_U==srcType))
            {
                return TRUE;
            }
            return 0;
        }
        return ((1 << destType) & PrimitiveAttributes[srcType]);
    }

    // Field Stuff.  The following stuff deals with fields making it possible
    //  to set/get field values on objects

    // SetValidField
    // Given an target object, a value object and a field this method will set the field
    //  on the target object.  The field must be validate before calling this.
    static void SetValidField(CorElementType fldType, TypeHandle fldTH, FieldDesc* pField, OBJECTREF* target, OBJECTREF* value, TypeHandle declaringType, CLR_BOOL *pDomainInitialized);

    static OBJECTREF GetFieldValue(FieldDesc* pField, TypeHandle fieldType, OBJECTREF* target, TypeHandle declaringType, CLR_BOOL *pDomainInitialized);

    // ValidateObjectTarget
    // This method will validate the Object/Target relationship
    //  is correct.  It throws an exception if this is not the case.
    static void ValidateObjectTarget(FieldDesc* pField,TypeHandle fldType,OBJECTREF *target);

    // Create reflection pointer wrapper
    static OBJECTREF CreatePointer(TypeHandle th, void * p);

    static TypeHandle GetPointerType(OBJECTREF pObj);
    static void* GetPointerValue(OBJECTREF pObj);
    static void* GetIntPtrValue(OBJECTREF pObj);

    // Check accessability of a type or nested type.
    static void CanAccessClass(RefSecContext*   pCtx,
                               MethodTable*     pClass,
                               BOOL             checkAccessForImplicitValueTypeCtor = FALSE);

    static void CanAccessMethod(MethodDesc*     pMeth,
                                MethodTable*    pParentMT,
                                MethodTable*    pInstanceMT,
                                RefSecContext*  pSCtx,
                                BOOL            fCriticalToFullDemand = TRUE,
                                BOOL            checkSkipVer = FALSE);

    // Check accessability of a field 
    static void CanAccessField(RefSecContext*   pCtx,
                               MethodTable*     pTargetMT,
                               MethodTable*     pInstanceMT,
                               FieldDesc*       pTargetField);

    //
    // Check to see if the target of a reflection operation is on a remote object
    //
    // Arguments:
    //    pDesc     - item being accessed (MethodDesc, FieldDesc, etc)
    //    pTargetMT - object being reflected on

    template <typename T>
    static bool IsTargetRemoted(T *pDesc, MethodTable *pTargetMT)
    {
        CONTRACTL
        {
            THROWS;
            GC_TRIGGERS;
            MODE_ANY;
            PRECONDITION(CheckPointer(pDesc));
        }
        CONTRACTL_END;

        if (pDesc->IsStatic())
            return FALSE;

        if (pTargetMT == NULL)
            return FALSE;

        return FALSE;
    }

    static AccessCheckOptions::AccessCheckType GetInvocationAccessCheckType(BOOL targetRemoted = FALSE);

    static bool IsDangerousMethod(MethodDesc *pMD);

private:
    // Check accessability of a type or nested type.
    static void CheckAccessClass(RefSecContext *pCtx,
                                 MethodTable *pClass,
                                 BOOL checkAccessForImplicitValueTypeCtor = FALSE);

public:
    // Check accessability of a method
    static void CheckAccessMethod(RefSecContext       *pCtx,
                                  MethodTable         *pTargetMT,
                                  MethodTable         *pInstanceMT,
                                  MethodDesc          *pTargetMethod);

private:
    // Check accessability of a field 
    static void CheckAccessField(RefSecContext       *pCtx,
                                 MethodTable         *pTargetMT,
                                 MethodTable         *pInstanceMT,
                                 FieldDesc           *pTargetField);

    // Check accessability of a field or method.
    // pTargetMD should be NULL for a field, and may be NULL for a method.
    // If checking a generic method with a method instantiation, 
    // the method should be in as pOptionalTargetMethod so
    // that the accessibilty of its type arguments is checked too.
    static void CheckAccess(RefSecContext               *pCtx,
                            MethodTable                 *pTargetMT,
                            MethodTable                 *pInstanceMT,
                            MethodDesc                  *pTargetMD,
                            FieldDesc                   *pTargetField,
                            const AccessCheckOptions    &accessCheckOptions);

    static void* CreateByRef(TypeHandle dstTh,CorElementType srcType, TypeHandle srcTH,OBJECTREF srcObj, OBJECTREF *pIncomingObj);

    // GetBoxedObject
    // Given an address of a primitve type, this will box that data...
    static OBJECTREF GetBoxedObject(TypeHandle th,void* pData);

private:
    // The Attributes Table
    // This constructs a table of legal widening operations
    //  for the primitive types.
    static DWORD const PrimitiveAttributes[PRIMITIVE_TABLE_SIZE];
};


#endif // __INVOKEUTIL_H__