PageRenderTime 937ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 2ms

/mono/metadata/verify.c

https://bitbucket.org/danipen/mono
C | 6374 lines | 4891 code | 987 blank | 496 comment | 1403 complexity | f77ac059fe004a60662c03edb9e66b82 MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * verify.c:
  3. *
  4. * Author:
  5. * Mono Project (http://www.mono-project.com)
  6. *
  7. * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
  8. * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
  9. * Copyright 2011 Rodrigo Kumpera
  10. */
  11. #include <config.h>
  12. #include <mono/metadata/object-internals.h>
  13. #include <mono/metadata/verify.h>
  14. #include <mono/metadata/verify-internals.h>
  15. #include <mono/metadata/opcodes.h>
  16. #include <mono/metadata/tabledefs.h>
  17. #include <mono/metadata/reflection.h>
  18. #include <mono/metadata/debug-helpers.h>
  19. #include <mono/metadata/mono-endian.h>
  20. #include <mono/metadata/metadata.h>
  21. #include <mono/metadata/metadata-internals.h>
  22. #include <mono/metadata/class-internals.h>
  23. #include <mono/metadata/security-manager.h>
  24. #include <mono/metadata/security-core-clr.h>
  25. #include <mono/metadata/tokentype.h>
  26. #include <mono/metadata/mono-basic-block.h>
  27. #include <mono/metadata/attrdefs.h>
  28. #include <mono/utils/mono-counters.h>
  29. #include <mono/utils/monobitset.h>
  30. #include <string.h>
  31. #include <signal.h>
  32. #include <ctype.h>
  33. static MiniVerifierMode verifier_mode = MONO_VERIFIER_MODE_OFF;
  34. static gboolean verify_all = FALSE;
  35. /*
  36. * Set the desired level of checks for the verfier.
  37. *
  38. */
  39. void
  40. mono_verifier_set_mode (MiniVerifierMode mode)
  41. {
  42. verifier_mode = mode;
  43. }
  44. void
  45. mono_verifier_enable_verify_all ()
  46. {
  47. verify_all = TRUE;
  48. }
  49. #ifndef DISABLE_VERIFIER
  50. /*
  51. * Pull the list of opcodes
  52. */
  53. #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
  54. a = i,
  55. enum {
  56. #include "mono/cil/opcode.def"
  57. LAST = 0xff
  58. };
  59. #undef OPDEF
  60. #ifdef MONO_VERIFIER_DEBUG
  61. #define VERIFIER_DEBUG(code) do { code } while (0)
  62. #else
  63. #define VERIFIER_DEBUG(code)
  64. #endif
  65. //////////////////////////////////////////////////////////////////
  66. #define IS_STRICT_MODE(ctx) (((ctx)->level & MONO_VERIFY_NON_STRICT) == 0)
  67. #define IS_FAIL_FAST_MODE(ctx) (((ctx)->level & MONO_VERIFY_FAIL_FAST) == MONO_VERIFY_FAIL_FAST)
  68. #define IS_SKIP_VISIBILITY(ctx) (((ctx)->level & MONO_VERIFY_SKIP_VISIBILITY) == MONO_VERIFY_SKIP_VISIBILITY)
  69. #define IS_REPORT_ALL_ERRORS(ctx) (((ctx)->level & MONO_VERIFY_REPORT_ALL_ERRORS) == MONO_VERIFY_REPORT_ALL_ERRORS)
  70. #define CLEAR_PREFIX(ctx, prefix) do { (ctx)->prefix_set &= ~(prefix); } while (0)
  71. #define ADD_VERIFY_INFO(__ctx, __msg, __status, __exception) \
  72. do { \
  73. MonoVerifyInfoExtended *vinfo = g_new (MonoVerifyInfoExtended, 1); \
  74. vinfo->info.status = __status; \
  75. vinfo->info.message = ( __msg ); \
  76. vinfo->exception_type = (__exception); \
  77. (__ctx)->list = g_slist_prepend ((__ctx)->list, vinfo); \
  78. } while (0)
  79. //TODO support MONO_VERIFY_REPORT_ALL_ERRORS
  80. #define ADD_VERIFY_ERROR(__ctx, __msg) \
  81. do { \
  82. ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, MONO_EXCEPTION_INVALID_PROGRAM); \
  83. (__ctx)->valid = 0; \
  84. } while (0)
  85. #define CODE_NOT_VERIFIABLE(__ctx, __msg) \
  86. do { \
  87. if ((__ctx)->verifiable || IS_REPORT_ALL_ERRORS (__ctx)) { \
  88. ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_NOT_VERIFIABLE, MONO_EXCEPTION_UNVERIFIABLE_IL); \
  89. (__ctx)->verifiable = 0; \
  90. if (IS_FAIL_FAST_MODE (__ctx)) \
  91. (__ctx)->valid = 0; \
  92. } \
  93. } while (0)
  94. #define ADD_VERIFY_ERROR2(__ctx, __msg, __exception) \
  95. do { \
  96. ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_ERROR, __exception); \
  97. (__ctx)->valid = 0; \
  98. } while (0)
  99. #define CODE_NOT_VERIFIABLE2(__ctx, __msg, __exception) \
  100. do { \
  101. if ((__ctx)->verifiable || IS_REPORT_ALL_ERRORS (__ctx)) { \
  102. ADD_VERIFY_INFO(__ctx, __msg, MONO_VERIFY_NOT_VERIFIABLE, __exception); \
  103. (__ctx)->verifiable = 0; \
  104. if (IS_FAIL_FAST_MODE (__ctx)) \
  105. (__ctx)->valid = 0; \
  106. } \
  107. } while (0)
  108. #define CHECK_ADD4_OVERFLOW_UN(a, b) ((guint32)(0xFFFFFFFFU) - (guint32)(b) < (guint32)(a))
  109. #define CHECK_ADD8_OVERFLOW_UN(a, b) ((guint64)(0xFFFFFFFFFFFFFFFFUL) - (guint64)(b) < (guint64)(a))
  110. #if SIZEOF_VOID_P == 4
  111. #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD4_OVERFLOW_UN(a, b)
  112. #else
  113. #define CHECK_ADDP_OVERFLOW_UN(a,b) CHECK_ADD8_OVERFLOW_UN(a, b)
  114. #endif
  115. #define ADDP_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADDP_OVERFLOW_UN (a, b))
  116. #define ADD_IS_GREATER_OR_OVF(a, b, c) (((a) + (b) > (c)) || CHECK_ADD4_OVERFLOW_UN (a, b))
  117. /*Flags to be used with ILCodeDesc::flags */
  118. enum {
  119. /*Instruction has not been processed.*/
  120. IL_CODE_FLAG_NOT_PROCESSED = 0,
  121. /*Instruction was decoded by mono_method_verify loop.*/
  122. IL_CODE_FLAG_SEEN = 1,
  123. /*Instruction was target of a branch or is at a protected block boundary.*/
  124. IL_CODE_FLAG_WAS_TARGET = 2,
  125. /*Used by stack_init to avoid double initialize each entry.*/
  126. IL_CODE_FLAG_STACK_INITED = 4,
  127. /*Used by merge_stacks to decide if it should just copy the eval stack.*/
  128. IL_CODE_STACK_MERGED = 8,
  129. /*This instruction is part of the delegate construction sequence, it cannot be target of a branch.*/
  130. IL_CODE_DELEGATE_SEQUENCE = 0x10,
  131. /*This is a delegate created from a ldftn to a non final virtual method*/
  132. IL_CODE_LDFTN_DELEGATE_NONFINAL_VIRTUAL = 0x20,
  133. /*This is a call to a non final virtual method*/
  134. IL_CODE_CALL_NONFINAL_VIRTUAL = 0x40,
  135. };
  136. typedef enum {
  137. RESULT_VALID,
  138. RESULT_UNVERIFIABLE,
  139. RESULT_INVALID
  140. } verify_result_t;
  141. typedef struct {
  142. MonoType *type;
  143. int stype;
  144. MonoMethod *method;
  145. } ILStackDesc;
  146. typedef struct {
  147. ILStackDesc *stack;
  148. guint16 size, max_size;
  149. guint16 flags;
  150. } ILCodeDesc;
  151. typedef struct {
  152. int max_args;
  153. int max_stack;
  154. int verifiable;
  155. int valid;
  156. int level;
  157. int code_size;
  158. ILCodeDesc *code;
  159. ILCodeDesc eval;
  160. MonoType **params;
  161. GSList *list;
  162. /*Allocated fnptr MonoType that should be freed by us.*/
  163. GSList *funptrs;
  164. /*Type dup'ed exception types from catch blocks.*/
  165. GSList *exception_types;
  166. int num_locals;
  167. MonoType **locals;
  168. /*TODO get rid of target here, need_merge in mono_method_verify and hoist the merging code in the branching code*/
  169. int target;
  170. guint32 ip_offset;
  171. MonoMethodSignature *signature;
  172. MonoMethodHeader *header;
  173. MonoGenericContext *generic_context;
  174. MonoImage *image;
  175. MonoMethod *method;
  176. /*This flag helps solving a corner case of delegate verification in that you cannot have a "starg 0"
  177. *on a method that creates a delegate for a non-final virtual method using ldftn*/
  178. gboolean has_this_store;
  179. /*This flag is used to control if the contructor of the parent class has been called.
  180. *If the this pointer is pushed on the eval stack and it's a reference type constructor and
  181. * super_ctor_called is false, the uninitialized flag is set on the pushed value.
  182. *
  183. * Poping an uninitialized this ptr from the eval stack is an unverifiable operation unless
  184. * the safe variant is used. Only a few opcodes can use it : dup, pop, ldfld, stfld and call to a constructor.
  185. */
  186. gboolean super_ctor_called;
  187. guint32 prefix_set;
  188. gboolean has_flags;
  189. MonoType *constrained_type;
  190. } VerifyContext;
  191. static void
  192. merge_stacks (VerifyContext *ctx, ILCodeDesc *from, ILCodeDesc *to, gboolean start, gboolean external);
  193. static int
  194. get_stack_type (MonoType *type);
  195. static gboolean
  196. mono_delegate_signature_equal (MonoMethodSignature *delegate_sig, MonoMethodSignature *method_sig, gboolean is_static_ldftn);
  197. static gboolean
  198. mono_class_is_valid_generic_instantiation (VerifyContext *ctx, MonoClass *klass);
  199. static gboolean
  200. mono_method_is_valid_generic_instantiation (VerifyContext *ctx, MonoMethod *method);
  201. static MonoGenericParam*
  202. verifier_get_generic_param_from_type (VerifyContext *ctx, MonoType *type);
  203. static gboolean
  204. verifier_class_is_assignable_from (MonoClass *target, MonoClass *candidate);
  205. //////////////////////////////////////////////////////////////////
  206. enum {
  207. TYPE_INV = 0, /* leave at 0. */
  208. TYPE_I4 = 1,
  209. TYPE_I8 = 2,
  210. TYPE_NATIVE_INT = 3,
  211. TYPE_R8 = 4,
  212. /* Used by operator tables to resolve pointer types (managed & unmanaged) and by unmanaged pointer types*/
  213. TYPE_PTR = 5,
  214. /* value types and classes */
  215. TYPE_COMPLEX = 6,
  216. /* Number of types, used to define the size of the tables*/
  217. TYPE_MAX = 6,
  218. /* Used by tables to signal that a result is not verifiable*/
  219. NON_VERIFIABLE_RESULT = 0x80,
  220. /*Mask used to extract just the type, excluding flags */
  221. TYPE_MASK = 0x0F,
  222. /* The stack type is a managed pointer, unmask the value to res */
  223. POINTER_MASK = 0x100,
  224. /*Stack type with the pointer mask*/
  225. RAW_TYPE_MASK = 0x10F,
  226. /* Controlled Mutability Manager Pointer */
  227. CMMP_MASK = 0x200,
  228. /* The stack type is a null literal*/
  229. NULL_LITERAL_MASK = 0x400,
  230. /**Used by ldarg.0 and family to let delegate verification happens.*/
  231. THIS_POINTER_MASK = 0x800,
  232. /**Signals that this is a boxed value type*/
  233. BOXED_MASK = 0x1000,
  234. /*This is an unitialized this ref*/
  235. UNINIT_THIS_MASK = 0x2000,
  236. };
  237. static const char* const
  238. type_names [TYPE_MAX + 1] = {
  239. "Invalid",
  240. "Int32",
  241. "Int64",
  242. "Native Int",
  243. "Float64",
  244. "Native Pointer",
  245. "Complex"
  246. };
  247. enum {
  248. PREFIX_UNALIGNED = 1,
  249. PREFIX_VOLATILE = 2,
  250. PREFIX_TAIL = 4,
  251. PREFIX_CONSTRAINED = 8,
  252. PREFIX_READONLY = 16
  253. };
  254. //////////////////////////////////////////////////////////////////
  255. #ifdef ENABLE_VERIFIER_STATS
  256. #define MEM_ALLOC(amt) do { allocated_memory += (amt); working_set += (amt); } while (0)
  257. #define MEM_FREE(amt) do { working_set -= (amt); } while (0)
  258. static int allocated_memory;
  259. static int working_set;
  260. static int max_allocated_memory;
  261. static int max_working_set;
  262. static int total_allocated_memory;
  263. static void
  264. finish_collect_stats (void)
  265. {
  266. max_allocated_memory = MAX (max_allocated_memory, allocated_memory);
  267. max_working_set = MAX (max_working_set, working_set);
  268. total_allocated_memory += allocated_memory;
  269. allocated_memory = working_set = 0;
  270. }
  271. static void
  272. init_verifier_stats (void)
  273. {
  274. static gboolean inited;
  275. if (!inited) {
  276. inited = TRUE;
  277. mono_counters_register ("Maximum memory allocated during verification", MONO_COUNTER_METADATA | MONO_COUNTER_INT, &max_allocated_memory);
  278. mono_counters_register ("Maximum memory used during verification", MONO_COUNTER_METADATA | MONO_COUNTER_INT, &max_working_set);
  279. mono_counters_register ("Total memory allocated for verification", MONO_COUNTER_METADATA | MONO_COUNTER_INT, &total_allocated_memory);
  280. }
  281. }
  282. #else
  283. #define MEM_ALLOC(amt) do {} while (0)
  284. #define MEM_FREE(amt) do { } while (0)
  285. #define finish_collect_stats()
  286. #define init_verifier_stats()
  287. #endif
  288. //////////////////////////////////////////////////////////////////
  289. /*Token validation macros and functions */
  290. #define IS_MEMBER_REF(token) (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF)
  291. #define IS_METHOD_DEF(token) (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
  292. #define IS_METHOD_SPEC(token) (mono_metadata_token_table (token) == MONO_TABLE_METHODSPEC)
  293. #define IS_FIELD_DEF(token) (mono_metadata_token_table (token) == MONO_TABLE_FIELD)
  294. #define IS_TYPE_REF(token) (mono_metadata_token_table (token) == MONO_TABLE_TYPEREF)
  295. #define IS_TYPE_DEF(token) (mono_metadata_token_table (token) == MONO_TABLE_TYPEDEF)
  296. #define IS_TYPE_SPEC(token) (mono_metadata_token_table (token) == MONO_TABLE_TYPESPEC)
  297. #define IS_METHOD_DEF_OR_REF_OR_SPEC(token) (IS_METHOD_DEF (token) || IS_MEMBER_REF (token) || IS_METHOD_SPEC (token))
  298. #define IS_TYPE_DEF_OR_REF_OR_SPEC(token) (IS_TYPE_DEF (token) || IS_TYPE_REF (token) || IS_TYPE_SPEC (token))
  299. #define IS_FIELD_DEF_OR_REF(token) (IS_FIELD_DEF (token) || IS_MEMBER_REF (token))
  300. /*
  301. * Verify if @token refers to a valid row on int's table.
  302. */
  303. static gboolean
  304. token_bounds_check (MonoImage *image, guint32 token)
  305. {
  306. if (image->dynamic)
  307. return mono_reflection_is_valid_dynamic_token ((MonoDynamicImage*)image, token);
  308. return image->tables [mono_metadata_token_table (token)].rows >= mono_metadata_token_index (token) && mono_metadata_token_index (token) > 0;
  309. }
  310. static MonoType *
  311. mono_type_create_fnptr_from_mono_method (VerifyContext *ctx, MonoMethod *method)
  312. {
  313. MonoType *res = g_new0 (MonoType, 1);
  314. MEM_ALLOC (sizeof (MonoType));
  315. //FIXME use mono_method_get_signature_full
  316. res->data.method = mono_method_signature (method);
  317. res->type = MONO_TYPE_FNPTR;
  318. ctx->funptrs = g_slist_prepend (ctx->funptrs, res);
  319. return res;
  320. }
  321. /*
  322. * mono_type_is_enum_type:
  323. *
  324. * Returns TRUE if @type is an enum type.
  325. */
  326. static gboolean
  327. mono_type_is_enum_type (MonoType *type)
  328. {
  329. if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
  330. return TRUE;
  331. if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
  332. return TRUE;
  333. return FALSE;
  334. }
  335. /*
  336. * mono_type_is_value_type:
  337. *
  338. * Returns TRUE if @type is named after @namespace.@name.
  339. *
  340. */
  341. static gboolean
  342. mono_type_is_value_type (MonoType *type, const char *namespace, const char *name)
  343. {
  344. return type->type == MONO_TYPE_VALUETYPE &&
  345. !strcmp (namespace, type->data.klass->name_space) &&
  346. !strcmp (name, type->data.klass->name);
  347. }
  348. /*
  349. * Returns TURE if @type is VAR or MVAR
  350. */
  351. static gboolean
  352. mono_type_is_generic_argument (MonoType *type)
  353. {
  354. return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
  355. }
  356. /*
  357. * mono_type_get_underlying_type_any:
  358. *
  359. * This functions is just like mono_type_get_underlying_type but it doesn't care if the type is byref.
  360. *
  361. * Returns the underlying type of @type regardless if it is byref or not.
  362. */
  363. static MonoType*
  364. mono_type_get_underlying_type_any (MonoType *type)
  365. {
  366. if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
  367. return mono_class_enum_basetype (type->data.klass);
  368. if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
  369. return mono_class_enum_basetype (type->data.generic_class->container_class);
  370. return type;
  371. }
  372. static G_GNUC_UNUSED const char*
  373. mono_type_get_stack_name (MonoType *type)
  374. {
  375. return type_names [get_stack_type (type) & TYPE_MASK];
  376. }
  377. #define CTOR_REQUIRED_FLAGS (METHOD_ATTRIBUTE_SPECIAL_NAME | METHOD_ATTRIBUTE_RT_SPECIAL_NAME)
  378. #define CTOR_INVALID_FLAGS (METHOD_ATTRIBUTE_STATIC)
  379. static gboolean
  380. mono_method_is_constructor (MonoMethod *method)
  381. {
  382. return ((method->flags & CTOR_REQUIRED_FLAGS) == CTOR_REQUIRED_FLAGS &&
  383. !(method->flags & CTOR_INVALID_FLAGS) &&
  384. !strcmp (".ctor", method->name));
  385. }
  386. static gboolean
  387. mono_class_has_default_constructor (MonoClass *klass)
  388. {
  389. MonoMethod *method;
  390. int i;
  391. mono_class_setup_methods (klass);
  392. if (klass->exception_type)
  393. return FALSE;
  394. for (i = 0; i < klass->method.count; ++i) {
  395. method = klass->methods [i];
  396. if (mono_method_is_constructor (method) &&
  397. mono_method_signature (method) &&
  398. mono_method_signature (method)->param_count == 0 &&
  399. (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)
  400. return TRUE;
  401. }
  402. return FALSE;
  403. }
  404. /*
  405. * Verify if @type is valid for the given @ctx verification context.
  406. * this function checks for VAR and MVAR types that are invalid under the current verifier,
  407. */
  408. static gboolean
  409. mono_type_is_valid_type_in_context_full (MonoType *type, MonoGenericContext *context, gboolean check_gtd)
  410. {
  411. int i;
  412. MonoGenericInst *inst;
  413. switch (type->type) {
  414. case MONO_TYPE_VAR:
  415. case MONO_TYPE_MVAR:
  416. if (!context)
  417. return FALSE;
  418. inst = type->type == MONO_TYPE_VAR ? context->class_inst : context->method_inst;
  419. if (!inst || mono_type_get_generic_param_num (type) >= inst->type_argc)
  420. return FALSE;
  421. break;
  422. case MONO_TYPE_SZARRAY:
  423. return mono_type_is_valid_type_in_context_full (&type->data.klass->byval_arg, context, check_gtd);
  424. case MONO_TYPE_ARRAY:
  425. return mono_type_is_valid_type_in_context_full (&type->data.array->eklass->byval_arg, context, check_gtd);
  426. case MONO_TYPE_PTR:
  427. return mono_type_is_valid_type_in_context_full (type->data.type, context, check_gtd);
  428. case MONO_TYPE_GENERICINST:
  429. inst = type->data.generic_class->context.class_inst;
  430. if (!inst->is_open)
  431. break;
  432. for (i = 0; i < inst->type_argc; ++i)
  433. if (!mono_type_is_valid_type_in_context_full (inst->type_argv [i], context, check_gtd))
  434. return FALSE;
  435. break;
  436. case MONO_TYPE_CLASS:
  437. case MONO_TYPE_VALUETYPE: {
  438. MonoClass *klass = type->data.klass;
  439. /*
  440. * It's possible to encode generic'sh types in such a way that they disguise themselves as class or valuetype.
  441. * Fixing the type decoding is really tricky since under some cases this behavior is needed, for example, to
  442. * have a 'class' type pointing to a 'genericinst' class.
  443. *
  444. * For the runtime these non canonical (weird) encodings work fine, the worst they can cause is some
  445. * reflection oddities which are harmless - to security at least.
  446. */
  447. if (klass->byval_arg.type != type->type)
  448. return mono_type_is_valid_type_in_context_full (&klass->byval_arg, context, check_gtd);
  449. if (check_gtd && klass->generic_container)
  450. return FALSE;
  451. break;
  452. }
  453. }
  454. return TRUE;
  455. }
  456. static gboolean
  457. mono_type_is_valid_type_in_context (MonoType *type, MonoGenericContext *context)
  458. {
  459. return mono_type_is_valid_type_in_context_full (type, context, FALSE);
  460. }
  461. /*This function returns NULL if the type is not instantiatable*/
  462. static MonoType*
  463. verifier_inflate_type (VerifyContext *ctx, MonoType *type, MonoGenericContext *context)
  464. {
  465. MonoError error;
  466. MonoType *result;
  467. result = mono_class_inflate_generic_type_checked (type, context, &error);
  468. if (!mono_error_ok (&error)) {
  469. mono_error_cleanup (&error);
  470. return NULL;
  471. }
  472. return result;
  473. }
  474. /*A side note here. We don't need to check if arguments are broken since this
  475. is only need to be done by the runtime before realizing the type.
  476. */
  477. static gboolean
  478. is_valid_generic_instantiation (MonoGenericContainer *gc, MonoGenericContext *context, MonoGenericInst *ginst)
  479. {
  480. MonoError error;
  481. int i;
  482. if (ginst->type_argc != gc->type_argc)
  483. return FALSE;
  484. for (i = 0; i < gc->type_argc; ++i) {
  485. MonoGenericParamInfo *param_info = mono_generic_container_get_param_info (gc, i);
  486. MonoClass *paramClass;
  487. MonoClass **constraints;
  488. MonoType *param_type = ginst->type_argv [i];
  489. /*it's not our job to validate type variables*/
  490. if (mono_type_is_generic_argument (param_type))
  491. continue;
  492. paramClass = mono_class_from_mono_type (param_type);
  493. /* A GTD can't be a generic argument.
  494. *
  495. * Due to how types are encoded we must check for the case of a genericinst MonoType and GTD MonoClass.
  496. * This happens in cases such as: class Foo<T> { void X() { new Bar<T> (); } }
  497. *
  498. * Open instantiations can have GTDs as this happens when one type is instantiated with others params
  499. * and the former has an expansion into the later. For example:
  500. * class B<K> {}
  501. * class A<T>: B<K> {}
  502. * The type A <K> has a parent B<K>, that is inflated into the GTD B<>.
  503. * Since A<K> is open, thus not instantiatable, this is valid.
  504. */
  505. if (paramClass->generic_container && param_type->type != MONO_TYPE_GENERICINST && !ginst->is_open)
  506. return FALSE;
  507. /*it's not safe to call mono_class_init from here*/
  508. if (paramClass->generic_class && !paramClass->inited) {
  509. if (!mono_class_is_valid_generic_instantiation (NULL, paramClass))
  510. return FALSE;
  511. }
  512. if (!param_info->constraints && !(param_info->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK))
  513. continue;
  514. if ((param_info->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && (!paramClass->valuetype || mono_class_is_nullable (paramClass)))
  515. return FALSE;
  516. if ((param_info->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && paramClass->valuetype)
  517. return FALSE;
  518. if ((param_info->flags & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !paramClass->valuetype && !mono_class_has_default_constructor (paramClass))
  519. return FALSE;
  520. if (!param_info->constraints)
  521. continue;
  522. for (constraints = param_info->constraints; *constraints; ++constraints) {
  523. MonoClass *ctr = *constraints;
  524. MonoType *inflated;
  525. inflated = mono_class_inflate_generic_type_checked (&ctr->byval_arg, context, &error);
  526. if (!mono_error_ok (&error)) {
  527. mono_error_cleanup (&error);
  528. return FALSE;
  529. }
  530. ctr = mono_class_from_mono_type (inflated);
  531. mono_metadata_free_type (inflated);
  532. /*FIXME maybe we need the same this as verifier_class_is_assignable_from*/
  533. if (!mono_class_is_assignable_from_slow (ctr, paramClass))
  534. return FALSE;
  535. }
  536. }
  537. return TRUE;
  538. }
  539. /*
  540. * Return true if @candidate is constraint compatible with @target.
  541. *
  542. * This means that @candidate constraints are a super set of @target constaints
  543. */
  544. static gboolean
  545. mono_generic_param_is_constraint_compatible (VerifyContext *ctx, MonoGenericParam *target, MonoGenericParam *candidate, MonoClass *candidate_param_class, MonoGenericContext *context)
  546. {
  547. MonoGenericParamInfo *tinfo = mono_generic_param_info (target);
  548. MonoGenericParamInfo *cinfo = mono_generic_param_info (candidate);
  549. MonoClass **candidate_class;
  550. gboolean class_constraint_satisfied = FALSE;
  551. gboolean valuetype_constraint_satisfied = FALSE;
  552. int tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
  553. int cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
  554. if (cinfo->constraints) {
  555. for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
  556. MonoClass *cc;
  557. MonoType *inflated = verifier_inflate_type (ctx, &(*candidate_class)->byval_arg, ctx->generic_context);
  558. if (!inflated)
  559. return FALSE;
  560. cc = mono_class_from_mono_type (inflated);
  561. mono_metadata_free_type (inflated);
  562. if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
  563. class_constraint_satisfied = TRUE;
  564. else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
  565. valuetype_constraint_satisfied = TRUE;
  566. }
  567. }
  568. class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
  569. valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
  570. if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
  571. return FALSE;
  572. if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
  573. return FALSE;
  574. if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
  575. valuetype_constraint_satisfied)) {
  576. return FALSE;
  577. }
  578. if (tinfo->constraints) {
  579. MonoClass **target_class;
  580. for (target_class = tinfo->constraints; *target_class; ++target_class) {
  581. MonoClass *tc;
  582. MonoType *inflated = verifier_inflate_type (ctx, &(*target_class)->byval_arg, context);
  583. if (!inflated)
  584. return FALSE;
  585. tc = mono_class_from_mono_type (inflated);
  586. mono_metadata_free_type (inflated);
  587. /*
  588. * A constraint from @target might inflate into @candidate itself and in that case we don't need
  589. * check it's constraints since it satisfy the constraint by itself.
  590. */
  591. if (mono_metadata_type_equal (&tc->byval_arg, &candidate_param_class->byval_arg))
  592. continue;
  593. if (!cinfo->constraints)
  594. return FALSE;
  595. for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
  596. MonoClass *cc;
  597. inflated = verifier_inflate_type (ctx, &(*candidate_class)->byval_arg, ctx->generic_context);
  598. if (!inflated)
  599. return FALSE;
  600. cc = mono_class_from_mono_type (inflated);
  601. mono_metadata_free_type (inflated);
  602. if (verifier_class_is_assignable_from (tc, cc))
  603. break;
  604. /*
  605. * This happens when we have the following:
  606. *
  607. * Bar<K> where K : IFace
  608. * Foo<T, U> where T : U where U : IFace
  609. * ...
  610. * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
  611. *
  612. */
  613. if (mono_type_is_generic_argument (&cc->byval_arg)) {
  614. MonoGenericParam *other_candidate = verifier_get_generic_param_from_type (ctx, &cc->byval_arg);
  615. if (mono_generic_param_is_constraint_compatible (ctx, target, other_candidate, cc, context)) {
  616. break;
  617. }
  618. }
  619. }
  620. if (!*candidate_class)
  621. return FALSE;
  622. }
  623. }
  624. return TRUE;
  625. }
  626. static MonoGenericParam*
  627. verifier_get_generic_param_from_type (VerifyContext *ctx, MonoType *type)
  628. {
  629. MonoGenericContainer *gc;
  630. MonoMethod *method = ctx->method;
  631. int num;
  632. num = mono_type_get_generic_param_num (type);
  633. if (type->type == MONO_TYPE_VAR) {
  634. MonoClass *gtd = method->klass;
  635. if (gtd->generic_class)
  636. gtd = gtd->generic_class->container_class;
  637. gc = gtd->generic_container;
  638. } else { //MVAR
  639. MonoMethod *gmd = method;
  640. if (method->is_inflated)
  641. gmd = ((MonoMethodInflated*)method)->declaring;
  642. gc = mono_method_get_generic_container (gmd);
  643. }
  644. if (!gc)
  645. return NULL;
  646. return mono_generic_container_get_param (gc, num);
  647. }
  648. /*
  649. * Verify if @type is valid for the given @ctx verification context.
  650. * this function checks for VAR and MVAR types that are invalid under the current verifier,
  651. * This means that it either
  652. */
  653. static gboolean
  654. is_valid_type_in_context (VerifyContext *ctx, MonoType *type)
  655. {
  656. return mono_type_is_valid_type_in_context (type, ctx->generic_context);
  657. }
  658. static gboolean
  659. is_valid_generic_instantiation_in_context (VerifyContext *ctx, MonoGenericInst *ginst, gboolean check_gtd)
  660. {
  661. int i;
  662. for (i = 0; i < ginst->type_argc; ++i) {
  663. MonoType *type = ginst->type_argv [i];
  664. if (!mono_type_is_valid_type_in_context_full (type, ctx->generic_context, TRUE))
  665. return FALSE;
  666. }
  667. return TRUE;
  668. }
  669. static gboolean
  670. generic_arguments_respect_constraints (VerifyContext *ctx, MonoGenericContainer *gc, MonoGenericContext *context, MonoGenericInst *ginst)
  671. {
  672. int i;
  673. for (i = 0; i < ginst->type_argc; ++i) {
  674. MonoType *type = ginst->type_argv [i];
  675. MonoGenericParam *target = mono_generic_container_get_param (gc, i);
  676. MonoGenericParam *candidate;
  677. MonoClass *candidate_class;
  678. if (!mono_type_is_generic_argument (type))
  679. continue;
  680. if (!is_valid_type_in_context (ctx, type))
  681. return FALSE;
  682. candidate = verifier_get_generic_param_from_type (ctx, type);
  683. candidate_class = mono_class_from_mono_type (type);
  684. if (!mono_generic_param_is_constraint_compatible (ctx, target, candidate, candidate_class, context))
  685. return FALSE;
  686. }
  687. return TRUE;
  688. }
  689. static gboolean
  690. mono_method_repect_method_constraints (VerifyContext *ctx, MonoMethod *method)
  691. {
  692. MonoMethodInflated *gmethod = (MonoMethodInflated *)method;
  693. MonoGenericInst *ginst = gmethod->context.method_inst;
  694. MonoGenericContainer *gc = mono_method_get_generic_container (gmethod->declaring);
  695. return !gc || generic_arguments_respect_constraints (ctx, gc, &gmethod->context, ginst);
  696. }
  697. static gboolean
  698. mono_class_repect_method_constraints (VerifyContext *ctx, MonoClass *klass)
  699. {
  700. MonoGenericClass *gklass = klass->generic_class;
  701. MonoGenericInst *ginst = gklass->context.class_inst;
  702. MonoGenericContainer *gc = gklass->container_class->generic_container;
  703. return !gc || generic_arguments_respect_constraints (ctx, gc, &gklass->context, ginst);
  704. }
  705. static gboolean
  706. mono_method_is_valid_generic_instantiation (VerifyContext *ctx, MonoMethod *method)
  707. {
  708. MonoMethodInflated *gmethod = (MonoMethodInflated *)method;
  709. MonoGenericInst *ginst = gmethod->context.method_inst;
  710. MonoGenericContainer *gc = mono_method_get_generic_container (gmethod->declaring);
  711. if (!gc) /*non-generic inflated method - it's part of a generic type */
  712. return TRUE;
  713. if (ctx && !is_valid_generic_instantiation_in_context (ctx, ginst, TRUE))
  714. return FALSE;
  715. return is_valid_generic_instantiation (gc, &gmethod->context, ginst);
  716. }
  717. static gboolean
  718. mono_class_is_valid_generic_instantiation (VerifyContext *ctx, MonoClass *klass)
  719. {
  720. MonoGenericClass *gklass = klass->generic_class;
  721. MonoGenericInst *ginst = gklass->context.class_inst;
  722. MonoGenericContainer *gc = gklass->container_class->generic_container;
  723. if (ctx && !is_valid_generic_instantiation_in_context (ctx, ginst, TRUE))
  724. return FALSE;
  725. return is_valid_generic_instantiation (gc, &gklass->context, ginst);
  726. }
  727. static gboolean
  728. mono_type_is_valid_in_context (VerifyContext *ctx, MonoType *type)
  729. {
  730. MonoClass *klass;
  731. if (type == NULL) {
  732. ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid null type at 0x%04x", ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
  733. return FALSE;
  734. }
  735. if (!is_valid_type_in_context (ctx, type)) {
  736. char *str = mono_type_full_name (type);
  737. ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid generic type (%s%s) (argument out of range or %s is not generic) at 0x%04x",
  738. type->type == MONO_TYPE_VAR ? "!" : "!!",
  739. str,
  740. type->type == MONO_TYPE_VAR ? "class" : "method",
  741. ctx->ip_offset),
  742. MONO_EXCEPTION_BAD_IMAGE);
  743. g_free (str);
  744. return FALSE;
  745. }
  746. klass = mono_class_from_mono_type (type);
  747. mono_class_init (klass);
  748. if (mono_loader_get_last_error () || klass->exception_type != MONO_EXCEPTION_NONE) {
  749. if (klass->generic_class && !mono_class_is_valid_generic_instantiation (NULL, klass))
  750. ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid generic instantiation of type %s.%s at 0x%04x", klass->name_space, klass->name, ctx->ip_offset), MONO_EXCEPTION_TYPE_LOAD);
  751. else
  752. ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Could not load type %s.%s at 0x%04x", klass->name_space, klass->name, ctx->ip_offset), MONO_EXCEPTION_TYPE_LOAD);
  753. mono_loader_clear_error ();
  754. return FALSE;
  755. }
  756. if (klass->generic_class && klass->generic_class->container_class->exception_type != MONO_EXCEPTION_NONE) {
  757. ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Could not load type %s.%s at 0x%04x", klass->name_space, klass->name, ctx->ip_offset), MONO_EXCEPTION_TYPE_LOAD);
  758. return FALSE;
  759. }
  760. if (!klass->generic_class)
  761. return TRUE;
  762. if (!mono_class_is_valid_generic_instantiation (ctx, klass)) {
  763. ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid generic type instantiation of type %s.%s at 0x%04x", klass->name_space, klass->name, ctx->ip_offset), MONO_EXCEPTION_TYPE_LOAD);
  764. return FALSE;
  765. }
  766. if (!mono_class_repect_method_constraints (ctx, klass)) {
  767. ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid generic type instantiation of type %s.%s (generic args don't respect target's constraints) at 0x%04x", klass->name_space, klass->name, ctx->ip_offset), MONO_EXCEPTION_TYPE_LOAD);
  768. return FALSE;
  769. }
  770. return TRUE;
  771. }
  772. static verify_result_t
  773. mono_method_is_valid_in_context (VerifyContext *ctx, MonoMethod *method)
  774. {
  775. if (!mono_type_is_valid_in_context (ctx, &method->klass->byval_arg))
  776. return RESULT_INVALID;
  777. if (!method->is_inflated)
  778. return RESULT_VALID;
  779. if (!mono_method_is_valid_generic_instantiation (ctx, method)) {
  780. ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid generic method instantiation of method %s.%s::%s at 0x%04x", method->klass->name_space, method->klass->name, method->name, ctx->ip_offset), MONO_EXCEPTION_UNVERIFIABLE_IL);
  781. return RESULT_INVALID;
  782. }
  783. if (!mono_method_repect_method_constraints (ctx, method)) {
  784. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid generic method instantiation of method %s.%s::%s (generic args don't respect target's constraints) at 0x%04x", method->klass->name_space, method->klass->name, method->name, ctx->ip_offset));
  785. return RESULT_UNVERIFIABLE;
  786. }
  787. return RESULT_VALID;
  788. }
  789. static MonoClassField*
  790. verifier_load_field (VerifyContext *ctx, int token, MonoClass **out_klass, const char *opcode) {
  791. MonoClassField *field;
  792. MonoClass *klass = NULL;
  793. if (ctx->method->wrapper_type != MONO_WRAPPER_NONE) {
  794. field = mono_method_get_wrapper_data (ctx->method, (guint32)token);
  795. klass = field ? field->parent : NULL;
  796. } else {
  797. if (!IS_FIELD_DEF_OR_REF (token) || !token_bounds_check (ctx->image, token)) {
  798. ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid field token 0x%08x for %s at 0x%04x", token, opcode, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
  799. return NULL;
  800. }
  801. field = mono_field_from_token (ctx->image, token, &klass, ctx->generic_context);
  802. }
  803. if (!field || !field->parent || !klass || mono_loader_get_last_error ()) {
  804. ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Cannot load field from token 0x%08x for %s at 0x%04x", token, opcode, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
  805. mono_loader_clear_error ();
  806. return NULL;
  807. }
  808. if (!mono_type_is_valid_in_context (ctx, &klass->byval_arg))
  809. return NULL;
  810. if (mono_field_get_flags (field) & FIELD_ATTRIBUTE_LITERAL) {
  811. char *type_name = mono_type_get_full_name (field->parent);
  812. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Cannot reference literal field %s::%s at 0x%04x", type_name, field->name, ctx->ip_offset));
  813. g_free (type_name);
  814. return NULL;
  815. }
  816. *out_klass = klass;
  817. return field;
  818. }
  819. static MonoMethod*
  820. verifier_load_method (VerifyContext *ctx, int token, const char *opcode) {
  821. MonoMethod* method;
  822. if (ctx->method->wrapper_type != MONO_WRAPPER_NONE) {
  823. method = mono_method_get_wrapper_data (ctx->method, (guint32)token);
  824. } else {
  825. if (!IS_METHOD_DEF_OR_REF_OR_SPEC (token) || !token_bounds_check (ctx->image, token)) {
  826. ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid method token 0x%08x for %s at 0x%04x", token, opcode, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
  827. return NULL;
  828. }
  829. method = mono_get_method_full (ctx->image, token, NULL, ctx->generic_context);
  830. }
  831. if (!method || mono_loader_get_last_error ()) {
  832. ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Cannot load method from token 0x%08x for %s at 0x%04x", token, opcode, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
  833. mono_loader_clear_error ();
  834. return NULL;
  835. }
  836. if (mono_method_is_valid_in_context (ctx, method) == RESULT_INVALID)
  837. return NULL;
  838. return method;
  839. }
  840. static MonoType*
  841. verifier_load_type (VerifyContext *ctx, int token, const char *opcode) {
  842. MonoType* type;
  843. if (ctx->method->wrapper_type != MONO_WRAPPER_NONE) {
  844. MonoClass *class = mono_method_get_wrapper_data (ctx->method, (guint32)token);
  845. type = class ? &class->byval_arg : NULL;
  846. } else {
  847. if (!IS_TYPE_DEF_OR_REF_OR_SPEC (token) || !token_bounds_check (ctx->image, token)) {
  848. ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid type token 0x%08x at 0x%04x", token, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
  849. return NULL;
  850. }
  851. type = mono_type_get_full (ctx->image, token, ctx->generic_context);
  852. }
  853. if (!type || mono_loader_get_last_error ()) {
  854. ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Cannot load type from token 0x%08x for %s at 0x%04x", token, opcode, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
  855. mono_loader_clear_error ();
  856. return NULL;
  857. }
  858. if (!mono_type_is_valid_in_context (ctx, type))
  859. return NULL;
  860. return type;
  861. }
  862. /* stack_slot_get_type:
  863. *
  864. * Returns the stack type of @value. This value includes POINTER_MASK.
  865. *
  866. * Use this function to checks that account for a managed pointer.
  867. */
  868. static gint32
  869. stack_slot_get_type (ILStackDesc *value)
  870. {
  871. return value->stype & RAW_TYPE_MASK;
  872. }
  873. /* stack_slot_get_underlying_type:
  874. *
  875. * Returns the stack type of @value. This value does not include POINTER_MASK.
  876. *
  877. * Use this function is cases where the fact that the value could be a managed pointer is
  878. * irrelevant. For example, field load doesn't care about this fact of type on stack.
  879. */
  880. static gint32
  881. stack_slot_get_underlying_type (ILStackDesc *value)
  882. {
  883. return value->stype & TYPE_MASK;
  884. }
  885. /* stack_slot_is_managed_pointer:
  886. *
  887. * Returns TRUE is @value is a managed pointer.
  888. */
  889. static gboolean
  890. stack_slot_is_managed_pointer (ILStackDesc *value)
  891. {
  892. return (value->stype & POINTER_MASK) == POINTER_MASK;
  893. }
  894. /* stack_slot_is_managed_mutability_pointer:
  895. *
  896. * Returns TRUE is @value is a managed mutability pointer.
  897. */
  898. static G_GNUC_UNUSED gboolean
  899. stack_slot_is_managed_mutability_pointer (ILStackDesc *value)
  900. {
  901. return (value->stype & CMMP_MASK) == CMMP_MASK;
  902. }
  903. /* stack_slot_is_null_literal:
  904. *
  905. * Returns TRUE is @value is the null literal.
  906. */
  907. static gboolean
  908. stack_slot_is_null_literal (ILStackDesc *value)
  909. {
  910. return (value->stype & NULL_LITERAL_MASK) == NULL_LITERAL_MASK;
  911. }
  912. /* stack_slot_is_this_pointer:
  913. *
  914. * Returns TRUE is @value is the this literal
  915. */
  916. static gboolean
  917. stack_slot_is_this_pointer (ILStackDesc *value)
  918. {
  919. return (value->stype & THIS_POINTER_MASK) == THIS_POINTER_MASK;
  920. }
  921. /* stack_slot_is_boxed_value:
  922. *
  923. * Returns TRUE is @value is a boxed value
  924. */
  925. static gboolean
  926. stack_slot_is_boxed_value (ILStackDesc *value)
  927. {
  928. return (value->stype & BOXED_MASK) == BOXED_MASK;
  929. }
  930. static const char *
  931. stack_slot_get_name (ILStackDesc *value)
  932. {
  933. return type_names [value->stype & TYPE_MASK];
  934. }
  935. #define APPEND_WITH_PREDICATE(PRED,NAME) do {\
  936. if (PRED (value)) { \
  937. if (!first) \
  938. g_string_append (str, ", "); \
  939. g_string_append (str, NAME); \
  940. first = FALSE; \
  941. } } while (0)
  942. static char*
  943. stack_slot_stack_type_full_name (ILStackDesc *value)
  944. {
  945. GString *str = g_string_new ("");
  946. char *result;
  947. gboolean has_pred = FALSE, first = TRUE;
  948. if ((value->stype & TYPE_MASK) != value->stype) {
  949. g_string_append(str, "[");
  950. APPEND_WITH_PREDICATE (stack_slot_is_this_pointer, "this");
  951. APPEND_WITH_PREDICATE (stack_slot_is_boxed_value, "boxed");
  952. APPEND_WITH_PREDICATE (stack_slot_is_null_literal, "null");
  953. APPEND_WITH_PREDICATE (stack_slot_is_managed_mutability_pointer, "cmmp");
  954. APPEND_WITH_PREDICATE (stack_slot_is_managed_pointer, "mp");
  955. has_pred = TRUE;
  956. }
  957. if (mono_type_is_generic_argument (value->type) && !stack_slot_is_boxed_value (value)) {
  958. if (!has_pred)
  959. g_string_append(str, "[");
  960. if (!first)
  961. g_string_append (str, ", ");
  962. g_string_append (str, "unboxed");
  963. has_pred = TRUE;
  964. }
  965. if (has_pred)
  966. g_string_append(str, "] ");
  967. g_string_append (str, stack_slot_get_name (value));
  968. result = str->str;
  969. g_string_free (str, FALSE);
  970. return result;
  971. }
  972. static char*
  973. stack_slot_full_name (ILStackDesc *value)
  974. {
  975. char *type_name = mono_type_full_name (value->type);
  976. char *stack_name = stack_slot_stack_type_full_name (value);
  977. char *res = g_strdup_printf ("%s (%s)", type_name, stack_name);
  978. g_free (type_name);
  979. g_free (stack_name);
  980. return res;
  981. }
  982. //////////////////////////////////////////////////////////////////
  983. void
  984. mono_free_verify_list (GSList *list)
  985. {
  986. MonoVerifyInfoExtended *info;
  987. GSList *tmp;
  988. for (tmp = list; tmp; tmp = tmp->next) {
  989. info = tmp->data;
  990. g_free (info->info.message);
  991. g_free (info);
  992. }
  993. g_slist_free (list);
  994. }
  995. #define ADD_ERROR(list,msg) \
  996. do { \
  997. MonoVerifyInfoExtended *vinfo = g_new (MonoVerifyInfoExtended, 1); \
  998. vinfo->info.status = MONO_VERIFY_ERROR; \
  999. vinfo->info.message = (msg); \
  1000. (list) = g_slist_prepend ((list), vinfo); \
  1001. } while (0)
  1002. #define ADD_WARN(list,code,msg) \
  1003. do { \
  1004. MonoVerifyInfoExtended *vinfo = g_new (MonoVerifyInfoExtended, 1); \
  1005. vinfo->info.status = (code); \
  1006. vinfo->info.message = (msg); \
  1007. (list) = g_slist_prepend ((list), vinfo); \
  1008. } while (0)
  1009. #define ADD_INVALID(list,msg) \
  1010. do { \
  1011. MonoVerifyInfoExtended *vinfo = g_new (MonoVerifyInfoExtended, 1); \
  1012. vinfo->status = MONO_VERIFY_ERROR; \
  1013. vinfo->message = (msg); \
  1014. (list) = g_slist_prepend ((list), vinfo); \
  1015. /*G_BREAKPOINT ();*/ \
  1016. goto invalid_cil; \
  1017. } while (0)
  1018. #define CHECK_STACK_UNDERFLOW(num) \
  1019. do { \
  1020. if (cur_stack < (num)) \
  1021. ADD_INVALID (list, g_strdup_printf ("Stack underflow at 0x%04x (%d items instead of %d)", ip_offset, cur_stack, (num))); \
  1022. } while (0)
  1023. #define CHECK_STACK_OVERFLOW() \
  1024. do { \
  1025. if (cur_stack >= max_stack) \
  1026. ADD_INVALID (list, g_strdup_printf ("Maxstack exceeded at 0x%04x", ip_offset)); \
  1027. } while (0)
  1028. static int
  1029. in_any_block (MonoMethodHeader *header, guint offset)
  1030. {
  1031. int i;
  1032. MonoExceptionClause *clause;
  1033. for (i = 0; i < header->num_clauses; ++i) {
  1034. clause = &header->clauses [i];
  1035. if (MONO_OFFSET_IN_CLAUSE (clause, offset))
  1036. return 1;
  1037. if (MONO_OFFSET_IN_HANDLER (clause, offset))
  1038. return 1;
  1039. if (MONO_OFFSET_IN_FILTER (clause, offset))
  1040. return 1;
  1041. }
  1042. return 0;
  1043. }
  1044. /*
  1045. * in_any_exception_block:
  1046. *
  1047. * Returns TRUE is @offset is part of any exception clause (filter, handler, catch, finally or fault).
  1048. */
  1049. static gboolean
  1050. in_any_exception_block (MonoMethodHeader *header, guint offset)
  1051. {
  1052. int i;
  1053. MonoExceptionClause *clause;
  1054. for (i = 0; i < header->num_clauses; ++i) {
  1055. clause = &header->clauses [i];
  1056. if (MONO_OFFSET_IN_HANDLER (clause, offset))
  1057. return TRUE;
  1058. if (MONO_OFFSET_IN_FILTER (clause, offset))
  1059. return TRUE;
  1060. }
  1061. return FALSE;
  1062. }
  1063. /*
  1064. * is_valid_branch_instruction:
  1065. *
  1066. * Verify if it's valid to perform a branch from @offset to @target.
  1067. * This should be used with br and brtrue/false.
  1068. * It returns 0 if valid, 1 for unverifiable and 2 for invalid.
  1069. * The major difference from other similiar functions is that branching into a
  1070. * finally/fault block is invalid instead of just unverifiable.
  1071. */
  1072. static int
  1073. is_valid_branch_instruction (MonoMethodHeader *header, guint offset, guint target)
  1074. {
  1075. int i;
  1076. MonoExceptionClause *clause;
  1077. for (i = 0; i < header->num_clauses; ++i) {
  1078. clause = &header->clauses [i];
  1079. /*branching into a finally block is invalid*/
  1080. if ((clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY || clause->flags == MONO_EXCEPTION_CLAUSE_FAULT) &&
  1081. !MONO_OFFSET_IN_HANDLER (clause, offset) &&
  1082. MONO_OFFSET_IN_HANDLER (clause, target))
  1083. return 2;
  1084. if (clause->try_offset != target && (MONO_OFFSET_IN_CLAUSE (clause, offset) ^ MONO_OFFSET_IN_CLAUSE (clause, target)))
  1085. return 1;
  1086. if (MONO_OFFSET_IN_HANDLER (clause, offset) ^ MONO_OFFSET_IN_HANDLER (clause, target))
  1087. return 1;
  1088. if (MONO_OFFSET_IN_FILTER (clause, offset) ^ MONO_OFFSET_IN_FILTER (clause, target))
  1089. return 1;
  1090. }
  1091. return 0;
  1092. }
  1093. /*
  1094. * is_valid_cmp_branch_instruction:
  1095. *
  1096. * Verify if it's valid to perform a branch from @offset to @target.
  1097. * This should be used with binary comparison branching instruction, like beq, bge and similars.
  1098. * It returns 0 if valid, 1 for unverifiable and 2 for invalid.
  1099. *
  1100. * The major differences from other similar functions are that most errors lead to invalid
  1101. * code and only branching out of finally, filter or fault clauses is unverifiable.
  1102. */
  1103. static int
  1104. is_valid_cmp_branch_instruction (MonoMethodHeader *header, guint offset, guint target)
  1105. {
  1106. int i;
  1107. MonoExceptionClause *clause;
  1108. for (i = 0; i < header->num_clauses; ++i) {
  1109. clause = &header->clauses [i];
  1110. /*branching out of a handler or finally*/
  1111. if (clause->flags != MONO_EXCEPTION_CLAUSE_NONE &&
  1112. MONO_OFFSET_IN_HANDLER (clause, offset) &&
  1113. !MONO_OFFSET_IN_HANDLER (clause, target))
  1114. return 1;
  1115. if (clause->try_offset != target && (MONO_OFFSET_IN_CLAUSE (clause, offset) ^ MONO_OFFSET_IN_CLAUSE (clause, target)))
  1116. return 2;
  1117. if (MONO_OFFSET_IN_HANDLER (clause, offset) ^ MONO_OFFSET_IN_HANDLER (clause, target))
  1118. return 2;
  1119. if (MONO_OFFSET_IN_FILTER (clause, offset) ^ MONO_OFFSET_IN_FILTER (clause, target))
  1120. return 2;
  1121. }
  1122. return 0;
  1123. }
  1124. /*
  1125. * A leave can't escape a finally block
  1126. */
  1127. static int
  1128. is_correct_leave (MonoMethodHeader *header, guint offset, guint target)
  1129. {
  1130. int i;
  1131. MonoExceptionClause *clause;
  1132. for (i = 0; i < header->num_clauses; ++i) {
  1133. clause = &header->clauses [i];
  1134. if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY && MONO_OFFSET_IN_HANDLER (clause, offset) && !MONO_OFFSET_IN_HANDLER (clause, target))
  1135. return 0;
  1136. if (MONO_OFFSET_IN_FILTER (clause, offset))
  1137. return 0;
  1138. }
  1139. return 1;
  1140. }
  1141. /*
  1142. * A rethrow can't happen outside of a catch handler.
  1143. */
  1144. static int
  1145. is_correct_rethrow (MonoMethodHeader *header, guint offset)
  1146. {
  1147. int i;
  1148. MonoExceptionClause *clause;
  1149. for (i = 0; i < header->num_clauses; ++i) {
  1150. clause = &header->clauses [i];
  1151. if (MONO_OFFSET_IN_HANDLER (clause, offset))
  1152. return 1;
  1153. if (MONO_OFFSET_IN_FILTER (clause, offset))
  1154. return 1;
  1155. }
  1156. return 0;
  1157. }
  1158. /*
  1159. * An endfinally can't happen outside of a finally/fault handler.
  1160. */
  1161. static int
  1162. is_correct_endfinally (MonoMethodHeader *header, guint offset)
  1163. {
  1164. int i;
  1165. MonoExceptionClause *clause;
  1166. for (i = 0; i < header->num_clauses; ++i) {
  1167. clause = &header->clauses [i];
  1168. if (MONO_OFFSET_IN_HANDLER (clause, offset) && (clause->flags == MONO_EXCEPTION_CLAUSE_FAULT || clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY))
  1169. return 1;
  1170. }
  1171. return 0;
  1172. }
  1173. /*
  1174. * An endfilter can only happens inside a filter clause.
  1175. * In non-strict mode filter is allowed inside the handler clause too
  1176. */
  1177. static MonoExceptionClause *
  1178. is_correct_endfilter (VerifyContext *ctx, guint offset)
  1179. {
  1180. int i;
  1181. MonoExceptionClause *clause;
  1182. for (i = 0; i < ctx->header->num_clauses; ++i) {
  1183. clause = &ctx->header->clauses [i];
  1184. if (clause->flags != MONO_EXCEPTION_CLAUSE_FILTER)
  1185. continue;
  1186. if (MONO_OFFSET_IN_FILTER (clause, offset))
  1187. return clause;
  1188. if (!IS_STRICT_MODE (ctx) && MONO_OFFSET_IN_HANDLER (clause, offset))
  1189. return clause;
  1190. }
  1191. return NULL;
  1192. }
  1193. /*
  1194. * Non-strict endfilter can happens inside a try block or any handler block
  1195. */
  1196. static int
  1197. is_unverifiable_endfilter (VerifyContext *ctx, guint offset)
  1198. {
  1199. int i;
  1200. MonoExceptionClause *clause;
  1201. for (i = 0; i < ctx->header->num_clauses; ++i) {
  1202. clause = &ctx->header->clauses [i];
  1203. if (MONO_OFFSET_IN_CLAUSE (clause, offset))
  1204. return 1;
  1205. }
  1206. return 0;
  1207. }
  1208. static gboolean
  1209. is_valid_bool_arg (ILStackDesc *arg)
  1210. {
  1211. if (stack_slot_is_managed_pointer (arg) || stack_slot_is_boxed_value (arg) || stack_slot_is_null_literal (arg))
  1212. return TRUE;
  1213. switch (stack_slot_get_underlying_type (arg)) {
  1214. case TYPE_I4:
  1215. case TYPE_I8:
  1216. case TYPE_NATIVE_INT:
  1217. case TYPE_PTR:
  1218. return TRUE;
  1219. case TYPE_COMPLEX:
  1220. g_assert (arg->type);
  1221. switch (arg->type->type) {
  1222. case MONO_TYPE_CLASS:
  1223. case MONO_TYPE_STRING:
  1224. case MONO_TYPE_OBJECT:
  1225. case MONO_TYPE_SZARRAY:
  1226. case MONO_TYPE_ARRAY:
  1227. case MONO_TYPE_FNPTR:
  1228. case MONO_TYPE_PTR:
  1229. return TRUE;
  1230. case MONO_TYPE_GENERICINST:
  1231. /*We need to check if the container class
  1232. * of the generic type is a valuetype, iow:
  1233. * is it a "class Foo<T>" or a "struct Foo<T>"?
  1234. */
  1235. return !arg->type->data.generic_class->container_class->valuetype;
  1236. }
  1237. default:
  1238. return FALSE;
  1239. }
  1240. }
  1241. /*Type manipulation helper*/
  1242. /*Returns the byref version of the supplied MonoType*/
  1243. static MonoType*
  1244. mono_type_get_type_byref (MonoType *type)
  1245. {
  1246. if (type->byref)
  1247. return type;
  1248. return &mono_class_from_mono_type (type)->this_arg;
  1249. }
  1250. /*Returns the byval version of the supplied MonoType*/
  1251. static MonoType*
  1252. mono_type_get_type_byval (MonoType *type)
  1253. {
  1254. if (!type->byref)
  1255. return type;
  1256. return &mono_class_from_mono_type (type)->byval_arg;
  1257. }
  1258. static MonoType*
  1259. mono_type_from_stack_slot (ILStackDesc *slot)
  1260. {
  1261. if (stack_slot_is_managed_pointer (slot))
  1262. return mono_type_get_type_byref (slot->type);
  1263. return slot->type;
  1264. }
  1265. /*Stack manipulation code*/
  1266. static void
  1267. ensure_stack_size (ILCodeDesc *stack, int required)
  1268. {
  1269. int new_size = 8;
  1270. ILStackDesc *tmp;
  1271. if (required < stack->max_size)
  1272. return;
  1273. /* We don't have to worry about the exponential growth since stack_copy prune unused space */
  1274. new_size = MAX (8, MAX (required, stack->max_size * 2));
  1275. g_assert (new_size >= stack->size);
  1276. g_assert (new_size >= required);
  1277. tmp = g_new0 (ILStackDesc, new_size);
  1278. MEM_ALLOC (sizeof (ILStackDesc) * new_size);
  1279. if (stack->stack) {
  1280. if (stack->size)
  1281. memcpy (tmp, stack->stack, stack->size * sizeof (ILStackDesc));
  1282. g_free (stack->stack);
  1283. MEM_FREE (sizeof (ILStackDesc) * stack->max_size);
  1284. }
  1285. stack->stack = tmp;
  1286. stack->max_size = new_size;
  1287. }
  1288. static void
  1289. stack_init (VerifyContext *ctx, ILCodeDesc *state)
  1290. {
  1291. if (state->flags & IL_CODE_FLAG_STACK_INITED)
  1292. return;
  1293. state->size = state->max_size = 0;
  1294. state->flags |= IL_CODE_FLAG_STACK_INITED;
  1295. }
  1296. static void
  1297. stack_copy (ILCodeDesc *to, ILCodeDesc *from)
  1298. {
  1299. ensure_stack_size (to, from->size);
  1300. to->size = from->size;
  1301. /*stack copy happens at merge points, which have small stacks*/
  1302. if (from->size)
  1303. memcpy (to->stack, from->stack, sizeof (ILStackDesc) * from->size);
  1304. }
  1305. static void
  1306. copy_stack_value (ILStackDesc *to, ILStackDesc *from)
  1307. {
  1308. to->stype = from->stype;
  1309. to->type = from->type;
  1310. to->method = from->method;
  1311. }
  1312. static int
  1313. check_underflow (VerifyContext *ctx, int size)
  1314. {
  1315. if (ctx->eval.size < size) {
  1316. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Stack underflow, required %d, but have %d at 0x%04x", size, ctx->eval.size, ctx->ip_offset));
  1317. return 0;
  1318. }
  1319. return 1;
  1320. }
  1321. static int
  1322. check_overflow (VerifyContext *ctx)
  1323. {
  1324. if (ctx->eval.size >= ctx->max_stack) {
  1325. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Method doesn't have stack-depth %d at 0x%04x", ctx->eval.size + 1, ctx->ip_offset));
  1326. return 0;
  1327. }
  1328. return 1;
  1329. }
  1330. /*This reject out PTR, FNPTR and TYPEDBYREF*/
  1331. static gboolean
  1332. check_unmanaged_pointer (VerifyContext *ctx, ILStackDesc *value)
  1333. {
  1334. if (stack_slot_get_type (value) == TYPE_PTR) {
  1335. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Unmanaged pointer is not a verifiable type at 0x%04x", ctx->ip_offset));
  1336. return 0;
  1337. }
  1338. return 1;
  1339. }
  1340. /*TODO verify if MONO_TYPE_TYPEDBYREF is not allowed here as well.*/
  1341. static gboolean
  1342. check_unverifiable_type (VerifyContext *ctx, MonoType *type)
  1343. {
  1344. if (type->type == MONO_TYPE_PTR || type->type == MONO_TYPE_FNPTR) {
  1345. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Unmanaged pointer is not a verifiable type at 0x%04x", ctx->ip_offset));
  1346. return 0;
  1347. }
  1348. return 1;
  1349. }
  1350. static ILStackDesc *
  1351. stack_push (VerifyContext *ctx)
  1352. {
  1353. g_assert (ctx->eval.size < ctx->max_stack);
  1354. g_assert (ctx->eval.size <= ctx->eval.max_size);
  1355. ensure_stack_size (&ctx->eval, ctx->eval.size + 1);
  1356. return & ctx->eval.stack [ctx->eval.size++];
  1357. }
  1358. static ILStackDesc *
  1359. stack_push_val (VerifyContext *ctx, int stype, MonoType *type)
  1360. {
  1361. ILStackDesc *top = stack_push (ctx);
  1362. top->stype = stype;
  1363. top->type = type;
  1364. return top;
  1365. }
  1366. static ILStackDesc *
  1367. stack_pop (VerifyContext *ctx)
  1368. {
  1369. ILStackDesc *ret;
  1370. g_assert (ctx->eval.size > 0);
  1371. ret = ctx->eval.stack + --ctx->eval.size;
  1372. if ((ret->stype & UNINIT_THIS_MASK) == UNINIT_THIS_MASK)
  1373. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Found use of uninitialized 'this ptr' ref at 0x%04x", ctx->ip_offset));
  1374. return ret;
  1375. }
  1376. /* This function allows to safely pop an unititialized this ptr from
  1377. * the eval stack without marking the method as unverifiable.
  1378. */
  1379. static ILStackDesc *
  1380. stack_pop_safe (VerifyContext *ctx)
  1381. {
  1382. g_assert (ctx->eval.size > 0);
  1383. return ctx->eval.stack + --ctx->eval.size;
  1384. }
  1385. /*Positive number distance from stack top. [0] is stack top, [1] is the one below*/
  1386. static ILStackDesc*
  1387. stack_peek (VerifyContext *ctx, int distance)
  1388. {
  1389. g_assert (ctx->eval.size - distance > 0);
  1390. return ctx->eval.stack + (ctx->eval.size - 1 - distance);
  1391. }
  1392. static ILStackDesc *
  1393. stack_push_stack_val (VerifyContext *ctx, ILStackDesc *value)
  1394. {
  1395. ILStackDesc *top = stack_push (ctx);
  1396. copy_stack_value (top, value);
  1397. return top;
  1398. }
  1399. /* Returns the MonoType associated with the token, or NULL if it is invalid.
  1400. *
  1401. * A boxable type can be either a refereā€¦

Large files files are truncated, but you can click here to view the full file