PageRenderTime 88ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/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
  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 reference or value type, but cannot be a byref type or an unmanaged pointer
  1402. * */
  1403. static MonoType*
  1404. get_boxable_mono_type (VerifyContext* ctx, int token, const char *opcode)
  1405. {
  1406. MonoType *type;
  1407. MonoClass *class;
  1408. if (!(type = verifier_load_type (ctx, token, opcode)))
  1409. return NULL;
  1410. if (type->byref && type->type != MONO_TYPE_TYPEDBYREF) {
  1411. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid use of byref type for %s at 0x%04x", opcode, ctx->ip_offset));
  1412. return NULL;
  1413. }
  1414. if (type->type == MONO_TYPE_VOID) {
  1415. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid use of void type for %s at 0x%04x", opcode, ctx->ip_offset));
  1416. return NULL;
  1417. }
  1418. if (type->type == MONO_TYPE_TYPEDBYREF)
  1419. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid use of typedbyref for %s at 0x%04x", opcode, ctx->ip_offset));
  1420. if (!(class = mono_class_from_mono_type (type)))
  1421. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Could not retrieve type token for %s at 0x%04x", opcode, ctx->ip_offset));
  1422. if (class->generic_container && type->type != MONO_TYPE_GENERICINST)
  1423. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use the generic type definition in a boxable type position for %s at 0x%04x", opcode, ctx->ip_offset));
  1424. check_unverifiable_type (ctx, type);
  1425. return type;
  1426. }
  1427. /*operation result tables */
  1428. static const unsigned char bin_op_table [TYPE_MAX][TYPE_MAX] = {
  1429. {TYPE_I4, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_INV, TYPE_INV},
  1430. {TYPE_INV, TYPE_I8, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1431. {TYPE_NATIVE_INT, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_INV, TYPE_INV},
  1432. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_R8, TYPE_INV, TYPE_INV},
  1433. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1434. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1435. };
  1436. static const unsigned char add_table [TYPE_MAX][TYPE_MAX] = {
  1437. {TYPE_I4, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_PTR | NON_VERIFIABLE_RESULT, TYPE_INV},
  1438. {TYPE_INV, TYPE_I8, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1439. {TYPE_NATIVE_INT, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_PTR | NON_VERIFIABLE_RESULT, TYPE_INV},
  1440. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_R8, TYPE_INV, TYPE_INV},
  1441. {TYPE_PTR | NON_VERIFIABLE_RESULT, TYPE_INV, TYPE_PTR | NON_VERIFIABLE_RESULT, TYPE_INV, TYPE_INV, TYPE_INV},
  1442. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1443. };
  1444. static const unsigned char sub_table [TYPE_MAX][TYPE_MAX] = {
  1445. {TYPE_I4, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_INV, TYPE_INV},
  1446. {TYPE_INV, TYPE_I8, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1447. {TYPE_NATIVE_INT, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_INV, TYPE_INV},
  1448. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_R8, TYPE_INV, TYPE_INV},
  1449. {TYPE_PTR | NON_VERIFIABLE_RESULT, TYPE_INV, TYPE_PTR | NON_VERIFIABLE_RESULT, TYPE_INV, TYPE_NATIVE_INT | NON_VERIFIABLE_RESULT, TYPE_INV},
  1450. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1451. };
  1452. static const unsigned char int_bin_op_table [TYPE_MAX][TYPE_MAX] = {
  1453. {TYPE_I4, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_INV, TYPE_INV},
  1454. {TYPE_INV, TYPE_I8, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1455. {TYPE_NATIVE_INT, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_INV, TYPE_INV},
  1456. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1457. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1458. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1459. };
  1460. static const unsigned char shift_op_table [TYPE_MAX][TYPE_MAX] = {
  1461. {TYPE_I4, TYPE_INV, TYPE_I4, TYPE_INV, TYPE_INV, TYPE_INV},
  1462. {TYPE_I8, TYPE_INV, TYPE_I8, TYPE_INV, TYPE_INV, TYPE_INV},
  1463. {TYPE_NATIVE_INT, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_INV, TYPE_INV},
  1464. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1465. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1466. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1467. };
  1468. static const unsigned char cmp_br_op [TYPE_MAX][TYPE_MAX] = {
  1469. {TYPE_I4, TYPE_INV, TYPE_I4, TYPE_INV, TYPE_INV, TYPE_INV},
  1470. {TYPE_INV, TYPE_I4, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1471. {TYPE_I4, TYPE_INV, TYPE_I4, TYPE_INV, TYPE_INV, TYPE_INV},
  1472. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_I4, TYPE_INV, TYPE_INV},
  1473. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_I4, TYPE_INV},
  1474. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1475. };
  1476. static const unsigned char cmp_br_eq_op [TYPE_MAX][TYPE_MAX] = {
  1477. {TYPE_I4, TYPE_INV, TYPE_I4, TYPE_INV, TYPE_INV, TYPE_INV},
  1478. {TYPE_INV, TYPE_I4, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1479. {TYPE_I4, TYPE_INV, TYPE_I4, TYPE_INV, TYPE_I4 | NON_VERIFIABLE_RESULT, TYPE_INV},
  1480. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_I4, TYPE_INV, TYPE_INV},
  1481. {TYPE_INV, TYPE_INV, TYPE_I4 | NON_VERIFIABLE_RESULT, TYPE_INV, TYPE_I4, TYPE_INV},
  1482. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_I4},
  1483. };
  1484. static const unsigned char add_ovf_un_table [TYPE_MAX][TYPE_MAX] = {
  1485. {TYPE_I4, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_PTR | NON_VERIFIABLE_RESULT, TYPE_INV},
  1486. {TYPE_INV, TYPE_I8, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1487. {TYPE_NATIVE_INT, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_PTR | NON_VERIFIABLE_RESULT, TYPE_INV},
  1488. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1489. {TYPE_PTR | NON_VERIFIABLE_RESULT, TYPE_INV, TYPE_PTR | NON_VERIFIABLE_RESULT, TYPE_INV, TYPE_INV, TYPE_INV},
  1490. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1491. };
  1492. static const unsigned char sub_ovf_un_table [TYPE_MAX][TYPE_MAX] = {
  1493. {TYPE_I4, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_INV, TYPE_INV},
  1494. {TYPE_INV, TYPE_I8, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1495. {TYPE_NATIVE_INT, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_INV, TYPE_INV},
  1496. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1497. {TYPE_PTR | NON_VERIFIABLE_RESULT, TYPE_INV, TYPE_PTR | NON_VERIFIABLE_RESULT, TYPE_INV, TYPE_NATIVE_INT | NON_VERIFIABLE_RESULT, TYPE_INV},
  1498. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1499. };
  1500. static const unsigned char bin_ovf_table [TYPE_MAX][TYPE_MAX] = {
  1501. {TYPE_I4, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_INV, TYPE_INV},
  1502. {TYPE_INV, TYPE_I8, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1503. {TYPE_NATIVE_INT, TYPE_INV, TYPE_NATIVE_INT, TYPE_INV, TYPE_INV, TYPE_INV},
  1504. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1505. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1506. {TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV, TYPE_INV},
  1507. };
  1508. #ifdef MONO_VERIFIER_DEBUG
  1509. /*debug helpers */
  1510. static void
  1511. dump_stack_value (ILStackDesc *value)
  1512. {
  1513. printf ("[(%x)(%x)", value->type->type, value->stype);
  1514. if (stack_slot_is_this_pointer (value))
  1515. printf ("[this] ");
  1516. if (stack_slot_is_boxed_value (value))
  1517. printf ("[boxed] ");
  1518. if (stack_slot_is_null_literal (value))
  1519. printf ("[null] ");
  1520. if (stack_slot_is_managed_mutability_pointer (value))
  1521. printf ("Controled Mutability MP: ");
  1522. if (stack_slot_is_managed_pointer (value))
  1523. printf ("Managed Pointer to: ");
  1524. switch (stack_slot_get_underlying_type (value)) {
  1525. case TYPE_INV:
  1526. printf ("invalid type]");
  1527. return;
  1528. case TYPE_I4:
  1529. printf ("int32]");
  1530. return;
  1531. case TYPE_I8:
  1532. printf ("int64]");
  1533. return;
  1534. case TYPE_NATIVE_INT:
  1535. printf ("native int]");
  1536. return;
  1537. case TYPE_R8:
  1538. printf ("float64]");
  1539. return;
  1540. case TYPE_PTR:
  1541. printf ("unmanaged pointer]");
  1542. return;
  1543. case TYPE_COMPLEX:
  1544. switch (value->type->type) {
  1545. case MONO_TYPE_CLASS:
  1546. case MONO_TYPE_VALUETYPE:
  1547. printf ("complex] (%s)", value->type->data.klass->name);
  1548. return;
  1549. case MONO_TYPE_STRING:
  1550. printf ("complex] (string)");
  1551. return;
  1552. case MONO_TYPE_OBJECT:
  1553. printf ("complex] (object)");
  1554. return;
  1555. case MONO_TYPE_SZARRAY:
  1556. printf ("complex] (%s [])", value->type->data.klass->name);
  1557. return;
  1558. case MONO_TYPE_ARRAY:
  1559. printf ("complex] (%s [%d %d %d])",
  1560. value->type->data.array->eklass->name,
  1561. value->type->data.array->rank,
  1562. value->type->data.array->numsizes,
  1563. value->type->data.array->numlobounds);
  1564. return;
  1565. case MONO_TYPE_GENERICINST:
  1566. printf ("complex] (inst of %s )", value->type->data.generic_class->container_class->name);
  1567. return;
  1568. case MONO_TYPE_VAR:
  1569. printf ("complex] (type generic param !%d - %s) ", value->type->data.generic_param->num, mono_generic_param_info (value->type->data.generic_param)->name);
  1570. return;
  1571. case MONO_TYPE_MVAR:
  1572. printf ("complex] (method generic param !!%d - %s) ", value->type->data.generic_param->num, mono_generic_param_info (value->type->data.generic_param)->name);
  1573. return;
  1574. default: {
  1575. //should be a boxed value
  1576. char * name = mono_type_full_name (value->type);
  1577. printf ("complex] %s", name);
  1578. g_free (name);
  1579. return;
  1580. }
  1581. }
  1582. default:
  1583. printf ("unknown stack %x type]\n", value->stype);
  1584. g_assert_not_reached ();
  1585. }
  1586. }
  1587. static void
  1588. dump_stack_state (ILCodeDesc *state)
  1589. {
  1590. int i;
  1591. printf ("(%d) ", state->size);
  1592. for (i = 0; i < state->size; ++i)
  1593. dump_stack_value (state->stack + i);
  1594. printf ("\n");
  1595. }
  1596. #endif
  1597. /*Returns TRUE if candidate array type can be assigned to target.
  1598. *Both parameters MUST be of type MONO_TYPE_ARRAY (target->type == MONO_TYPE_ARRAY)
  1599. */
  1600. static gboolean
  1601. is_array_type_compatible (MonoType *target, MonoType *candidate)
  1602. {
  1603. MonoArrayType *left = target->data.array;
  1604. MonoArrayType *right = candidate->data.array;
  1605. g_assert (target->type == MONO_TYPE_ARRAY);
  1606. g_assert (candidate->type == MONO_TYPE_ARRAY);
  1607. if (left->rank != right->rank)
  1608. return FALSE;
  1609. return verifier_class_is_assignable_from (left->eklass, right->eklass);
  1610. }
  1611. static int
  1612. get_stack_type (MonoType *type)
  1613. {
  1614. int mask = 0;
  1615. int type_kind = type->type;
  1616. if (type->byref)
  1617. mask = POINTER_MASK;
  1618. /*TODO handle CMMP_MASK */
  1619. handle_enum:
  1620. switch (type_kind) {
  1621. case MONO_TYPE_I1:
  1622. case MONO_TYPE_U1:
  1623. case MONO_TYPE_BOOLEAN:
  1624. case MONO_TYPE_I2:
  1625. case MONO_TYPE_U2:
  1626. case MONO_TYPE_CHAR:
  1627. case MONO_TYPE_I4:
  1628. case MONO_TYPE_U4:
  1629. return TYPE_I4 | mask;
  1630. case MONO_TYPE_I:
  1631. case MONO_TYPE_U:
  1632. return TYPE_NATIVE_INT | mask;
  1633. /* FIXME: the spec says that you cannot have a pointer to method pointer, do we need to check this here? */
  1634. case MONO_TYPE_FNPTR:
  1635. case MONO_TYPE_PTR:
  1636. case MONO_TYPE_TYPEDBYREF:
  1637. return TYPE_PTR | mask;
  1638. case MONO_TYPE_VAR:
  1639. case MONO_TYPE_MVAR:
  1640. case MONO_TYPE_CLASS:
  1641. case MONO_TYPE_STRING:
  1642. case MONO_TYPE_OBJECT:
  1643. case MONO_TYPE_SZARRAY:
  1644. case MONO_TYPE_ARRAY:
  1645. return TYPE_COMPLEX | mask;
  1646. case MONO_TYPE_I8:
  1647. case MONO_TYPE_U8:
  1648. return TYPE_I8 | mask;
  1649. case MONO_TYPE_R4:
  1650. case MONO_TYPE_R8:
  1651. return TYPE_R8 | mask;
  1652. case MONO_TYPE_GENERICINST:
  1653. case MONO_TYPE_VALUETYPE:
  1654. if (mono_type_is_enum_type (type)) {
  1655. type = mono_type_get_underlying_type_any (type);
  1656. if (!type)
  1657. return FALSE;
  1658. type_kind = type->type;
  1659. goto handle_enum;
  1660. } else {
  1661. return TYPE_COMPLEX | mask;
  1662. }
  1663. default:
  1664. return TYPE_INV;
  1665. }
  1666. }
  1667. /* convert MonoType to ILStackDesc format (stype) */
  1668. static gboolean
  1669. set_stack_value (VerifyContext *ctx, ILStackDesc *stack, MonoType *type, int take_addr)
  1670. {
  1671. int mask = 0;
  1672. int type_kind = type->type;
  1673. if (type->byref || take_addr)
  1674. mask = POINTER_MASK;
  1675. /* TODO handle CMMP_MASK */
  1676. handle_enum:
  1677. stack->type = type;
  1678. switch (type_kind) {
  1679. case MONO_TYPE_I1:
  1680. case MONO_TYPE_U1:
  1681. case MONO_TYPE_BOOLEAN:
  1682. case MONO_TYPE_I2:
  1683. case MONO_TYPE_U2:
  1684. case MONO_TYPE_CHAR:
  1685. case MONO_TYPE_I4:
  1686. case MONO_TYPE_U4:
  1687. stack->stype = TYPE_I4 | mask;
  1688. break;
  1689. case MONO_TYPE_I:
  1690. case MONO_TYPE_U:
  1691. stack->stype = TYPE_NATIVE_INT | mask;
  1692. break;
  1693. /*FIXME: Do we need to check if it's a pointer to the method pointer? The spec says it' illegal to have that.*/
  1694. case MONO_TYPE_FNPTR:
  1695. case MONO_TYPE_PTR:
  1696. case MONO_TYPE_TYPEDBYREF:
  1697. stack->stype = TYPE_PTR | mask;
  1698. break;
  1699. case MONO_TYPE_CLASS:
  1700. case MONO_TYPE_STRING:
  1701. case MONO_TYPE_OBJECT:
  1702. case MONO_TYPE_SZARRAY:
  1703. case MONO_TYPE_ARRAY:
  1704. case MONO_TYPE_VAR:
  1705. case MONO_TYPE_MVAR:
  1706. stack->stype = TYPE_COMPLEX | mask;
  1707. break;
  1708. case MONO_TYPE_I8:
  1709. case MONO_TYPE_U8:
  1710. stack->stype = TYPE_I8 | mask;
  1711. break;
  1712. case MONO_TYPE_R4:
  1713. case MONO_TYPE_R8:
  1714. stack->stype = TYPE_R8 | mask;
  1715. break;
  1716. case MONO_TYPE_GENERICINST:
  1717. case MONO_TYPE_VALUETYPE:
  1718. if (mono_type_is_enum_type (type)) {
  1719. MonoType *utype = mono_type_get_underlying_type_any (type);
  1720. if (!utype) {
  1721. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Could not resolve underlying type of %x at %d", type->type, ctx->ip_offset));
  1722. return FALSE;
  1723. }
  1724. type = utype;
  1725. type_kind = type->type;
  1726. goto handle_enum;
  1727. } else {
  1728. stack->stype = TYPE_COMPLEX | mask;
  1729. break;
  1730. }
  1731. default:
  1732. VERIFIER_DEBUG ( printf ("unknown type 0x%02x in eval stack type\n", type->type); );
  1733. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Illegal value set on stack 0x%02x at %d", type->type, ctx->ip_offset));
  1734. return FALSE;
  1735. }
  1736. return TRUE;
  1737. }
  1738. /*
  1739. * init_stack_with_value_at_exception_boundary:
  1740. *
  1741. * Initialize the stack and push a given type.
  1742. * The instruction is marked as been on the exception boundary.
  1743. */
  1744. static void
  1745. init_stack_with_value_at_exception_boundary (VerifyContext *ctx, ILCodeDesc *code, MonoClass *klass)
  1746. {
  1747. MonoError error;
  1748. MonoType *type = mono_class_inflate_generic_type_checked (&klass->byval_arg, ctx->generic_context, &error);
  1749. if (!mono_error_ok (&error)) {
  1750. char *name = mono_type_get_full_name (klass);
  1751. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid class %s used for exception", name));
  1752. g_free (name);
  1753. mono_error_cleanup (&error);
  1754. return;
  1755. }
  1756. if (!ctx->max_stack) {
  1757. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Stack overflow at 0x%04x", ctx->ip_offset));
  1758. return;
  1759. }
  1760. stack_init (ctx, code);
  1761. ensure_stack_size (code, 1);
  1762. set_stack_value (ctx, code->stack, type, FALSE);
  1763. ctx->exception_types = g_slist_prepend (ctx->exception_types, type);
  1764. code->size = 1;
  1765. code->flags |= IL_CODE_FLAG_WAS_TARGET;
  1766. if (mono_type_is_generic_argument (type))
  1767. code->stack->stype |= BOXED_MASK;
  1768. }
  1769. static MonoClass*
  1770. get_ienumerable_class (void)
  1771. {
  1772. static MonoClass* generic_ienumerable_class = NULL;
  1773. if (generic_ienumerable_class == NULL)
  1774. generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
  1775. "System.Collections.Generic", "IEnumerable`1");
  1776. return generic_ienumerable_class;
  1777. }
  1778. static MonoClass*
  1779. get_icollection_class (void)
  1780. {
  1781. static MonoClass* generic_icollection_class = NULL;
  1782. if (generic_icollection_class == NULL)
  1783. generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
  1784. "System.Collections.Generic", "ICollection`1");
  1785. return generic_icollection_class;
  1786. }
  1787. static MonoClass*
  1788. inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
  1789. {
  1790. MonoType *args [1];
  1791. args [0] = &arg0->byval_arg;
  1792. return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
  1793. }
  1794. static gboolean
  1795. verifier_inflate_and_check_compat (MonoClass *target, MonoClass *gtd, MonoClass *arg)
  1796. {
  1797. MonoClass *tmp;
  1798. if (!(tmp = inflate_class_one_arg (gtd, arg)))
  1799. return FALSE;
  1800. if (mono_class_is_variant_compatible (target, tmp, TRUE))
  1801. return TRUE;
  1802. return FALSE;
  1803. }
  1804. static gboolean
  1805. verifier_class_is_assignable_from (MonoClass *target, MonoClass *candidate)
  1806. {
  1807. MonoClass *iface_gtd;
  1808. if (target == candidate)
  1809. return TRUE;
  1810. if (mono_class_has_variant_generic_params (target)) {
  1811. if (MONO_CLASS_IS_INTERFACE (target)) {
  1812. if (candidate->rank == 1) {
  1813. if (verifier_inflate_and_check_compat (target, mono_defaults.generic_ilist_class, candidate->element_class))
  1814. return TRUE;
  1815. if (verifier_inflate_and_check_compat (target, get_icollection_class (), candidate->element_class))
  1816. return TRUE;
  1817. if (verifier_inflate_and_check_compat (target, get_ienumerable_class (), candidate->element_class))
  1818. return TRUE;
  1819. } else {
  1820. MonoError error;
  1821. int i;
  1822. while (candidate && candidate != mono_defaults.object_class) {
  1823. mono_class_setup_interfaces (candidate, &error);
  1824. if (!mono_error_ok (&error)) {
  1825. mono_error_cleanup (&error);
  1826. return FALSE;
  1827. }
  1828. /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
  1829. for (i = 0; i < candidate->interface_offsets_count; ++i) {
  1830. MonoClass *iface = candidate->interfaces_packed [i];
  1831. if (mono_class_is_variant_compatible (target, iface, TRUE))
  1832. return TRUE;
  1833. }
  1834. for (i = 0; i < candidate->interface_count; ++i) {
  1835. MonoClass *iface = candidate->interfaces [i];
  1836. if (mono_class_is_variant_compatible (target, iface, TRUE))
  1837. return TRUE;
  1838. }
  1839. candidate = candidate->parent;
  1840. }
  1841. }
  1842. } else if (target->delegate) {
  1843. if (mono_class_is_variant_compatible (target, candidate, TRUE))
  1844. return TRUE;
  1845. }
  1846. return FALSE;
  1847. }
  1848. if (mono_class_is_assignable_from (target, candidate))
  1849. return TRUE;
  1850. if (!MONO_CLASS_IS_INTERFACE (target) || !target->generic_class || candidate->rank != 1)
  1851. return FALSE;
  1852. iface_gtd = target->generic_class->container_class;
  1853. if (iface_gtd != mono_defaults.generic_ilist_class && iface_gtd != get_icollection_class () && iface_gtd != get_ienumerable_class ())
  1854. return FALSE;
  1855. target = mono_class_from_mono_type (target->generic_class->context.class_inst->type_argv [0]);
  1856. candidate = candidate->element_class;
  1857. return TRUE;
  1858. }
  1859. /*Verify if type 'candidate' can be stored in type 'target'.
  1860. *
  1861. * If strict, check for the underlying type and not the verification stack types
  1862. */
  1863. static gboolean
  1864. verify_type_compatibility_full (VerifyContext *ctx, MonoType *target, MonoType *candidate, gboolean strict)
  1865. {
  1866. #define IS_ONE_OF3(T, A, B, C) (T == A || T == B || T == C)
  1867. #define IS_ONE_OF2(T, A, B) (T == A || T == B)
  1868. MonoType *original_candidate = candidate;
  1869. VERIFIER_DEBUG ( printf ("checking type compatibility %s x %s strict %d\n", mono_type_full_name (target), mono_type_full_name (candidate), strict); );
  1870. /*only one is byref */
  1871. if (candidate->byref ^ target->byref) {
  1872. /* converting from native int to byref*/
  1873. if (get_stack_type (candidate) == TYPE_NATIVE_INT && target->byref) {
  1874. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("using byref native int at 0x%04x", ctx->ip_offset));
  1875. return TRUE;
  1876. }
  1877. return FALSE;
  1878. }
  1879. strict |= target->byref;
  1880. /*From now on we don't care about byref anymore, so it's ok to discard it here*/
  1881. candidate = mono_type_get_underlying_type_any (candidate);
  1882. handle_enum:
  1883. switch (target->type) {
  1884. case MONO_TYPE_VOID:
  1885. return candidate->type == MONO_TYPE_VOID;
  1886. case MONO_TYPE_I1:
  1887. case MONO_TYPE_U1:
  1888. case MONO_TYPE_BOOLEAN:
  1889. if (strict)
  1890. return IS_ONE_OF3 (candidate->type, MONO_TYPE_I1, MONO_TYPE_U1, MONO_TYPE_BOOLEAN);
  1891. case MONO_TYPE_I2:
  1892. case MONO_TYPE_U2:
  1893. case MONO_TYPE_CHAR:
  1894. if (strict)
  1895. return IS_ONE_OF3 (candidate->type, MONO_TYPE_I2, MONO_TYPE_U2, MONO_TYPE_CHAR);
  1896. case MONO_TYPE_I4:
  1897. case MONO_TYPE_U4: {
  1898. gboolean is_native_int = IS_ONE_OF2 (candidate->type, MONO_TYPE_I, MONO_TYPE_U);
  1899. gboolean is_int4 = IS_ONE_OF2 (candidate->type, MONO_TYPE_I4, MONO_TYPE_U4);
  1900. if (strict)
  1901. return is_native_int || is_int4;
  1902. return is_native_int || get_stack_type (candidate) == TYPE_I4;
  1903. }
  1904. case MONO_TYPE_I8:
  1905. case MONO_TYPE_U8:
  1906. return IS_ONE_OF2 (candidate->type, MONO_TYPE_I8, MONO_TYPE_U8);
  1907. case MONO_TYPE_R4:
  1908. case MONO_TYPE_R8:
  1909. if (strict)
  1910. return candidate->type == target->type;
  1911. return IS_ONE_OF2 (candidate->type, MONO_TYPE_R4, MONO_TYPE_R8);
  1912. case MONO_TYPE_I:
  1913. case MONO_TYPE_U: {
  1914. gboolean is_native_int = IS_ONE_OF2 (candidate->type, MONO_TYPE_I, MONO_TYPE_U);
  1915. gboolean is_int4 = IS_ONE_OF2 (candidate->type, MONO_TYPE_I4, MONO_TYPE_U4);
  1916. if (strict)
  1917. return is_native_int || is_int4;
  1918. return is_native_int || get_stack_type (candidate) == TYPE_I4;
  1919. }
  1920. case MONO_TYPE_PTR:
  1921. if (candidate->type != MONO_TYPE_PTR)
  1922. return FALSE;
  1923. /* check the underlying type */
  1924. return verify_type_compatibility_full (ctx, target->data.type, candidate->data.type, TRUE);
  1925. case MONO_TYPE_FNPTR: {
  1926. MonoMethodSignature *left, *right;
  1927. if (candidate->type != MONO_TYPE_FNPTR)
  1928. return FALSE;
  1929. left = mono_type_get_signature (target);
  1930. right = mono_type_get_signature (candidate);
  1931. return mono_metadata_signature_equal (left, right) && left->call_convention == right->call_convention;
  1932. }
  1933. case MONO_TYPE_GENERICINST: {
  1934. MonoClass *target_klass;
  1935. MonoClass *candidate_klass;
  1936. if (mono_type_is_enum_type (target)) {
  1937. target = mono_type_get_underlying_type_any (target);
  1938. if (!target)
  1939. return FALSE;
  1940. goto handle_enum;
  1941. }
  1942. /*
  1943. * VAR / MVAR compatibility must be checked by verify_stack_type_compatibility
  1944. * to take boxing status into account.
  1945. */
  1946. if (mono_type_is_generic_argument (original_candidate))
  1947. return FALSE;
  1948. target_klass = mono_class_from_mono_type (target);
  1949. candidate_klass = mono_class_from_mono_type (candidate);
  1950. if (mono_class_is_nullable (target_klass)) {
  1951. if (!mono_class_is_nullable (candidate_klass))
  1952. return FALSE;
  1953. return target_klass == candidate_klass;
  1954. }
  1955. return verifier_class_is_assignable_from (target_klass, candidate_klass);
  1956. }
  1957. case MONO_TYPE_STRING:
  1958. return candidate->type == MONO_TYPE_STRING;
  1959. case MONO_TYPE_CLASS:
  1960. /*
  1961. * VAR / MVAR compatibility must be checked by verify_stack_type_compatibility
  1962. * to take boxing status into account.
  1963. */
  1964. if (mono_type_is_generic_argument (original_candidate))
  1965. return FALSE;
  1966. if (candidate->type == MONO_TYPE_VALUETYPE)
  1967. return FALSE;
  1968. /* If candidate is an enum it should return true for System.Enum and supertypes.
  1969. * That's why here we use the original type and not the underlying type.
  1970. */
  1971. return verifier_class_is_assignable_from (target->data.klass, mono_class_from_mono_type (original_candidate));
  1972. case MONO_TYPE_OBJECT:
  1973. return MONO_TYPE_IS_REFERENCE (candidate);
  1974. case MONO_TYPE_SZARRAY: {
  1975. MonoClass *left;
  1976. MonoClass *right;
  1977. if (candidate->type != MONO_TYPE_SZARRAY)
  1978. return FALSE;
  1979. left = mono_class_from_mono_type (target);
  1980. right = mono_class_from_mono_type (candidate);
  1981. return verifier_class_is_assignable_from (left, right);
  1982. }
  1983. case MONO_TYPE_ARRAY:
  1984. if (candidate->type != MONO_TYPE_ARRAY)
  1985. return FALSE;
  1986. return is_array_type_compatible (target, candidate);
  1987. case MONO_TYPE_TYPEDBYREF:
  1988. return candidate->type == MONO_TYPE_TYPEDBYREF;
  1989. case MONO_TYPE_VALUETYPE: {
  1990. MonoClass *target_klass;
  1991. MonoClass *candidate_klass;
  1992. if (candidate->type == MONO_TYPE_CLASS)
  1993. return FALSE;
  1994. target_klass = mono_class_from_mono_type (target);
  1995. candidate_klass = mono_class_from_mono_type (candidate);
  1996. if (target_klass == candidate_klass)
  1997. return TRUE;
  1998. if (mono_type_is_enum_type (target)) {
  1999. target = mono_type_get_underlying_type_any (target);
  2000. if (!target)
  2001. return FALSE;
  2002. goto handle_enum;
  2003. }
  2004. return FALSE;
  2005. }
  2006. case MONO_TYPE_VAR:
  2007. if (candidate->type != MONO_TYPE_VAR)
  2008. return FALSE;
  2009. return mono_type_get_generic_param_num (candidate) == mono_type_get_generic_param_num (target);
  2010. case MONO_TYPE_MVAR:
  2011. if (candidate->type != MONO_TYPE_MVAR)
  2012. return FALSE;
  2013. return mono_type_get_generic_param_num (candidate) == mono_type_get_generic_param_num (target);
  2014. default:
  2015. VERIFIER_DEBUG ( printf ("unknown store type %d\n", target->type); );
  2016. g_assert_not_reached ();
  2017. return FALSE;
  2018. }
  2019. return 1;
  2020. #undef IS_ONE_OF3
  2021. #undef IS_ONE_OF2
  2022. }
  2023. static gboolean
  2024. verify_type_compatibility (VerifyContext *ctx, MonoType *target, MonoType *candidate)
  2025. {
  2026. return verify_type_compatibility_full (ctx, target, candidate, FALSE);
  2027. }
  2028. /*
  2029. * Returns the generic param bound to the context been verified.
  2030. *
  2031. */
  2032. static MonoGenericParam*
  2033. get_generic_param (VerifyContext *ctx, MonoType *param)
  2034. {
  2035. guint16 param_num = mono_type_get_generic_param_num (param);
  2036. if (param->type == MONO_TYPE_VAR) {
  2037. if (!ctx->generic_context->class_inst || ctx->generic_context->class_inst->type_argc <= param_num) {
  2038. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid generic type argument %d", param_num));
  2039. return NULL;
  2040. }
  2041. return ctx->generic_context->class_inst->type_argv [param_num]->data.generic_param;
  2042. }
  2043. /*param must be a MVAR */
  2044. if (!ctx->generic_context->method_inst || ctx->generic_context->method_inst->type_argc <= param_num) {
  2045. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid generic method argument %d", param_num));
  2046. return NULL;
  2047. }
  2048. return ctx->generic_context->method_inst->type_argv [param_num]->data.generic_param;
  2049. }
  2050. static gboolean
  2051. recursive_boxed_constraint_type_check (VerifyContext *ctx, MonoType *type, MonoClass *constraint_class, int recursion_level)
  2052. {
  2053. MonoType *constraint_type = &constraint_class->byval_arg;
  2054. if (recursion_level <= 0)
  2055. return FALSE;
  2056. if (verify_type_compatibility_full (ctx, type, mono_type_get_type_byval (constraint_type), FALSE))
  2057. return TRUE;
  2058. if (mono_type_is_generic_argument (constraint_type)) {
  2059. MonoGenericParam *param = get_generic_param (ctx, constraint_type);
  2060. MonoClass **class;
  2061. if (!param)
  2062. return FALSE;
  2063. for (class = mono_generic_param_info (param)->constraints; class && *class; ++class) {
  2064. if (recursive_boxed_constraint_type_check (ctx, type, *class, recursion_level - 1))
  2065. return TRUE;
  2066. }
  2067. }
  2068. return FALSE;
  2069. }
  2070. /*
  2071. * is_compatible_boxed_valuetype:
  2072. *
  2073. * Returns TRUE if @candidate / @stack is a valid boxed valuetype.
  2074. *
  2075. * @type The source type. It it tested to be of the proper type.
  2076. * @candidate type of the boxed valuetype.
  2077. * @stack stack slot of the boxed valuetype, separate from @candidade since one could be changed before calling this function
  2078. * @strict if TRUE candidate must be boxed compatible to the target type
  2079. *
  2080. */
  2081. static gboolean
  2082. is_compatible_boxed_valuetype (VerifyContext *ctx, MonoType *type, MonoType *candidate, ILStackDesc *stack, gboolean strict)
  2083. {
  2084. if (!stack_slot_is_boxed_value (stack))
  2085. return FALSE;
  2086. if (type->byref || candidate->byref)
  2087. return FALSE;
  2088. if (mono_type_is_generic_argument (candidate)) {
  2089. MonoGenericParam *param = get_generic_param (ctx, candidate);
  2090. MonoClass **class;
  2091. if (!param)
  2092. return FALSE;
  2093. for (class = mono_generic_param_info (param)->constraints; class && *class; ++class) {
  2094. /*256 should be enough since there can't be more than 255 generic arguments.*/
  2095. if (recursive_boxed_constraint_type_check (ctx, type, *class, 256))
  2096. return TRUE;
  2097. }
  2098. }
  2099. if (mono_type_is_generic_argument (type))
  2100. return FALSE;
  2101. if (!strict)
  2102. return TRUE;
  2103. return MONO_TYPE_IS_REFERENCE (type) && verifier_class_is_assignable_from (mono_class_from_mono_type (type), mono_class_from_mono_type (candidate));
  2104. }
  2105. static int
  2106. verify_stack_type_compatibility_full (VerifyContext *ctx, MonoType *type, ILStackDesc *stack, gboolean drop_byref, gboolean valuetype_must_be_boxed)
  2107. {
  2108. MonoType *candidate = mono_type_from_stack_slot (stack);
  2109. if (MONO_TYPE_IS_REFERENCE (type) && !type->byref && stack_slot_is_null_literal (stack))
  2110. return TRUE;
  2111. if (is_compatible_boxed_valuetype (ctx, type, candidate, stack, TRUE))
  2112. return TRUE;
  2113. if (valuetype_must_be_boxed && !stack_slot_is_boxed_value (stack) && !MONO_TYPE_IS_REFERENCE (candidate))
  2114. return FALSE;
  2115. if (!valuetype_must_be_boxed && stack_slot_is_boxed_value (stack))
  2116. return FALSE;
  2117. if (drop_byref)
  2118. return verify_type_compatibility_full (ctx, type, mono_type_get_type_byval (candidate), FALSE);
  2119. return verify_type_compatibility_full (ctx, type, candidate, FALSE);
  2120. }
  2121. static int
  2122. verify_stack_type_compatibility (VerifyContext *ctx, MonoType *type, ILStackDesc *stack)
  2123. {
  2124. return verify_stack_type_compatibility_full (ctx, type, stack, FALSE, FALSE);
  2125. }
  2126. static gboolean
  2127. mono_delegate_type_equal (MonoType *target, MonoType *candidate)
  2128. {
  2129. if (candidate->byref ^ target->byref)
  2130. return FALSE;
  2131. switch (target->type) {
  2132. case MONO_TYPE_VOID:
  2133. case MONO_TYPE_I1:
  2134. case MONO_TYPE_U1:
  2135. case MONO_TYPE_BOOLEAN:
  2136. case MONO_TYPE_I2:
  2137. case MONO_TYPE_U2:
  2138. case MONO_TYPE_CHAR:
  2139. case MONO_TYPE_I4:
  2140. case MONO_TYPE_U4:
  2141. case MONO_TYPE_I8:
  2142. case MONO_TYPE_U8:
  2143. case MONO_TYPE_R4:
  2144. case MONO_TYPE_R8:
  2145. case MONO_TYPE_I:
  2146. case MONO_TYPE_U:
  2147. case MONO_TYPE_STRING:
  2148. case MONO_TYPE_TYPEDBYREF:
  2149. return candidate->type == target->type;
  2150. case MONO_TYPE_PTR:
  2151. if (candidate->type != MONO_TYPE_PTR)
  2152. return FALSE;
  2153. return mono_delegate_type_equal (target->data.type, candidate->data.type);
  2154. case MONO_TYPE_FNPTR:
  2155. if (candidate->type != MONO_TYPE_FNPTR)
  2156. return FALSE;
  2157. return mono_delegate_signature_equal (mono_type_get_signature (target), mono_type_get_signature (candidate), FALSE);
  2158. case MONO_TYPE_GENERICINST: {
  2159. MonoClass *target_klass;
  2160. MonoClass *candidate_klass;
  2161. target_klass = mono_class_from_mono_type (target);
  2162. candidate_klass = mono_class_from_mono_type (candidate);
  2163. /*FIXME handle nullables and enum*/
  2164. return verifier_class_is_assignable_from (target_klass, candidate_klass);
  2165. }
  2166. case MONO_TYPE_OBJECT:
  2167. return MONO_TYPE_IS_REFERENCE (candidate);
  2168. case MONO_TYPE_CLASS:
  2169. return verifier_class_is_assignable_from(target->data.klass, mono_class_from_mono_type (candidate));
  2170. case MONO_TYPE_SZARRAY:
  2171. if (candidate->type != MONO_TYPE_SZARRAY)
  2172. return FALSE;
  2173. return verifier_class_is_assignable_from (mono_class_from_mono_type (target)->element_class, mono_class_from_mono_type (candidate)->element_class);
  2174. case MONO_TYPE_ARRAY:
  2175. if (candidate->type != MONO_TYPE_ARRAY)
  2176. return FALSE;
  2177. return is_array_type_compatible (target, candidate);
  2178. case MONO_TYPE_VALUETYPE:
  2179. /*FIXME handle nullables and enum*/
  2180. return mono_class_from_mono_type (candidate) == mono_class_from_mono_type (target);
  2181. case MONO_TYPE_VAR:
  2182. return candidate->type == MONO_TYPE_VAR && mono_type_get_generic_param_num (target) == mono_type_get_generic_param_num (candidate);
  2183. return FALSE;
  2184. case MONO_TYPE_MVAR:
  2185. return candidate->type == MONO_TYPE_MVAR && mono_type_get_generic_param_num (target) == mono_type_get_generic_param_num (candidate);
  2186. return FALSE;
  2187. default:
  2188. VERIFIER_DEBUG ( printf ("Unknown type %d. Implement me!\n", target->type); );
  2189. g_assert_not_reached ();
  2190. return FALSE;
  2191. }
  2192. }
  2193. static gboolean
  2194. mono_delegate_param_equal (MonoType *delegate, MonoType *method)
  2195. {
  2196. if (mono_metadata_type_equal_full (delegate, method, TRUE))
  2197. return TRUE;
  2198. return mono_delegate_type_equal (method, delegate);
  2199. }
  2200. static gboolean
  2201. mono_delegate_ret_equal (MonoType *delegate, MonoType *method)
  2202. {
  2203. if (mono_metadata_type_equal_full (delegate, method, TRUE))
  2204. return TRUE;
  2205. return mono_delegate_type_equal (delegate, method);
  2206. }
  2207. /*
  2208. * mono_delegate_signature_equal:
  2209. *
  2210. * Compare two signatures in the way expected by delegates.
  2211. *
  2212. * This function only exists due to the fact that it should ignore the 'has_this' part of the signature.
  2213. *
  2214. * FIXME can this function be eliminated and proper metadata functionality be used?
  2215. */
  2216. static gboolean
  2217. mono_delegate_signature_equal (MonoMethodSignature *delegate_sig, MonoMethodSignature *method_sig, gboolean is_static_ldftn)
  2218. {
  2219. int i;
  2220. int method_offset = is_static_ldftn ? 1 : 0;
  2221. if (delegate_sig->param_count + method_offset != method_sig->param_count)
  2222. return FALSE;
  2223. if (delegate_sig->call_convention != method_sig->call_convention)
  2224. return FALSE;
  2225. for (i = 0; i < delegate_sig->param_count; i++) {
  2226. MonoType *p1 = delegate_sig->params [i];
  2227. MonoType *p2 = method_sig->params [i + method_offset];
  2228. if (!mono_delegate_param_equal (p1, p2))
  2229. return FALSE;
  2230. }
  2231. if (!mono_delegate_ret_equal (delegate_sig->ret, method_sig->ret))
  2232. return FALSE;
  2233. return TRUE;
  2234. }
  2235. gboolean
  2236. mono_verifier_is_signature_compatible (MonoMethodSignature *target, MonoMethodSignature *candidate)
  2237. {
  2238. return mono_delegate_signature_equal (target, candidate, FALSE);
  2239. }
  2240. /*
  2241. * verify_ldftn_delegate:
  2242. *
  2243. * Verify properties of ldftn based delegates.
  2244. */
  2245. static void
  2246. verify_ldftn_delegate (VerifyContext *ctx, MonoClass *delegate, ILStackDesc *value, ILStackDesc *funptr)
  2247. {
  2248. MonoMethod *method = funptr->method;
  2249. /*ldftn non-final virtuals only allowed if method is not static,
  2250. * the object is a this arg (comes from a ldarg.0), and there is no starg.0.
  2251. * This rules doesn't apply if the object on stack is a boxed valuetype.
  2252. */
  2253. if ((method->flags & METHOD_ATTRIBUTE_VIRTUAL) && !(method->flags & METHOD_ATTRIBUTE_FINAL) && !(method->klass->flags & TYPE_ATTRIBUTE_SEALED) && !stack_slot_is_boxed_value (value)) {
  2254. /*A stdarg 0 must not happen, we fail here only in fail fast mode to avoid double error reports*/
  2255. if (IS_FAIL_FAST_MODE (ctx) && ctx->has_this_store)
  2256. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid ldftn with virtual function in method with stdarg 0 at 0x%04x", ctx->ip_offset));
  2257. /*current method must not be static*/
  2258. if (ctx->method->flags & METHOD_ATTRIBUTE_STATIC)
  2259. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid ldftn with virtual function at 0x%04x", ctx->ip_offset));
  2260. /*value is the this pointer, loaded using ldarg.0 */
  2261. if (!stack_slot_is_this_pointer (value))
  2262. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid object argument, it is not the this pointer, to ldftn with virtual method at 0x%04x", ctx->ip_offset));
  2263. ctx->code [ctx->ip_offset].flags |= IL_CODE_LDFTN_DELEGATE_NONFINAL_VIRTUAL;
  2264. }
  2265. }
  2266. /*
  2267. * verify_delegate_compatibility:
  2268. *
  2269. * Verify delegate creation sequence.
  2270. *
  2271. */
  2272. static void
  2273. verify_delegate_compatibility (VerifyContext *ctx, MonoClass *delegate, ILStackDesc *value, ILStackDesc *funptr)
  2274. {
  2275. #define IS_VALID_OPCODE(offset, opcode) (ip [ip_offset - offset] == opcode && (ctx->code [ip_offset - offset].flags & IL_CODE_FLAG_SEEN))
  2276. #define IS_LOAD_FUN_PTR(kind) (IS_VALID_OPCODE (6, CEE_PREFIX1) && ip [ip_offset - 5] == kind)
  2277. MonoMethod *invoke, *method;
  2278. const guint8 *ip = ctx->header->code;
  2279. guint32 ip_offset = ctx->ip_offset;
  2280. gboolean is_static_ldftn = FALSE, is_first_arg_bound = FALSE;
  2281. if (stack_slot_get_type (funptr) != TYPE_PTR || !funptr->method) {
  2282. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid function pointer parameter for delegate constructor at 0x%04x", ctx->ip_offset));
  2283. return;
  2284. }
  2285. invoke = mono_get_delegate_invoke (delegate);
  2286. method = funptr->method;
  2287. if (!method || !mono_method_signature (method)) {
  2288. char *name = mono_type_get_full_name (delegate);
  2289. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid method on stack to create delegate %s construction at 0x%04x", name, ctx->ip_offset));
  2290. g_free (name);
  2291. return;
  2292. }
  2293. if (!invoke || !mono_method_signature (invoke)) {
  2294. char *name = mono_type_get_full_name (delegate);
  2295. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Delegate type %s with bad Invoke method at 0x%04x", name, ctx->ip_offset));
  2296. g_free (name);
  2297. return;
  2298. }
  2299. is_static_ldftn = (ip_offset > 5 && IS_LOAD_FUN_PTR (CEE_LDFTN)) && method->flags & METHOD_ATTRIBUTE_STATIC;
  2300. if (is_static_ldftn)
  2301. is_first_arg_bound = mono_method_signature (invoke)->param_count + 1 == mono_method_signature (method)->param_count;
  2302. if (!mono_delegate_signature_equal (mono_method_signature (invoke), mono_method_signature (method), is_first_arg_bound)) {
  2303. char *fun_sig = mono_signature_get_desc (mono_method_signature (method), FALSE);
  2304. char *invoke_sig = mono_signature_get_desc (mono_method_signature (invoke), FALSE);
  2305. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Function pointer signature '%s' doesn't match delegate's signature '%s' at 0x%04x", fun_sig, invoke_sig, ctx->ip_offset));
  2306. g_free (fun_sig);
  2307. g_free (invoke_sig);
  2308. }
  2309. /*
  2310. * Delegate code sequences:
  2311. * [-6] ldftn token
  2312. * newobj ...
  2313. *
  2314. *
  2315. * [-7] dup
  2316. * [-6] ldvirtftn token
  2317. * newobj ...
  2318. *
  2319. * ldftn sequence:*/
  2320. if (ip_offset > 5 && IS_LOAD_FUN_PTR (CEE_LDFTN)) {
  2321. verify_ldftn_delegate (ctx, delegate, value, funptr);
  2322. } else if (ip_offset > 6 && IS_VALID_OPCODE (7, CEE_DUP) && IS_LOAD_FUN_PTR (CEE_LDVIRTFTN)) {
  2323. ctx->code [ip_offset - 6].flags |= IL_CODE_DELEGATE_SEQUENCE;
  2324. }else {
  2325. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid code sequence for delegate creation at 0x%04x", ctx->ip_offset));
  2326. }
  2327. ctx->code [ip_offset].flags |= IL_CODE_DELEGATE_SEQUENCE;
  2328. //general tests
  2329. if (is_first_arg_bound) {
  2330. if (mono_method_signature (method)->param_count == 0 || !verify_stack_type_compatibility_full (ctx, mono_method_signature (method)->params [0], value, FALSE, TRUE))
  2331. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("This object not compatible with function pointer for delegate creation at 0x%04x", ctx->ip_offset));
  2332. } else {
  2333. if (method->flags & METHOD_ATTRIBUTE_STATIC) {
  2334. if (!stack_slot_is_null_literal (value) && !is_first_arg_bound)
  2335. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Non-null this args used with static function for delegate creation at 0x%04x", ctx->ip_offset));
  2336. } else {
  2337. if (!verify_stack_type_compatibility_full (ctx, &method->klass->byval_arg, value, FALSE, TRUE) && !stack_slot_is_null_literal (value))
  2338. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("This object not compatible with function pointer for delegate creation at 0x%04x", ctx->ip_offset));
  2339. }
  2340. }
  2341. if (stack_slot_get_type (value) != TYPE_COMPLEX)
  2342. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid first parameter for delegate creation at 0x%04x", ctx->ip_offset));
  2343. #undef IS_VALID_OPCODE
  2344. #undef IS_LOAD_FUN_PTR
  2345. }
  2346. /* implement the opcode checks*/
  2347. static void
  2348. push_arg (VerifyContext *ctx, unsigned int arg, int take_addr)
  2349. {
  2350. ILStackDesc *top;
  2351. if (arg >= ctx->max_args) {
  2352. if (take_addr)
  2353. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Method doesn't have argument %d", arg + 1));
  2354. else {
  2355. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Method doesn't have argument %d", arg + 1));
  2356. if (check_overflow (ctx)) //FIXME: what sane value could we ever push?
  2357. stack_push_val (ctx, TYPE_I4, &mono_defaults.int32_class->byval_arg);
  2358. }
  2359. } else if (check_overflow (ctx)) {
  2360. /*We must let the value be pushed, otherwise we would get an underflow error*/
  2361. check_unverifiable_type (ctx, ctx->params [arg]);
  2362. if (ctx->params [arg]->byref && take_addr)
  2363. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("ByRef of ByRef at 0x%04x", ctx->ip_offset));
  2364. top = stack_push (ctx);
  2365. if (!set_stack_value (ctx, top, ctx->params [arg], take_addr))
  2366. return;
  2367. if (arg == 0 && !(ctx->method->flags & METHOD_ATTRIBUTE_STATIC)) {
  2368. if (take_addr)
  2369. ctx->has_this_store = TRUE;
  2370. else
  2371. top->stype |= THIS_POINTER_MASK;
  2372. if (mono_method_is_constructor (ctx->method) && !ctx->super_ctor_called && !ctx->method->klass->valuetype)
  2373. top->stype |= UNINIT_THIS_MASK;
  2374. }
  2375. }
  2376. }
  2377. static void
  2378. push_local (VerifyContext *ctx, guint32 arg, int take_addr)
  2379. {
  2380. if (arg >= ctx->num_locals) {
  2381. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Method doesn't have local %d", arg + 1));
  2382. } else if (check_overflow (ctx)) {
  2383. /*We must let the value be pushed, otherwise we would get an underflow error*/
  2384. check_unverifiable_type (ctx, ctx->locals [arg]);
  2385. if (ctx->locals [arg]->byref && take_addr)
  2386. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("ByRef of ByRef at 0x%04x", ctx->ip_offset));
  2387. set_stack_value (ctx, stack_push (ctx), ctx->locals [arg], take_addr);
  2388. }
  2389. }
  2390. static void
  2391. store_arg (VerifyContext *ctx, guint32 arg)
  2392. {
  2393. ILStackDesc *value;
  2394. if (arg >= ctx->max_args) {
  2395. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Method doesn't have argument %d at 0x%04x", arg + 1, ctx->ip_offset));
  2396. if (check_underflow (ctx, 1))
  2397. stack_pop (ctx);
  2398. return;
  2399. }
  2400. if (check_underflow (ctx, 1)) {
  2401. value = stack_pop (ctx);
  2402. if (!verify_stack_type_compatibility (ctx, ctx->params [arg], value)) {
  2403. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Incompatible type %s in argument store at 0x%04x", stack_slot_get_name (value), ctx->ip_offset));
  2404. }
  2405. }
  2406. if (arg == 0 && !(ctx->method->flags & METHOD_ATTRIBUTE_STATIC))
  2407. ctx->has_this_store = 1;
  2408. }
  2409. static void
  2410. store_local (VerifyContext *ctx, guint32 arg)
  2411. {
  2412. ILStackDesc *value;
  2413. if (arg >= ctx->num_locals) {
  2414. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Method doesn't have local var %d at 0x%04x", arg + 1, ctx->ip_offset));
  2415. return;
  2416. }
  2417. /*TODO verify definite assigment */
  2418. if (!check_underflow (ctx, 1))
  2419. return;
  2420. value = stack_pop (ctx);
  2421. if (ctx->locals [arg]->byref && stack_slot_is_managed_mutability_pointer (value))
  2422. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use a readonly managed reference when storing on a local variable at 0x%04x", ctx->ip_offset));
  2423. if (!verify_stack_type_compatibility (ctx, ctx->locals [arg], value)) {
  2424. char *expected = mono_type_full_name (ctx->locals [arg]);
  2425. char *found = stack_slot_full_name (value);
  2426. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Incompatible type '%s' on stack cannot be stored to local %d with type '%s' at 0x%04x",
  2427. found,
  2428. arg,
  2429. expected,
  2430. ctx->ip_offset));
  2431. g_free (expected);
  2432. g_free (found);
  2433. }
  2434. }
  2435. /*FIXME add and sub needs special care here*/
  2436. static void
  2437. do_binop (VerifyContext *ctx, unsigned int opcode, const unsigned char table [TYPE_MAX][TYPE_MAX])
  2438. {
  2439. ILStackDesc *a, *b, *top;
  2440. int idxa, idxb, complexMerge = 0;
  2441. unsigned char res;
  2442. if (!check_underflow (ctx, 2))
  2443. return;
  2444. b = stack_pop (ctx);
  2445. a = stack_pop (ctx);
  2446. idxa = stack_slot_get_underlying_type (a);
  2447. if (stack_slot_is_managed_pointer (a)) {
  2448. idxa = TYPE_PTR;
  2449. complexMerge = 1;
  2450. }
  2451. idxb = stack_slot_get_underlying_type (b);
  2452. if (stack_slot_is_managed_pointer (b)) {
  2453. idxb = TYPE_PTR;
  2454. complexMerge = 2;
  2455. }
  2456. --idxa;
  2457. --idxb;
  2458. res = table [idxa][idxb];
  2459. VERIFIER_DEBUG ( printf ("binop res %d\n", res); );
  2460. VERIFIER_DEBUG ( printf ("idxa %d idxb %d\n", idxa, idxb); );
  2461. top = stack_push (ctx);
  2462. if (res == TYPE_INV) {
  2463. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Binary instruction applyed to ill formed stack (%s x %s)", stack_slot_get_name (a), stack_slot_get_name (b)));
  2464. copy_stack_value (top, a);
  2465. return;
  2466. }
  2467. if (res & NON_VERIFIABLE_RESULT) {
  2468. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Binary instruction is not verifiable (%s x %s)", stack_slot_get_name (a), stack_slot_get_name (b)));
  2469. res = res & ~NON_VERIFIABLE_RESULT;
  2470. }
  2471. if (complexMerge && res == TYPE_PTR) {
  2472. if (complexMerge == 1)
  2473. copy_stack_value (top, a);
  2474. else if (complexMerge == 2)
  2475. copy_stack_value (top, b);
  2476. /*
  2477. * There is no need to merge the type of two pointers.
  2478. * The only valid operation is subtraction, that returns a native
  2479. * int as result and can be used with any 2 pointer kinds.
  2480. * This is valid acording to Patition III 1.1.4
  2481. */
  2482. } else
  2483. top->stype = res;
  2484. }
  2485. static void
  2486. do_boolean_branch_op (VerifyContext *ctx, int delta)
  2487. {
  2488. int target = ctx->ip_offset + delta;
  2489. ILStackDesc *top;
  2490. VERIFIER_DEBUG ( printf ("boolean branch offset %d delta %d target %d\n", ctx->ip_offset, delta, target); );
  2491. if (target < 0 || target >= ctx->code_size) {
  2492. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Boolean branch target out of code at 0x%04x", ctx->ip_offset));
  2493. return;
  2494. }
  2495. switch (is_valid_branch_instruction (ctx->header, ctx->ip_offset, target)) {
  2496. case 1:
  2497. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Branch target escapes out of exception block at 0x%04x", ctx->ip_offset));
  2498. break;
  2499. case 2:
  2500. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Branch target escapes out of exception block at 0x%04x", ctx->ip_offset));
  2501. return;
  2502. }
  2503. ctx->target = target;
  2504. if (!check_underflow (ctx, 1))
  2505. return;
  2506. top = stack_pop (ctx);
  2507. if (!is_valid_bool_arg (top))
  2508. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Argument type %s not valid for brtrue/brfalse at 0x%04x", stack_slot_get_name (top), ctx->ip_offset));
  2509. check_unmanaged_pointer (ctx, top);
  2510. }
  2511. static gboolean
  2512. stack_slot_is_complex_type_not_reference_type (ILStackDesc *slot)
  2513. {
  2514. return stack_slot_get_type (slot) == TYPE_COMPLEX && !MONO_TYPE_IS_REFERENCE (slot->type) && !stack_slot_is_boxed_value (slot);
  2515. }
  2516. static void
  2517. do_branch_op (VerifyContext *ctx, signed int delta, const unsigned char table [TYPE_MAX][TYPE_MAX])
  2518. {
  2519. ILStackDesc *a, *b;
  2520. int idxa, idxb;
  2521. unsigned char res;
  2522. int target = ctx->ip_offset + delta;
  2523. VERIFIER_DEBUG ( printf ("branch offset %d delta %d target %d\n", ctx->ip_offset, delta, target); );
  2524. if (target < 0 || target >= ctx->code_size) {
  2525. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Branch target out of code at 0x%04x", ctx->ip_offset));
  2526. return;
  2527. }
  2528. switch (is_valid_cmp_branch_instruction (ctx->header, ctx->ip_offset, target)) {
  2529. case 1: /*FIXME use constants and not magic numbers.*/
  2530. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Branch target escapes out of exception block at 0x%04x", ctx->ip_offset));
  2531. break;
  2532. case 2:
  2533. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Branch target escapes out of exception block at 0x%04x", ctx->ip_offset));
  2534. return;
  2535. }
  2536. ctx->target = target;
  2537. if (!check_underflow (ctx, 2))
  2538. return;
  2539. b = stack_pop (ctx);
  2540. a = stack_pop (ctx);
  2541. idxa = stack_slot_get_underlying_type (a);
  2542. if (stack_slot_is_managed_pointer (a))
  2543. idxa = TYPE_PTR;
  2544. idxb = stack_slot_get_underlying_type (b);
  2545. if (stack_slot_is_managed_pointer (b))
  2546. idxb = TYPE_PTR;
  2547. if (stack_slot_is_complex_type_not_reference_type (a) || stack_slot_is_complex_type_not_reference_type (b)) {
  2548. res = TYPE_INV;
  2549. } else {
  2550. --idxa;
  2551. --idxb;
  2552. res = table [idxa][idxb];
  2553. }
  2554. VERIFIER_DEBUG ( printf ("branch res %d\n", res); );
  2555. VERIFIER_DEBUG ( printf ("idxa %d idxb %d\n", idxa, idxb); );
  2556. if (res == TYPE_INV) {
  2557. CODE_NOT_VERIFIABLE (ctx,
  2558. g_strdup_printf ("Compare and Branch instruction applyed to ill formed stack (%s x %s) at 0x%04x", stack_slot_get_name (a), stack_slot_get_name (b), ctx->ip_offset));
  2559. } else if (res & NON_VERIFIABLE_RESULT) {
  2560. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Compare and Branch instruction is not verifiable (%s x %s) at 0x%04x", stack_slot_get_name (a), stack_slot_get_name (b), ctx->ip_offset));
  2561. res = res & ~NON_VERIFIABLE_RESULT;
  2562. }
  2563. }
  2564. static void
  2565. do_cmp_op (VerifyContext *ctx, const unsigned char table [TYPE_MAX][TYPE_MAX], guint32 opcode)
  2566. {
  2567. ILStackDesc *a, *b;
  2568. int idxa, idxb;
  2569. unsigned char res;
  2570. if (!check_underflow (ctx, 2))
  2571. return;
  2572. b = stack_pop (ctx);
  2573. a = stack_pop (ctx);
  2574. if (opcode == CEE_CGT_UN) {
  2575. if (stack_slot_get_type (a) == TYPE_COMPLEX && stack_slot_get_type (b) == TYPE_COMPLEX) {
  2576. stack_push_val (ctx, TYPE_I4, &mono_defaults.int32_class->byval_arg);
  2577. return;
  2578. }
  2579. }
  2580. idxa = stack_slot_get_underlying_type (a);
  2581. if (stack_slot_is_managed_pointer (a))
  2582. idxa = TYPE_PTR;
  2583. idxb = stack_slot_get_underlying_type (b);
  2584. if (stack_slot_is_managed_pointer (b))
  2585. idxb = TYPE_PTR;
  2586. if (stack_slot_is_complex_type_not_reference_type (a) || stack_slot_is_complex_type_not_reference_type (b)) {
  2587. res = TYPE_INV;
  2588. } else {
  2589. --idxa;
  2590. --idxb;
  2591. res = table [idxa][idxb];
  2592. }
  2593. if(res == TYPE_INV) {
  2594. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf("Compare instruction applyed to ill formed stack (%s x %s) at 0x%04x", stack_slot_get_name (a), stack_slot_get_name (b), ctx->ip_offset));
  2595. } else if (res & NON_VERIFIABLE_RESULT) {
  2596. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Compare instruction is not verifiable (%s x %s) at 0x%04x", stack_slot_get_name (a), stack_slot_get_name (b), ctx->ip_offset));
  2597. res = res & ~NON_VERIFIABLE_RESULT;
  2598. }
  2599. stack_push_val (ctx, TYPE_I4, &mono_defaults.int32_class->byval_arg);
  2600. }
  2601. static void
  2602. do_ret (VerifyContext *ctx)
  2603. {
  2604. MonoType *ret = ctx->signature->ret;
  2605. VERIFIER_DEBUG ( printf ("checking ret\n"); );
  2606. if (ret->type != MONO_TYPE_VOID) {
  2607. ILStackDesc *top;
  2608. if (!check_underflow (ctx, 1))
  2609. return;
  2610. top = stack_pop(ctx);
  2611. if (!verify_stack_type_compatibility (ctx, ctx->signature->ret, top)) {
  2612. char *ret_type = mono_type_full_name (ctx->signature->ret);
  2613. char *stack_type = stack_slot_full_name (top);
  2614. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Incompatible return value on stack with method signature, expected '%s' but got '%s' at 0x%04x", ret_type, stack_type, ctx->ip_offset));
  2615. g_free (stack_type);
  2616. g_free (ret_type);
  2617. return;
  2618. }
  2619. if (ret->byref || ret->type == MONO_TYPE_TYPEDBYREF || mono_type_is_value_type (ret, "System", "ArgIterator") || mono_type_is_value_type (ret, "System", "RuntimeArgumentHandle"))
  2620. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Method returns byref, TypedReference, ArgIterator or RuntimeArgumentHandle at 0x%04x", ctx->ip_offset));
  2621. }
  2622. if (ctx->eval.size > 0) {
  2623. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Stack not empty (%d) after ret at 0x%04x", ctx->eval.size, ctx->ip_offset));
  2624. }
  2625. if (in_any_block (ctx->header, ctx->ip_offset))
  2626. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("ret cannot escape exception blocks at 0x%04x", ctx->ip_offset));
  2627. }
  2628. /*
  2629. * FIXME we need to fix the case of a non-virtual instance method defined in the parent but call using a token pointing to a subclass.
  2630. * This is illegal but mono_get_method_full decoded it.
  2631. * TODO handle calling .ctor outside one or calling the .ctor for other class but super
  2632. */
  2633. static void
  2634. do_invoke_method (VerifyContext *ctx, int method_token, gboolean virtual)
  2635. {
  2636. int param_count, i;
  2637. MonoMethodSignature *sig;
  2638. ILStackDesc *value;
  2639. MonoMethod *method;
  2640. gboolean virt_check_this = FALSE;
  2641. gboolean constrained = ctx->prefix_set & PREFIX_CONSTRAINED;
  2642. if (!(method = verifier_load_method (ctx, method_token, virtual ? "callvirt" : "call")))
  2643. return;
  2644. if (virtual) {
  2645. CLEAR_PREFIX (ctx, PREFIX_CONSTRAINED);
  2646. if (method->klass->valuetype) // && !constrained ???
  2647. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use callvirtual with valuetype method at 0x%04x", ctx->ip_offset));
  2648. if ((method->flags & METHOD_ATTRIBUTE_STATIC))
  2649. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use callvirtual with static method at 0x%04x", ctx->ip_offset));
  2650. } else {
  2651. if (method->flags & METHOD_ATTRIBUTE_ABSTRACT)
  2652. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use call with an abstract method at 0x%04x", ctx->ip_offset));
  2653. if ((method->flags & METHOD_ATTRIBUTE_VIRTUAL) && !(method->flags & METHOD_ATTRIBUTE_FINAL) && !(method->klass->flags & TYPE_ATTRIBUTE_SEALED)) {
  2654. virt_check_this = TRUE;
  2655. ctx->code [ctx->ip_offset].flags |= IL_CODE_CALL_NONFINAL_VIRTUAL;
  2656. }
  2657. }
  2658. if (!(sig = mono_method_get_signature_full (method, ctx->image, method_token, ctx->generic_context)))
  2659. sig = mono_method_get_signature (method, ctx->image, method_token);
  2660. if (!sig) {
  2661. char *name = mono_type_get_full_name (method->klass);
  2662. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Could not resolve signature of %s:%s at 0x%04x", name, method->name, ctx->ip_offset));
  2663. g_free (name);
  2664. return;
  2665. }
  2666. param_count = sig->param_count + sig->hasthis;
  2667. if (!check_underflow (ctx, param_count))
  2668. return;
  2669. for (i = sig->param_count - 1; i >= 0; --i) {
  2670. VERIFIER_DEBUG ( printf ("verifying argument %d\n", i); );
  2671. value = stack_pop (ctx);
  2672. if (!verify_stack_type_compatibility (ctx, sig->params[i], value)) {
  2673. char *stack_name = stack_slot_full_name (value);
  2674. char *sig_name = mono_type_full_name (sig->params [i]);
  2675. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Incompatible parameter with function signature: Calling method with signature (%s) but for argument %d there is a (%s) on stack at 0x%04x", sig_name, i, stack_name, ctx->ip_offset));
  2676. g_free (stack_name);
  2677. g_free (sig_name);
  2678. }
  2679. if (stack_slot_is_managed_mutability_pointer (value))
  2680. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use a readonly pointer as argument of %s at 0x%04x", virtual ? "callvirt" : "call", ctx->ip_offset));
  2681. if ((ctx->prefix_set & PREFIX_TAIL) && stack_slot_is_managed_pointer (value)) {
  2682. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Cannot pass a byref argument to a tail %s at 0x%04x", virtual ? "callvirt" : "call", ctx->ip_offset));
  2683. return;
  2684. }
  2685. }
  2686. if (sig->hasthis) {
  2687. MonoType *type = &method->klass->byval_arg;
  2688. ILStackDesc copy;
  2689. if (mono_method_is_constructor (method) && !method->klass->valuetype) {
  2690. if (IS_STRICT_MODE (ctx) && !mono_method_is_constructor (ctx->method))
  2691. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot call a constructor outside one at 0x%04x", ctx->ip_offset));
  2692. if (IS_STRICT_MODE (ctx) && method->klass != ctx->method->klass->parent && method->klass != ctx->method->klass)
  2693. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot call a constructor of a type different from this or super at 0x%04x", ctx->ip_offset));
  2694. ctx->super_ctor_called = TRUE;
  2695. value = stack_pop_safe (ctx);
  2696. if (IS_STRICT_MODE (ctx) && (value->stype & THIS_POINTER_MASK) != THIS_POINTER_MASK)
  2697. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid 'this ptr' argument for constructor at 0x%04x", ctx->ip_offset));
  2698. } else {
  2699. value = stack_pop (ctx);
  2700. }
  2701. copy_stack_value (&copy, value);
  2702. //TODO we should extract this to a 'drop_byref_argument' and use everywhere
  2703. //Other parts of the code suffer from the same issue of
  2704. copy.type = mono_type_get_type_byval (copy.type);
  2705. copy.stype &= ~POINTER_MASK;
  2706. if (virt_check_this && !stack_slot_is_this_pointer (value) && !(method->klass->valuetype || stack_slot_is_boxed_value (value)))
  2707. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use the call opcode with a non-final virtual method on an object different than the 'this' pointer at 0x%04x", ctx->ip_offset));
  2708. if (constrained && virtual) {
  2709. if (!stack_slot_is_managed_pointer (value))
  2710. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Object is not a managed pointer for a constrained call at 0x%04x", ctx->ip_offset));
  2711. if (!mono_metadata_type_equal_full (mono_type_get_type_byval (value->type), ctx->constrained_type, TRUE))
  2712. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Object not compatible with constrained type at 0x%04x", ctx->ip_offset));
  2713. copy.stype |= BOXED_MASK;
  2714. } else {
  2715. if (stack_slot_is_managed_pointer (value) && !mono_class_from_mono_type (value->type)->valuetype)
  2716. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot call a reference type using a managed pointer to the this arg at 0x%04x", ctx->ip_offset));
  2717. if (!virtual && mono_class_from_mono_type (value->type)->valuetype && !method->klass->valuetype && !stack_slot_is_boxed_value (value))
  2718. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot call a valuetype baseclass at 0x%04x", ctx->ip_offset));
  2719. if (virtual && mono_class_from_mono_type (value->type)->valuetype && !stack_slot_is_boxed_value (value))
  2720. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use a valuetype with callvirt at 0x%04x", ctx->ip_offset));
  2721. if (method->klass->valuetype && (stack_slot_is_boxed_value (value) || !stack_slot_is_managed_pointer (value)))
  2722. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use a boxed or literal valuetype to call a valuetype method at 0x%04x", ctx->ip_offset));
  2723. }
  2724. if (!verify_stack_type_compatibility (ctx, type, &copy)) {
  2725. char *expected = mono_type_full_name (type);
  2726. char *effective = stack_slot_full_name (&copy);
  2727. char *method_name = mono_method_full_name (method, TRUE);
  2728. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Incompatible this argument on stack with method signature expected '%s' but got '%s' for a call to '%s' at 0x%04x",
  2729. expected, effective, method_name, ctx->ip_offset));
  2730. g_free (method_name);
  2731. g_free (effective);
  2732. g_free (expected);
  2733. }
  2734. if (!IS_SKIP_VISIBILITY (ctx) && !mono_method_can_access_method_full (ctx->method, method, mono_class_from_mono_type (value->type))) {
  2735. char *name = mono_method_full_name (method, TRUE);
  2736. CODE_NOT_VERIFIABLE2 (ctx, g_strdup_printf ("Method %s is not accessible at 0x%04x", name, ctx->ip_offset), MONO_EXCEPTION_METHOD_ACCESS);
  2737. g_free (name);
  2738. }
  2739. } else if (!IS_SKIP_VISIBILITY (ctx) && !mono_method_can_access_method_full (ctx->method, method, NULL)) {
  2740. char *name = mono_method_full_name (method, TRUE);
  2741. CODE_NOT_VERIFIABLE2 (ctx, g_strdup_printf ("Method %s is not accessible at 0x%04x", name, ctx->ip_offset), MONO_EXCEPTION_METHOD_ACCESS);
  2742. g_free (name);
  2743. }
  2744. if (sig->ret->type != MONO_TYPE_VOID) {
  2745. if (!mono_type_is_valid_in_context (ctx, sig->ret))
  2746. return;
  2747. if (check_overflow (ctx)) {
  2748. value = stack_push (ctx);
  2749. set_stack_value (ctx, value, sig->ret, FALSE);
  2750. if ((ctx->prefix_set & PREFIX_READONLY) && method->klass->rank && !strcmp (method->name, "Address")) {
  2751. ctx->prefix_set &= ~PREFIX_READONLY;
  2752. value->stype |= CMMP_MASK;
  2753. }
  2754. }
  2755. }
  2756. if ((ctx->prefix_set & PREFIX_TAIL)) {
  2757. if (!mono_delegate_ret_equal (mono_method_signature (ctx->method)->ret, sig->ret))
  2758. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Tail call with incompatible return type at 0x%04x", ctx->ip_offset));
  2759. if (ctx->header->code [ctx->ip_offset + 5] != CEE_RET)
  2760. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Tail call not followed by ret at 0x%04x", ctx->ip_offset));
  2761. }
  2762. }
  2763. static void
  2764. do_push_static_field (VerifyContext *ctx, int token, gboolean take_addr)
  2765. {
  2766. MonoClassField *field;
  2767. MonoClass *klass;
  2768. if (!check_overflow (ctx))
  2769. return;
  2770. if (!take_addr)
  2771. CLEAR_PREFIX (ctx, PREFIX_VOLATILE);
  2772. if (!(field = verifier_load_field (ctx, token, &klass, take_addr ? "ldsflda" : "ldsfld")))
  2773. return;
  2774. if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
  2775. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Cannot load non static field at 0x%04x", ctx->ip_offset));
  2776. return;
  2777. }
  2778. /*taking the address of initonly field only works from the static constructor */
  2779. if (take_addr && (field->type->attrs & FIELD_ATTRIBUTE_INIT_ONLY) &&
  2780. !(field->parent == ctx->method->klass && (ctx->method->flags & (METHOD_ATTRIBUTE_SPECIAL_NAME | METHOD_ATTRIBUTE_STATIC)) && !strcmp (".cctor", ctx->method->name)))
  2781. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot take the address of a init-only field at 0x%04x", ctx->ip_offset));
  2782. if (!IS_SKIP_VISIBILITY (ctx) && !mono_method_can_access_field_full (ctx->method, field, NULL))
  2783. CODE_NOT_VERIFIABLE2 (ctx, g_strdup_printf ("Type at stack is not accessible at 0x%04x", ctx->ip_offset), MONO_EXCEPTION_FIELD_ACCESS);
  2784. set_stack_value (ctx, stack_push (ctx), field->type, take_addr);
  2785. }
  2786. static void
  2787. do_store_static_field (VerifyContext *ctx, int token) {
  2788. MonoClassField *field;
  2789. MonoClass *klass;
  2790. ILStackDesc *value;
  2791. CLEAR_PREFIX (ctx, PREFIX_VOLATILE);
  2792. if (!check_underflow (ctx, 1))
  2793. return;
  2794. value = stack_pop (ctx);
  2795. if (!(field = verifier_load_field (ctx, token, &klass, "stsfld")))
  2796. return;
  2797. if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
  2798. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Cannot store non static field at 0x%04x", ctx->ip_offset));
  2799. return;
  2800. }
  2801. if (field->type->type == MONO_TYPE_TYPEDBYREF) {
  2802. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Typedbyref field is an unverfiable type in store static field at 0x%04x", ctx->ip_offset));
  2803. return;
  2804. }
  2805. if (!IS_SKIP_VISIBILITY (ctx) && !mono_method_can_access_field_full (ctx->method, field, NULL))
  2806. CODE_NOT_VERIFIABLE2 (ctx, g_strdup_printf ("Type at stack is not accessible at 0x%04x", ctx->ip_offset), MONO_EXCEPTION_FIELD_ACCESS);
  2807. if (!verify_stack_type_compatibility (ctx, field->type, value)) {
  2808. char *stack_name = stack_slot_full_name (value);
  2809. char *field_name = mono_type_full_name (field->type);
  2810. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Incompatible type in static field store expected '%s' but found '%s' at 0x%04x",
  2811. field_name, stack_name, ctx->ip_offset));
  2812. g_free (field_name);
  2813. g_free (stack_name);
  2814. }
  2815. }
  2816. static gboolean
  2817. check_is_valid_type_for_field_ops (VerifyContext *ctx, int token, ILStackDesc *obj, MonoClassField **ret_field, const char *opcode)
  2818. {
  2819. MonoClassField *field;
  2820. MonoClass *klass;
  2821. gboolean is_pointer;
  2822. /*must be a reference type, a managed pointer, an unamanaged pointer, or a valuetype*/
  2823. if (!(field = verifier_load_field (ctx, token, &klass, opcode)))
  2824. return FALSE;
  2825. *ret_field = field;
  2826. //the value on stack is going to be used as a pointer
  2827. is_pointer = stack_slot_get_type (obj) == TYPE_PTR || (stack_slot_get_type (obj) == TYPE_NATIVE_INT && !get_stack_type (&field->parent->byval_arg));
  2828. if (field->type->type == MONO_TYPE_TYPEDBYREF) {
  2829. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Typedbyref field is an unverfiable type at 0x%04x", ctx->ip_offset));
  2830. return FALSE;
  2831. }
  2832. g_assert (obj->type);
  2833. /*The value on the stack must be a subclass of the defining type of the field*/
  2834. /* we need to check if we can load the field from the stack value*/
  2835. if (is_pointer) {
  2836. if (stack_slot_get_underlying_type (obj) == TYPE_NATIVE_INT)
  2837. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Native int is not a verifiable type to reference a field at 0x%04x", ctx->ip_offset));
  2838. if (!IS_SKIP_VISIBILITY (ctx) && !mono_method_can_access_field_full (ctx->method, field, NULL))
  2839. CODE_NOT_VERIFIABLE2 (ctx, g_strdup_printf ("Type at stack is not accessible at 0x%04x", ctx->ip_offset), MONO_EXCEPTION_FIELD_ACCESS);
  2840. } else {
  2841. if (!field->parent->valuetype && stack_slot_is_managed_pointer (obj))
  2842. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Type at stack is a managed pointer to a reference type and is not compatible to reference the field at 0x%04x", ctx->ip_offset));
  2843. /*a value type can be loaded from a value or a managed pointer, but not a boxed object*/
  2844. if (field->parent->valuetype && stack_slot_is_boxed_value (obj))
  2845. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Type at stack is a boxed valuetype and is not compatible to reference the field at 0x%04x", ctx->ip_offset));
  2846. if (!stack_slot_is_null_literal (obj) && !verify_stack_type_compatibility_full (ctx, &field->parent->byval_arg, obj, TRUE, FALSE)) {
  2847. char *found = stack_slot_full_name (obj);
  2848. char *expected = mono_type_full_name (&field->parent->byval_arg);
  2849. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Expected type '%s' but found '%s' referencing the 'this' argument at 0x%04x", expected, found, ctx->ip_offset));
  2850. g_free (found);
  2851. g_free (expected);
  2852. }
  2853. if (!IS_SKIP_VISIBILITY (ctx) && !mono_method_can_access_field_full (ctx->method, field, mono_class_from_mono_type (obj->type)))
  2854. CODE_NOT_VERIFIABLE2 (ctx, g_strdup_printf ("Type at stack is not accessible at 0x%04x", ctx->ip_offset), MONO_EXCEPTION_FIELD_ACCESS);
  2855. }
  2856. check_unmanaged_pointer (ctx, obj);
  2857. return TRUE;
  2858. }
  2859. static void
  2860. do_push_field (VerifyContext *ctx, int token, gboolean take_addr)
  2861. {
  2862. ILStackDesc *obj;
  2863. MonoClassField *field;
  2864. if (!take_addr)
  2865. CLEAR_PREFIX (ctx, PREFIX_UNALIGNED | PREFIX_VOLATILE);
  2866. if (!check_underflow (ctx, 1))
  2867. return;
  2868. obj = stack_pop_safe (ctx);
  2869. if (!check_is_valid_type_for_field_ops (ctx, token, obj, &field, take_addr ? "ldflda" : "ldfld"))
  2870. return;
  2871. if (take_addr && field->parent->valuetype && !stack_slot_is_managed_pointer (obj))
  2872. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot take the address of a temporary value-type at 0x%04x", ctx->ip_offset));
  2873. if (take_addr && (field->type->attrs & FIELD_ATTRIBUTE_INIT_ONLY) &&
  2874. !(field->parent == ctx->method->klass && mono_method_is_constructor (ctx->method)))
  2875. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot take the address of a init-only field at 0x%04x", ctx->ip_offset));
  2876. set_stack_value (ctx, stack_push (ctx), field->type, take_addr);
  2877. }
  2878. static void
  2879. do_store_field (VerifyContext *ctx, int token)
  2880. {
  2881. ILStackDesc *value, *obj;
  2882. MonoClassField *field;
  2883. CLEAR_PREFIX (ctx, PREFIX_UNALIGNED | PREFIX_VOLATILE);
  2884. if (!check_underflow (ctx, 2))
  2885. return;
  2886. value = stack_pop (ctx);
  2887. obj = stack_pop_safe (ctx);
  2888. if (!check_is_valid_type_for_field_ops (ctx, token, obj, &field, "stfld"))
  2889. return;
  2890. if (!verify_stack_type_compatibility (ctx, field->type, value))
  2891. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Incompatible type %s in field store at 0x%04x", stack_slot_get_name (value), ctx->ip_offset));
  2892. }
  2893. /*TODO proper handle for Nullable<T>*/
  2894. static void
  2895. do_box_value (VerifyContext *ctx, int klass_token)
  2896. {
  2897. ILStackDesc *value;
  2898. MonoType *type = get_boxable_mono_type (ctx, klass_token, "box");
  2899. MonoClass *klass;
  2900. if (!type)
  2901. return;
  2902. if (!check_underflow (ctx, 1))
  2903. return;
  2904. value = stack_pop (ctx);
  2905. /*box is a nop for reference types*/
  2906. if (stack_slot_get_underlying_type (value) == TYPE_COMPLEX && MONO_TYPE_IS_REFERENCE (value->type) && MONO_TYPE_IS_REFERENCE (type)) {
  2907. stack_push_stack_val (ctx, value)->stype |= BOXED_MASK;
  2908. return;
  2909. }
  2910. if (!verify_stack_type_compatibility (ctx, type, value))
  2911. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type at stack for boxing operation at 0x%04x", ctx->ip_offset));
  2912. klass = mono_class_from_mono_type (type);
  2913. if (mono_class_is_nullable (klass))
  2914. type = &mono_class_get_nullable_param (klass)->byval_arg;
  2915. stack_push_val (ctx, TYPE_COMPLEX | BOXED_MASK, type);
  2916. }
  2917. static void
  2918. do_unbox_value (VerifyContext *ctx, int klass_token)
  2919. {
  2920. ILStackDesc *value;
  2921. MonoType *type = get_boxable_mono_type (ctx, klass_token, "unbox");
  2922. if (!type)
  2923. return;
  2924. if (!check_underflow (ctx, 1))
  2925. return;
  2926. if (!mono_class_from_mono_type (type)->valuetype)
  2927. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid reference type for unbox at 0x%04x", ctx->ip_offset));
  2928. value = stack_pop (ctx);
  2929. /*Value should be: a boxed valuetype or a reference type*/
  2930. if (!(stack_slot_get_type (value) == TYPE_COMPLEX &&
  2931. (stack_slot_is_boxed_value (value) || !mono_class_from_mono_type (value->type)->valuetype)))
  2932. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type %s at stack for unbox operation at 0x%04x", stack_slot_get_name (value), ctx->ip_offset));
  2933. set_stack_value (ctx, value = stack_push (ctx), mono_type_get_type_byref (type), FALSE);
  2934. value->stype |= CMMP_MASK;
  2935. }
  2936. static void
  2937. do_unbox_any (VerifyContext *ctx, int klass_token)
  2938. {
  2939. ILStackDesc *value;
  2940. MonoType *type = get_boxable_mono_type (ctx, klass_token, "unbox.any");
  2941. if (!type)
  2942. return;
  2943. if (!check_underflow (ctx, 1))
  2944. return;
  2945. value = stack_pop (ctx);
  2946. /*Value should be: a boxed valuetype or a reference type*/
  2947. if (!(stack_slot_get_type (value) == TYPE_COMPLEX &&
  2948. (stack_slot_is_boxed_value (value) || !mono_class_from_mono_type (value->type)->valuetype)))
  2949. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type %s at stack for unbox.any operation at 0x%04x", stack_slot_get_name (value), ctx->ip_offset));
  2950. set_stack_value (ctx, stack_push (ctx), type, FALSE);
  2951. }
  2952. static void
  2953. do_unary_math_op (VerifyContext *ctx, int op)
  2954. {
  2955. ILStackDesc *value;
  2956. if (!check_underflow (ctx, 1))
  2957. return;
  2958. value = stack_pop (ctx);
  2959. switch (stack_slot_get_type (value)) {
  2960. case TYPE_I4:
  2961. case TYPE_I8:
  2962. case TYPE_NATIVE_INT:
  2963. break;
  2964. case TYPE_R8:
  2965. if (op == CEE_NEG)
  2966. break;
  2967. case TYPE_COMPLEX: /*only enums are ok*/
  2968. if (mono_type_is_enum_type (value->type))
  2969. break;
  2970. default:
  2971. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type at stack for unary not at 0x%04x", ctx->ip_offset));
  2972. }
  2973. stack_push_stack_val (ctx, value);
  2974. }
  2975. static void
  2976. do_conversion (VerifyContext *ctx, int kind)
  2977. {
  2978. ILStackDesc *value;
  2979. if (!check_underflow (ctx, 1))
  2980. return;
  2981. value = stack_pop (ctx);
  2982. switch (stack_slot_get_type (value)) {
  2983. case TYPE_I4:
  2984. case TYPE_I8:
  2985. case TYPE_NATIVE_INT:
  2986. case TYPE_R8:
  2987. break;
  2988. default:
  2989. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type (%s) at stack for conversion operation. Numeric type expected at 0x%04x", stack_slot_get_name (value), ctx->ip_offset));
  2990. }
  2991. switch (kind) {
  2992. case TYPE_I4:
  2993. stack_push_val (ctx, TYPE_I4, &mono_defaults.int32_class->byval_arg);
  2994. break;
  2995. case TYPE_I8:
  2996. stack_push_val (ctx,TYPE_I8, &mono_defaults.int64_class->byval_arg);
  2997. break;
  2998. case TYPE_R8:
  2999. stack_push_val (ctx, TYPE_R8, &mono_defaults.double_class->byval_arg);
  3000. break;
  3001. case TYPE_NATIVE_INT:
  3002. stack_push_val (ctx, TYPE_NATIVE_INT, &mono_defaults.int_class->byval_arg);
  3003. break;
  3004. default:
  3005. g_error ("unknown type %02x in conversion", kind);
  3006. }
  3007. }
  3008. static void
  3009. do_load_token (VerifyContext *ctx, int token)
  3010. {
  3011. gpointer handle;
  3012. MonoClass *handle_class;
  3013. if (!check_overflow (ctx))
  3014. return;
  3015. if (ctx->method->wrapper_type != MONO_WRAPPER_NONE) {
  3016. handle = mono_method_get_wrapper_data (ctx->method, token);
  3017. handle_class = mono_method_get_wrapper_data (ctx->method, token + 1);
  3018. if (handle_class == mono_defaults.typehandle_class)
  3019. handle = &((MonoClass*)handle)->byval_arg;
  3020. } else {
  3021. switch (token & 0xff000000) {
  3022. case MONO_TOKEN_TYPE_DEF:
  3023. case MONO_TOKEN_TYPE_REF:
  3024. case MONO_TOKEN_TYPE_SPEC:
  3025. case MONO_TOKEN_FIELD_DEF:
  3026. case MONO_TOKEN_METHOD_DEF:
  3027. case MONO_TOKEN_METHOD_SPEC:
  3028. case MONO_TOKEN_MEMBER_REF:
  3029. if (!token_bounds_check (ctx->image, token)) {
  3030. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Table index out of range 0x%x for token %x for ldtoken at 0x%04x", mono_metadata_token_index (token), token, ctx->ip_offset));
  3031. return;
  3032. }
  3033. break;
  3034. default:
  3035. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid table 0x%x for token 0x%x for ldtoken at 0x%04x", mono_metadata_token_table (token), token, ctx->ip_offset));
  3036. return;
  3037. }
  3038. handle = mono_ldtoken (ctx->image, token, &handle_class, ctx->generic_context);
  3039. }
  3040. if (!handle) {
  3041. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid token 0x%x for ldtoken at 0x%04x", token, ctx->ip_offset));
  3042. return;
  3043. }
  3044. if (handle_class == mono_defaults.typehandle_class) {
  3045. mono_type_is_valid_in_context (ctx, (MonoType*)handle);
  3046. } else if (handle_class == mono_defaults.methodhandle_class) {
  3047. mono_method_is_valid_in_context (ctx, (MonoMethod*)handle);
  3048. } else if (handle_class == mono_defaults.fieldhandle_class) {
  3049. mono_type_is_valid_in_context (ctx, &((MonoClassField*)handle)->parent->byval_arg);
  3050. } else {
  3051. ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid ldtoken type %x at 0x%04x", token, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
  3052. }
  3053. stack_push_val (ctx, TYPE_COMPLEX, mono_class_get_type (handle_class));
  3054. }
  3055. static void
  3056. do_ldobj_value (VerifyContext *ctx, int token)
  3057. {
  3058. ILStackDesc *value;
  3059. MonoType *type = get_boxable_mono_type (ctx, token, "ldobj");
  3060. CLEAR_PREFIX (ctx, PREFIX_UNALIGNED | PREFIX_VOLATILE);
  3061. if (!type)
  3062. return;
  3063. if (!check_underflow (ctx, 1))
  3064. return;
  3065. value = stack_pop (ctx);
  3066. if (!stack_slot_is_managed_pointer (value)
  3067. && stack_slot_get_type (value) != TYPE_NATIVE_INT
  3068. && !(stack_slot_get_type (value) == TYPE_PTR && value->type->type != MONO_TYPE_FNPTR)) {
  3069. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid argument %s to ldobj at 0x%04x", stack_slot_get_name (value), ctx->ip_offset));
  3070. return;
  3071. }
  3072. if (stack_slot_get_type (value) == TYPE_NATIVE_INT)
  3073. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Using native pointer to ldobj at 0x%04x", ctx->ip_offset));
  3074. /*We have a byval on the stack, but the comparison must be strict. */
  3075. if (!verify_type_compatibility_full (ctx, type, mono_type_get_type_byval (value->type), TRUE))
  3076. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type at stack for ldojb operation at 0x%04x", ctx->ip_offset));
  3077. set_stack_value (ctx, stack_push (ctx), type, FALSE);
  3078. }
  3079. static void
  3080. do_stobj (VerifyContext *ctx, int token)
  3081. {
  3082. ILStackDesc *dest, *src;
  3083. MonoType *type = get_boxable_mono_type (ctx, token, "stobj");
  3084. CLEAR_PREFIX (ctx, PREFIX_UNALIGNED | PREFIX_VOLATILE);
  3085. if (!type)
  3086. return;
  3087. if (!check_underflow (ctx, 2))
  3088. return;
  3089. src = stack_pop (ctx);
  3090. dest = stack_pop (ctx);
  3091. if (stack_slot_is_managed_mutability_pointer (dest))
  3092. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use a readonly pointer with stobj at 0x%04x", ctx->ip_offset));
  3093. if (!stack_slot_is_managed_pointer (dest))
  3094. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid destination of stobj operation at 0x%04x", ctx->ip_offset));
  3095. if (stack_slot_is_boxed_value (src) && !MONO_TYPE_IS_REFERENCE (src->type) && !MONO_TYPE_IS_REFERENCE (type))
  3096. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use stobj with a boxed source value that is not a reference type at 0x%04x", ctx->ip_offset));
  3097. if (!verify_stack_type_compatibility (ctx, type, src)) {
  3098. char *type_name = mono_type_full_name (type);
  3099. char *src_name = stack_slot_full_name (src);
  3100. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Token '%s' and source '%s' of stobj don't match ' at 0x%04x", type_name, src_name, ctx->ip_offset));
  3101. g_free (type_name);
  3102. g_free (src_name);
  3103. }
  3104. if (!verify_type_compatibility (ctx, mono_type_get_type_byval (dest->type), type))
  3105. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Destination and token types of stobj don't match at 0x%04x", ctx->ip_offset));
  3106. }
  3107. static void
  3108. do_cpobj (VerifyContext *ctx, int token)
  3109. {
  3110. ILStackDesc *dest, *src;
  3111. MonoType *type = get_boxable_mono_type (ctx, token, "cpobj");
  3112. if (!type)
  3113. return;
  3114. if (!check_underflow (ctx, 2))
  3115. return;
  3116. src = stack_pop (ctx);
  3117. dest = stack_pop (ctx);
  3118. if (!stack_slot_is_managed_pointer (src))
  3119. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid source of cpobj operation at 0x%04x", ctx->ip_offset));
  3120. if (!stack_slot_is_managed_pointer (dest))
  3121. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid destination of cpobj operation at 0x%04x", ctx->ip_offset));
  3122. if (stack_slot_is_managed_mutability_pointer (dest))
  3123. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use a readonly pointer with cpobj at 0x%04x", ctx->ip_offset));
  3124. if (!verify_type_compatibility (ctx, type, mono_type_get_type_byval (src->type)))
  3125. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Token and source types of cpobj don't match at 0x%04x", ctx->ip_offset));
  3126. if (!verify_type_compatibility (ctx, mono_type_get_type_byval (dest->type), type))
  3127. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Destination and token types of cpobj don't match at 0x%04x", ctx->ip_offset));
  3128. }
  3129. static void
  3130. do_initobj (VerifyContext *ctx, int token)
  3131. {
  3132. ILStackDesc *obj;
  3133. MonoType *stack, *type = get_boxable_mono_type (ctx, token, "initobj");
  3134. if (!type)
  3135. return;
  3136. if (!check_underflow (ctx, 1))
  3137. return;
  3138. obj = stack_pop (ctx);
  3139. if (!stack_slot_is_managed_pointer (obj))
  3140. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid object address for initobj at 0x%04x", ctx->ip_offset));
  3141. if (stack_slot_is_managed_mutability_pointer (obj))
  3142. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use a readonly pointer with initobj at 0x%04x", ctx->ip_offset));
  3143. stack = mono_type_get_type_byval (obj->type);
  3144. if (MONO_TYPE_IS_REFERENCE (stack)) {
  3145. if (!verify_type_compatibility (ctx, stack, type))
  3146. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Type token of initobj not compatible with value on stack at 0x%04x", ctx->ip_offset));
  3147. else if (IS_STRICT_MODE (ctx) && !mono_metadata_type_equal (type, stack))
  3148. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Type token of initobj not compatible with value on stack at 0x%04x", ctx->ip_offset));
  3149. } else if (!verify_type_compatibility (ctx, stack, type)) {
  3150. char *expected_name = mono_type_full_name (type);
  3151. char *stack_name = mono_type_full_name (stack);
  3152. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Initobj %s not compatible with value on stack %s at 0x%04x", expected_name, stack_name, ctx->ip_offset));
  3153. g_free (expected_name);
  3154. g_free (stack_name);
  3155. }
  3156. }
  3157. static void
  3158. do_newobj (VerifyContext *ctx, int token)
  3159. {
  3160. ILStackDesc *value;
  3161. int i;
  3162. MonoMethodSignature *sig;
  3163. MonoMethod *method;
  3164. gboolean is_delegate = FALSE;
  3165. if (!(method = verifier_load_method (ctx, token, "newobj")))
  3166. return;
  3167. if (!mono_method_is_constructor (method)) {
  3168. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Method from token 0x%08x not a constructor at 0x%04x", token, ctx->ip_offset));
  3169. return;
  3170. }
  3171. if (method->klass->flags & (TYPE_ATTRIBUTE_ABSTRACT | TYPE_ATTRIBUTE_INTERFACE))
  3172. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Trying to instantiate an abstract or interface type at 0x%04x", ctx->ip_offset));
  3173. if (!IS_SKIP_VISIBILITY (ctx) && !mono_method_can_access_method_full (ctx->method, method, NULL)) {
  3174. char *from = mono_method_full_name (ctx->method, TRUE);
  3175. char *to = mono_method_full_name (method, TRUE);
  3176. CODE_NOT_VERIFIABLE2 (ctx, g_strdup_printf ("Constructor %s not visible from %s at 0x%04x", to, from, ctx->ip_offset), MONO_EXCEPTION_METHOD_ACCESS);
  3177. g_free (from);
  3178. g_free (to);
  3179. }
  3180. //FIXME use mono_method_get_signature_full
  3181. sig = mono_method_signature (method);
  3182. if (!sig) {
  3183. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid constructor signature to newobj at 0x%04x", ctx->ip_offset));
  3184. return;
  3185. }
  3186. if (!sig->hasthis) {
  3187. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid constructor signature missing hasthis at 0x%04x", ctx->ip_offset));
  3188. return;
  3189. }
  3190. if (!check_underflow (ctx, sig->param_count))
  3191. return;
  3192. is_delegate = method->klass->parent == mono_defaults.multicastdelegate_class;
  3193. if (is_delegate) {
  3194. ILStackDesc *funptr;
  3195. //first arg is object, second arg is fun ptr
  3196. if (sig->param_count != 2) {
  3197. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid delegate constructor at 0x%04x", ctx->ip_offset));
  3198. return;
  3199. }
  3200. funptr = stack_pop (ctx);
  3201. value = stack_pop (ctx);
  3202. verify_delegate_compatibility (ctx, method->klass, value, funptr);
  3203. } else {
  3204. for (i = sig->param_count - 1; i >= 0; --i) {
  3205. VERIFIER_DEBUG ( printf ("verifying constructor argument %d\n", i); );
  3206. value = stack_pop (ctx);
  3207. if (!verify_stack_type_compatibility (ctx, sig->params [i], value)) {
  3208. char *stack_name = stack_slot_full_name (value);
  3209. char *sig_name = mono_type_full_name (sig->params [i]);
  3210. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Incompatible parameter value with constructor signature: %s X %s at 0x%04x", sig_name, stack_name, ctx->ip_offset));
  3211. g_free (stack_name);
  3212. g_free (sig_name);
  3213. }
  3214. if (stack_slot_is_managed_mutability_pointer (value))
  3215. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use a readonly pointer as argument of newobj at 0x%04x", ctx->ip_offset));
  3216. }
  3217. }
  3218. if (check_overflow (ctx))
  3219. set_stack_value (ctx, stack_push (ctx), &method->klass->byval_arg, FALSE);
  3220. }
  3221. static void
  3222. do_cast (VerifyContext *ctx, int token, const char *opcode) {
  3223. ILStackDesc *value;
  3224. MonoType *type;
  3225. gboolean is_boxed;
  3226. gboolean do_box;
  3227. if (!check_underflow (ctx, 1))
  3228. return;
  3229. if (!(type = get_boxable_mono_type (ctx, token, opcode)))
  3230. return;
  3231. if (type->byref) {
  3232. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid %s type at 0x%04x", opcode, ctx->ip_offset));
  3233. return;
  3234. }
  3235. value = stack_pop (ctx);
  3236. is_boxed = stack_slot_is_boxed_value (value);
  3237. if (stack_slot_is_managed_pointer (value))
  3238. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid value for %s at 0x%04x", opcode, ctx->ip_offset));
  3239. else if (!MONO_TYPE_IS_REFERENCE (value->type) && !is_boxed) {
  3240. char *name = stack_slot_full_name (value);
  3241. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Expected a reference type on stack for %s but found %s at 0x%04x", opcode, name, ctx->ip_offset));
  3242. g_free (name);
  3243. }
  3244. switch (value->type->type) {
  3245. case MONO_TYPE_FNPTR:
  3246. case MONO_TYPE_PTR:
  3247. case MONO_TYPE_TYPEDBYREF:
  3248. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid value for %s at 0x%04x", opcode, ctx->ip_offset));
  3249. }
  3250. do_box = is_boxed || mono_type_is_generic_argument(type) || mono_class_from_mono_type (type)->valuetype;
  3251. stack_push_val (ctx, TYPE_COMPLEX | (do_box ? BOXED_MASK : 0), type);
  3252. }
  3253. static MonoType *
  3254. mono_type_from_opcode (int opcode) {
  3255. switch (opcode) {
  3256. case CEE_LDIND_I1:
  3257. case CEE_LDIND_U1:
  3258. case CEE_STIND_I1:
  3259. case CEE_LDELEM_I1:
  3260. case CEE_LDELEM_U1:
  3261. case CEE_STELEM_I1:
  3262. return &mono_defaults.sbyte_class->byval_arg;
  3263. case CEE_LDIND_I2:
  3264. case CEE_LDIND_U2:
  3265. case CEE_STIND_I2:
  3266. case CEE_LDELEM_I2:
  3267. case CEE_LDELEM_U2:
  3268. case CEE_STELEM_I2:
  3269. return &mono_defaults.int16_class->byval_arg;
  3270. case CEE_LDIND_I4:
  3271. case CEE_LDIND_U4:
  3272. case CEE_STIND_I4:
  3273. case CEE_LDELEM_I4:
  3274. case CEE_LDELEM_U4:
  3275. case CEE_STELEM_I4:
  3276. return &mono_defaults.int32_class->byval_arg;
  3277. case CEE_LDIND_I8:
  3278. case CEE_STIND_I8:
  3279. case CEE_LDELEM_I8:
  3280. case CEE_STELEM_I8:
  3281. return &mono_defaults.int64_class->byval_arg;
  3282. case CEE_LDIND_R4:
  3283. case CEE_STIND_R4:
  3284. case CEE_LDELEM_R4:
  3285. case CEE_STELEM_R4:
  3286. return &mono_defaults.single_class->byval_arg;
  3287. case CEE_LDIND_R8:
  3288. case CEE_STIND_R8:
  3289. case CEE_LDELEM_R8:
  3290. case CEE_STELEM_R8:
  3291. return &mono_defaults.double_class->byval_arg;
  3292. case CEE_LDIND_I:
  3293. case CEE_STIND_I:
  3294. case CEE_LDELEM_I:
  3295. case CEE_STELEM_I:
  3296. return &mono_defaults.int_class->byval_arg;
  3297. case CEE_LDIND_REF:
  3298. case CEE_STIND_REF:
  3299. case CEE_LDELEM_REF:
  3300. case CEE_STELEM_REF:
  3301. return &mono_defaults.object_class->byval_arg;
  3302. default:
  3303. g_error ("unknown opcode %02x in mono_type_from_opcode ", opcode);
  3304. return NULL;
  3305. }
  3306. }
  3307. static void
  3308. do_load_indirect (VerifyContext *ctx, int opcode)
  3309. {
  3310. ILStackDesc *value;
  3311. CLEAR_PREFIX (ctx, PREFIX_UNALIGNED | PREFIX_VOLATILE);
  3312. if (!check_underflow (ctx, 1))
  3313. return;
  3314. value = stack_pop (ctx);
  3315. if (!stack_slot_is_managed_pointer (value)) {
  3316. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Load indirect not using a manager pointer at 0x%04x", ctx->ip_offset));
  3317. set_stack_value (ctx, stack_push (ctx), mono_type_from_opcode (opcode), FALSE);
  3318. return;
  3319. }
  3320. if (opcode == CEE_LDIND_REF) {
  3321. if (stack_slot_get_underlying_type (value) != TYPE_COMPLEX || mono_class_from_mono_type (value->type)->valuetype)
  3322. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type at stack for ldind_ref expected object byref operation at 0x%04x", ctx->ip_offset));
  3323. set_stack_value (ctx, stack_push (ctx), mono_type_get_type_byval (value->type), FALSE);
  3324. } else {
  3325. if (!verify_type_compatibility_full (ctx, mono_type_from_opcode (opcode), mono_type_get_type_byval (value->type), TRUE))
  3326. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type at stack for ldind 0x%x operation at 0x%04x", opcode, ctx->ip_offset));
  3327. set_stack_value (ctx, stack_push (ctx), mono_type_from_opcode (opcode), FALSE);
  3328. }
  3329. }
  3330. static void
  3331. do_store_indirect (VerifyContext *ctx, int opcode)
  3332. {
  3333. ILStackDesc *addr, *val;
  3334. CLEAR_PREFIX (ctx, PREFIX_UNALIGNED | PREFIX_VOLATILE);
  3335. if (!check_underflow (ctx, 2))
  3336. return;
  3337. val = stack_pop (ctx);
  3338. addr = stack_pop (ctx);
  3339. check_unmanaged_pointer (ctx, addr);
  3340. if (!stack_slot_is_managed_pointer (addr) && stack_slot_get_type (addr) != TYPE_PTR) {
  3341. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid non-pointer argument to stind at 0x%04x", ctx->ip_offset));
  3342. return;
  3343. }
  3344. if (stack_slot_is_managed_mutability_pointer (addr)) {
  3345. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use a readonly pointer with stind at 0x%04x", ctx->ip_offset));
  3346. return;
  3347. }
  3348. if (!verify_type_compatibility_full (ctx, mono_type_from_opcode (opcode), mono_type_get_type_byval (addr->type), TRUE))
  3349. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid addr type at stack for stind 0x%x operation at 0x%04x", opcode, ctx->ip_offset));
  3350. if (!verify_stack_type_compatibility (ctx, mono_type_from_opcode (opcode), val))
  3351. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid value type at stack for stind 0x%x operation at 0x%04x", opcode, ctx->ip_offset));
  3352. }
  3353. static void
  3354. do_newarr (VerifyContext *ctx, int token)
  3355. {
  3356. ILStackDesc *value;
  3357. MonoType *type = get_boxable_mono_type (ctx, token, "newarr");
  3358. if (!type)
  3359. return;
  3360. if (!check_underflow (ctx, 1))
  3361. return;
  3362. value = stack_pop (ctx);
  3363. if (stack_slot_get_type (value) != TYPE_I4 && stack_slot_get_type (value) != TYPE_NATIVE_INT)
  3364. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Array size type on stack (%s) is not a verifiable type at 0x%04x", stack_slot_get_name (value), ctx->ip_offset));
  3365. set_stack_value (ctx, stack_push (ctx), mono_class_get_type (mono_array_class_get (mono_class_from_mono_type (type), 1)), FALSE);
  3366. }
  3367. /*FIXME handle arrays that are not 0-indexed*/
  3368. static void
  3369. do_ldlen (VerifyContext *ctx)
  3370. {
  3371. ILStackDesc *value;
  3372. if (!check_underflow (ctx, 1))
  3373. return;
  3374. value = stack_pop (ctx);
  3375. if (stack_slot_get_type (value) != TYPE_COMPLEX || value->type->type != MONO_TYPE_SZARRAY)
  3376. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid array type for ldlen at 0x%04x", ctx->ip_offset));
  3377. stack_push_val (ctx, TYPE_NATIVE_INT, &mono_defaults.int_class->byval_arg);
  3378. }
  3379. /*FIXME handle arrays that are not 0-indexed*/
  3380. /*FIXME handle readonly prefix and CMMP*/
  3381. static void
  3382. do_ldelema (VerifyContext *ctx, int klass_token)
  3383. {
  3384. ILStackDesc *index, *array, *res;
  3385. MonoType *type = get_boxable_mono_type (ctx, klass_token, "ldelema");
  3386. gboolean valid;
  3387. if (!type)
  3388. return;
  3389. if (!check_underflow (ctx, 2))
  3390. return;
  3391. index = stack_pop (ctx);
  3392. array = stack_pop (ctx);
  3393. if (stack_slot_get_type (index) != TYPE_I4 && stack_slot_get_type (index) != TYPE_NATIVE_INT)
  3394. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Index type(%s) for ldelema is not an int or a native int at 0x%04x", stack_slot_get_name (index), ctx->ip_offset));
  3395. if (!stack_slot_is_null_literal (array)) {
  3396. if (stack_slot_get_type (array) != TYPE_COMPLEX || array->type->type != MONO_TYPE_SZARRAY)
  3397. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid array type(%s) for ldelema at 0x%04x", stack_slot_get_name (array), ctx->ip_offset));
  3398. else {
  3399. if (get_stack_type (type) == TYPE_I4 || get_stack_type (type) == TYPE_NATIVE_INT) {
  3400. valid = verify_type_compatibility_full (ctx, type, &array->type->data.klass->byval_arg, TRUE);
  3401. } else {
  3402. valid = mono_metadata_type_equal (type, &array->type->data.klass->byval_arg);
  3403. }
  3404. if (!valid)
  3405. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid array type on stack for ldelema at 0x%04x", ctx->ip_offset));
  3406. }
  3407. }
  3408. res = stack_push (ctx);
  3409. set_stack_value (ctx, res, type, TRUE);
  3410. if (ctx->prefix_set & PREFIX_READONLY) {
  3411. ctx->prefix_set &= ~PREFIX_READONLY;
  3412. res->stype |= CMMP_MASK;
  3413. }
  3414. }
  3415. /*
  3416. * FIXME handle arrays that are not 0-indexed
  3417. * FIXME handle readonly prefix and CMMP
  3418. */
  3419. static void
  3420. do_ldelem (VerifyContext *ctx, int opcode, int token)
  3421. {
  3422. #define IS_ONE_OF2(T, A, B) (T == A || T == B)
  3423. ILStackDesc *index, *array;
  3424. MonoType *type;
  3425. if (!check_underflow (ctx, 2))
  3426. return;
  3427. if (opcode == CEE_LDELEM) {
  3428. if (!(type = verifier_load_type (ctx, token, "ldelem.any"))) {
  3429. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Type (0x%08x) not found at 0x%04x", token, ctx->ip_offset));
  3430. return;
  3431. }
  3432. } else {
  3433. type = mono_type_from_opcode (opcode);
  3434. }
  3435. index = stack_pop (ctx);
  3436. array = stack_pop (ctx);
  3437. if (stack_slot_get_type (index) != TYPE_I4 && stack_slot_get_type (index) != TYPE_NATIVE_INT)
  3438. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Index type(%s) for ldelem.X is not an int or a native int at 0x%04x", stack_slot_get_name (index), ctx->ip_offset));
  3439. if (!stack_slot_is_null_literal (array)) {
  3440. if (stack_slot_get_type (array) != TYPE_COMPLEX || array->type->type != MONO_TYPE_SZARRAY)
  3441. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid array type(%s) for ldelem.X at 0x%04x", stack_slot_get_name (array), ctx->ip_offset));
  3442. else {
  3443. if (opcode == CEE_LDELEM_REF) {
  3444. if (array->type->data.klass->valuetype)
  3445. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid array type is not a reference type for ldelem.ref 0x%04x", ctx->ip_offset));
  3446. type = &array->type->data.klass->byval_arg;
  3447. } else {
  3448. MonoType *candidate = &array->type->data.klass->byval_arg;
  3449. if (IS_STRICT_MODE (ctx)) {
  3450. MonoType *underlying_type = mono_type_get_underlying_type_any (type);
  3451. MonoType *underlying_candidate = mono_type_get_underlying_type_any (candidate);
  3452. if ((IS_ONE_OF2 (underlying_type->type, MONO_TYPE_I4, MONO_TYPE_U4) && IS_ONE_OF2 (underlying_candidate->type, MONO_TYPE_I, MONO_TYPE_U)) ||
  3453. (IS_ONE_OF2 (underlying_candidate->type, MONO_TYPE_I4, MONO_TYPE_U4) && IS_ONE_OF2 (underlying_type->type, MONO_TYPE_I, MONO_TYPE_U)))
  3454. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid array type on stack for ldelem.X at 0x%04x", ctx->ip_offset));
  3455. }
  3456. if (!verify_type_compatibility_full (ctx, type, candidate, TRUE))
  3457. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid array type on stack for ldelem.X at 0x%04x", ctx->ip_offset));
  3458. }
  3459. }
  3460. }
  3461. set_stack_value (ctx, stack_push (ctx), type, FALSE);
  3462. #undef IS_ONE_OF2
  3463. }
  3464. /*
  3465. * FIXME handle arrays that are not 0-indexed
  3466. */
  3467. static void
  3468. do_stelem (VerifyContext *ctx, int opcode, int token)
  3469. {
  3470. ILStackDesc *index, *array, *value;
  3471. MonoType *type;
  3472. if (!check_underflow (ctx, 3))
  3473. return;
  3474. if (opcode == CEE_STELEM) {
  3475. if (!(type = verifier_load_type (ctx, token, "stelem.any"))) {
  3476. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Type (0x%08x) not found at 0x%04x", token, ctx->ip_offset));
  3477. return;
  3478. }
  3479. } else {
  3480. type = mono_type_from_opcode (opcode);
  3481. }
  3482. value = stack_pop (ctx);
  3483. index = stack_pop (ctx);
  3484. array = stack_pop (ctx);
  3485. if (stack_slot_get_type (index) != TYPE_I4 && stack_slot_get_type (index) != TYPE_NATIVE_INT)
  3486. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Index type(%s) for stdelem.X is not an int or a native int at 0x%04x", stack_slot_get_name (index), ctx->ip_offset));
  3487. if (!stack_slot_is_null_literal (array)) {
  3488. if (stack_slot_get_type (array) != TYPE_COMPLEX || array->type->type != MONO_TYPE_SZARRAY) {
  3489. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid array type(%s) for stelem.X at 0x%04x", stack_slot_get_name (array), ctx->ip_offset));
  3490. } else {
  3491. if (opcode == CEE_STELEM_REF) {
  3492. if (array->type->data.klass->valuetype)
  3493. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid array type is not a reference type for stelem.ref 0x%04x", ctx->ip_offset));
  3494. } else if (!verify_type_compatibility_full (ctx, &array->type->data.klass->byval_arg, type, TRUE)) {
  3495. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid array type on stack for stdelem.X at 0x%04x", ctx->ip_offset));
  3496. }
  3497. }
  3498. }
  3499. if (opcode == CEE_STELEM_REF) {
  3500. if (!stack_slot_is_boxed_value (value) && mono_class_from_mono_type (value->type)->valuetype)
  3501. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid value is not a reference type for stelem.ref 0x%04x", ctx->ip_offset));
  3502. } else if (opcode != CEE_STELEM_REF) {
  3503. if (!verify_stack_type_compatibility (ctx, type, value))
  3504. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid value on stack for stdelem.X at 0x%04x", ctx->ip_offset));
  3505. if (stack_slot_is_boxed_value (value) && !MONO_TYPE_IS_REFERENCE (value->type) && !MONO_TYPE_IS_REFERENCE (type))
  3506. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use stobj with a boxed source value that is not a reference type at 0x%04x", ctx->ip_offset));
  3507. }
  3508. }
  3509. static void
  3510. do_throw (VerifyContext *ctx)
  3511. {
  3512. ILStackDesc *exception;
  3513. if (!check_underflow (ctx, 1))
  3514. return;
  3515. exception = stack_pop (ctx);
  3516. if (!stack_slot_is_null_literal (exception) && !(stack_slot_get_type (exception) == TYPE_COMPLEX && !mono_class_from_mono_type (exception->type)->valuetype))
  3517. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type on stack for throw, expected reference type at 0x%04x", ctx->ip_offset));
  3518. if (mono_type_is_generic_argument (exception->type) && !stack_slot_is_boxed_value (exception)) {
  3519. char *name = mono_type_full_name (exception->type);
  3520. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid type on stack for throw, expected reference type but found unboxed %s at 0x%04x ", name, ctx->ip_offset));
  3521. g_free (name);
  3522. }
  3523. /*The stack is left empty after a throw*/
  3524. ctx->eval.size = 0;
  3525. }
  3526. static void
  3527. do_endfilter (VerifyContext *ctx)
  3528. {
  3529. MonoExceptionClause *clause;
  3530. if (IS_STRICT_MODE (ctx)) {
  3531. if (ctx->eval.size != 1)
  3532. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Stack size must have one item for endfilter at 0x%04x", ctx->ip_offset));
  3533. if (ctx->eval.size >= 1 && stack_slot_get_type (stack_pop (ctx)) != TYPE_I4)
  3534. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Stack item type is not an int32 for endfilter at 0x%04x", ctx->ip_offset));
  3535. }
  3536. if ((clause = is_correct_endfilter (ctx, ctx->ip_offset))) {
  3537. if (IS_STRICT_MODE (ctx)) {
  3538. if (ctx->ip_offset != clause->handler_offset - 2)
  3539. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("endfilter is not the last instruction of the filter clause at 0x%04x", ctx->ip_offset));
  3540. } else {
  3541. if ((ctx->ip_offset != clause->handler_offset - 2) && !MONO_OFFSET_IN_HANDLER (clause, ctx->ip_offset))
  3542. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("endfilter is not the last instruction of the filter clause at 0x%04x", ctx->ip_offset));
  3543. }
  3544. } else {
  3545. if (IS_STRICT_MODE (ctx) && !is_unverifiable_endfilter (ctx, ctx->ip_offset))
  3546. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("endfilter outside filter clause at 0x%04x", ctx->ip_offset));
  3547. else
  3548. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("endfilter outside filter clause at 0x%04x", ctx->ip_offset));
  3549. }
  3550. ctx->eval.size = 0;
  3551. }
  3552. static void
  3553. do_leave (VerifyContext *ctx, int delta)
  3554. {
  3555. int target = ((gint32)ctx->ip_offset) + delta;
  3556. if (target >= ctx->code_size || target < 0)
  3557. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Branch target out of code at 0x%04x", ctx->ip_offset));
  3558. if (!is_correct_leave (ctx->header, ctx->ip_offset, target))
  3559. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Leave not allowed in finally block at 0x%04x", ctx->ip_offset));
  3560. ctx->eval.size = 0;
  3561. ctx->target = target;
  3562. }
  3563. /*
  3564. * do_static_branch:
  3565. *
  3566. * Verify br and br.s opcodes.
  3567. */
  3568. static void
  3569. do_static_branch (VerifyContext *ctx, int delta)
  3570. {
  3571. int target = ctx->ip_offset + delta;
  3572. if (target < 0 || target >= ctx->code_size) {
  3573. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("branch target out of code at 0x%04x", ctx->ip_offset));
  3574. return;
  3575. }
  3576. switch (is_valid_branch_instruction (ctx->header, ctx->ip_offset, target)) {
  3577. case 1:
  3578. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Branch target escapes out of exception block at 0x%04x", ctx->ip_offset));
  3579. break;
  3580. case 2:
  3581. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Branch target escapes out of exception block at 0x%04x", ctx->ip_offset));
  3582. break;
  3583. }
  3584. ctx->target = target;
  3585. }
  3586. static void
  3587. do_switch (VerifyContext *ctx, int count, const unsigned char *data)
  3588. {
  3589. int i, base = ctx->ip_offset + 5 + count * 4;
  3590. ILStackDesc *value;
  3591. if (!check_underflow (ctx, 1))
  3592. return;
  3593. value = stack_pop (ctx);
  3594. if (stack_slot_get_type (value) != TYPE_I4 && stack_slot_get_type (value) != TYPE_NATIVE_INT)
  3595. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid argument to switch at 0x%04x", ctx->ip_offset));
  3596. for (i = 0; i < count; ++i) {
  3597. int target = base + read32 (data + i * 4);
  3598. if (target < 0 || target >= ctx->code_size) {
  3599. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Switch target %x out of code at 0x%04x", i, ctx->ip_offset));
  3600. return;
  3601. }
  3602. switch (is_valid_branch_instruction (ctx->header, ctx->ip_offset, target)) {
  3603. case 1:
  3604. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Switch target %x escapes out of exception block at 0x%04x", i, ctx->ip_offset));
  3605. break;
  3606. case 2:
  3607. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Switch target %x escapes out of exception block at 0x%04x", i, ctx->ip_offset));
  3608. return;
  3609. }
  3610. merge_stacks (ctx, &ctx->eval, &ctx->code [target], FALSE, TRUE);
  3611. }
  3612. }
  3613. static void
  3614. do_load_function_ptr (VerifyContext *ctx, guint32 token, gboolean virtual)
  3615. {
  3616. ILStackDesc *top;
  3617. MonoMethod *method;
  3618. if (virtual && !check_underflow (ctx, 1))
  3619. return;
  3620. if (!virtual && !check_overflow (ctx))
  3621. return;
  3622. if (ctx->method->wrapper_type != MONO_WRAPPER_NONE) {
  3623. method = mono_method_get_wrapper_data (ctx->method, (guint32)token);
  3624. if (!method) {
  3625. ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid token %x for ldftn at 0x%04x", token, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
  3626. return;
  3627. }
  3628. } else {
  3629. if (!IS_METHOD_DEF_OR_REF_OR_SPEC (token) || !token_bounds_check (ctx->image, token)) {
  3630. ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid token %x for ldftn at 0x%04x", token, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
  3631. return;
  3632. }
  3633. if (!(method = verifier_load_method (ctx, token, virtual ? "ldvirtfrn" : "ldftn")))
  3634. return;
  3635. }
  3636. if (mono_method_is_constructor (method))
  3637. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use ldftn with a constructor at 0x%04x", ctx->ip_offset));
  3638. if (virtual) {
  3639. ILStackDesc *top = stack_pop (ctx);
  3640. if (stack_slot_get_type (top) != TYPE_COMPLEX || top->type->type == MONO_TYPE_VALUETYPE)
  3641. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Invalid argument to ldvirtftn at 0x%04x", ctx->ip_offset));
  3642. if (method->flags & METHOD_ATTRIBUTE_STATIC)
  3643. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use ldvirtftn with a constructor at 0x%04x", ctx->ip_offset));
  3644. if (!verify_stack_type_compatibility (ctx, &method->klass->byval_arg, top))
  3645. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Unexpected object for ldvirtftn at 0x%04x", ctx->ip_offset));
  3646. }
  3647. if (!IS_SKIP_VISIBILITY (ctx) && !mono_method_can_access_method_full (ctx->method, method, NULL))
  3648. CODE_NOT_VERIFIABLE2 (ctx, g_strdup_printf ("Loaded method is not visible for ldftn/ldvirtftn at 0x%04x", ctx->ip_offset), MONO_EXCEPTION_METHOD_ACCESS);
  3649. top = stack_push_val(ctx, TYPE_PTR, mono_type_create_fnptr_from_mono_method (ctx, method));
  3650. top->method = method;
  3651. }
  3652. static void
  3653. do_sizeof (VerifyContext *ctx, int token)
  3654. {
  3655. MonoType *type;
  3656. if (!(type = verifier_load_type (ctx, token, "sizeof")))
  3657. return;
  3658. if (type->byref && type->type != MONO_TYPE_TYPEDBYREF) {
  3659. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid use of byref type at 0x%04x", ctx->ip_offset));
  3660. return;
  3661. }
  3662. if (type->type == MONO_TYPE_VOID) {
  3663. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid use of void type at 0x%04x", ctx->ip_offset));
  3664. return;
  3665. }
  3666. if (check_overflow (ctx))
  3667. set_stack_value (ctx, stack_push (ctx), &mono_defaults.uint32_class->byval_arg, FALSE);
  3668. }
  3669. /* Stack top can be of any type, the runtime doesn't care and treat everything as an int. */
  3670. static void
  3671. do_localloc (VerifyContext *ctx)
  3672. {
  3673. ILStackDesc *top;
  3674. if (ctx->eval.size != 1) {
  3675. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Stack must have only size item in localloc at 0x%04x", ctx->ip_offset));
  3676. return;
  3677. }
  3678. if (in_any_exception_block (ctx->header, ctx->ip_offset)) {
  3679. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Stack must have only size item in localloc at 0x%04x", ctx->ip_offset));
  3680. return;
  3681. }
  3682. /*TODO verify top type*/
  3683. top = stack_pop (ctx);
  3684. set_stack_value (ctx, stack_push (ctx), &mono_defaults.int_class->byval_arg, FALSE);
  3685. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Instruction localloc in never verifiable at 0x%04x", ctx->ip_offset));
  3686. }
  3687. static void
  3688. do_ldstr (VerifyContext *ctx, guint32 token)
  3689. {
  3690. GSList *error = NULL;
  3691. if (ctx->method->wrapper_type == MONO_WRAPPER_NONE && !ctx->image->dynamic) {
  3692. if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
  3693. ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid string token %x at 0x%04x", token, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
  3694. return;
  3695. }
  3696. if (!mono_verifier_verify_string_signature (ctx->image, mono_metadata_token_index (token), &error)) {
  3697. if (error)
  3698. ctx->list = g_slist_concat (ctx->list, error);
  3699. ADD_VERIFY_ERROR2 (ctx, g_strdup_printf ("Invalid string index %x at 0x%04x", token, ctx->ip_offset), MONO_EXCEPTION_BAD_IMAGE);
  3700. return;
  3701. }
  3702. }
  3703. if (check_overflow (ctx))
  3704. stack_push_val (ctx, TYPE_COMPLEX, &mono_defaults.string_class->byval_arg);
  3705. }
  3706. static void
  3707. do_refanyval (VerifyContext *ctx, int token)
  3708. {
  3709. ILStackDesc *top;
  3710. MonoType *type;
  3711. if (!check_underflow (ctx, 1))
  3712. return;
  3713. if (!(type = get_boxable_mono_type (ctx, token, "refanyval")))
  3714. return;
  3715. top = stack_pop (ctx);
  3716. if (top->stype != TYPE_PTR || top->type->type != MONO_TYPE_TYPEDBYREF)
  3717. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Expected a typedref as argument for refanyval, but found %s at 0x%04x", stack_slot_get_name (top), ctx->ip_offset));
  3718. set_stack_value (ctx, stack_push (ctx), type, TRUE);
  3719. }
  3720. static void
  3721. do_refanytype (VerifyContext *ctx)
  3722. {
  3723. ILStackDesc *top;
  3724. if (!check_underflow (ctx, 1))
  3725. return;
  3726. top = stack_pop (ctx);
  3727. if (top->stype != TYPE_PTR || top->type->type != MONO_TYPE_TYPEDBYREF)
  3728. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Expected a typedref as argument for refanytype, but found %s at 0x%04x", stack_slot_get_name (top), ctx->ip_offset));
  3729. set_stack_value (ctx, stack_push (ctx), &mono_defaults.typehandle_class->byval_arg, FALSE);
  3730. }
  3731. static void
  3732. do_mkrefany (VerifyContext *ctx, int token)
  3733. {
  3734. ILStackDesc *top;
  3735. MonoType *type;
  3736. if (!check_underflow (ctx, 1))
  3737. return;
  3738. if (!(type = get_boxable_mono_type (ctx, token, "refanyval")))
  3739. return;
  3740. top = stack_pop (ctx);
  3741. if (stack_slot_is_managed_mutability_pointer (top))
  3742. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot use a readonly pointer with mkrefany at 0x%04x", ctx->ip_offset));
  3743. if (!stack_slot_is_managed_pointer (top)) {
  3744. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Expected a managed pointer for mkrefany, but found %s at 0x%04x", stack_slot_get_name (top), ctx->ip_offset));
  3745. }else {
  3746. MonoType *stack_type = mono_type_get_type_byval (top->type);
  3747. if (MONO_TYPE_IS_REFERENCE (type) && !mono_metadata_type_equal (type, stack_type))
  3748. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Type not compatible for mkrefany at 0x%04x", ctx->ip_offset));
  3749. if (!MONO_TYPE_IS_REFERENCE (type) && !verify_type_compatibility_full (ctx, type, stack_type, TRUE))
  3750. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Type not compatible for mkrefany at 0x%04x", ctx->ip_offset));
  3751. }
  3752. set_stack_value (ctx, stack_push (ctx), &mono_defaults.typed_reference_class->byval_arg, FALSE);
  3753. }
  3754. static void
  3755. do_ckfinite (VerifyContext *ctx)
  3756. {
  3757. ILStackDesc *top;
  3758. if (!check_underflow (ctx, 1))
  3759. return;
  3760. top = stack_pop (ctx);
  3761. if (stack_slot_get_underlying_type (top) != TYPE_R8)
  3762. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Expected float32 or float64 on stack for ckfinit but found %s at 0x%04x", stack_slot_get_name (top), ctx->ip_offset));
  3763. stack_push_stack_val (ctx, top);
  3764. }
  3765. /*
  3766. * merge_stacks:
  3767. * Merge the stacks and perform compat checks. The merge check if types of @from are mergeable with type of @to
  3768. *
  3769. * @from holds new values for a given control path
  3770. * @to holds the current values of a given control path
  3771. *
  3772. * TODO we can eliminate the from argument as all callers pass &ctx->eval
  3773. */
  3774. static void
  3775. merge_stacks (VerifyContext *ctx, ILCodeDesc *from, ILCodeDesc *to, gboolean start, gboolean external)
  3776. {
  3777. MonoError error;
  3778. int i, j, k;
  3779. stack_init (ctx, to);
  3780. if (start) {
  3781. if (to->flags == IL_CODE_FLAG_NOT_PROCESSED)
  3782. from->size = 0;
  3783. else
  3784. stack_copy (&ctx->eval, to);
  3785. goto end_verify;
  3786. } else if (!(to->flags & IL_CODE_STACK_MERGED)) {
  3787. stack_copy (to, &ctx->eval);
  3788. goto end_verify;
  3789. }
  3790. VERIFIER_DEBUG ( printf ("performing stack merge %d x %d\n", from->size, to->size); );
  3791. if (from->size != to->size) {
  3792. VERIFIER_DEBUG ( printf ("different stack sizes %d x %d at 0x%04x\n", from->size, to->size, ctx->ip_offset); );
  3793. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Could not merge stacks, different sizes (%d x %d) at 0x%04x", from->size, to->size, ctx->ip_offset));
  3794. goto end_verify;
  3795. }
  3796. //FIXME we need to preserve CMMP attributes
  3797. //FIXME we must take null literals into consideration.
  3798. for (i = 0; i < from->size; ++i) {
  3799. ILStackDesc *new_slot = from->stack + i;
  3800. ILStackDesc *old_slot = to->stack + i;
  3801. MonoType *new_type = mono_type_from_stack_slot (new_slot);
  3802. MonoType *old_type = mono_type_from_stack_slot (old_slot);
  3803. MonoClass *old_class = mono_class_from_mono_type (old_type);
  3804. MonoClass *new_class = mono_class_from_mono_type (new_type);
  3805. MonoClass *match_class = NULL;
  3806. // S := T then U = S (new value is compatible with current value, keep current)
  3807. if (verify_stack_type_compatibility (ctx, old_type, new_slot)) {
  3808. copy_stack_value (new_slot, old_slot);
  3809. continue;
  3810. }
  3811. // T := S then U = T (old value is compatible with current value, use new)
  3812. if (verify_stack_type_compatibility (ctx, new_type, old_slot)) {
  3813. copy_stack_value (old_slot, new_slot);
  3814. continue;
  3815. }
  3816. if (mono_type_is_generic_argument (old_type) || mono_type_is_generic_argument (new_type)) {
  3817. char *old_name = stack_slot_full_name (old_slot);
  3818. char *new_name = stack_slot_full_name (new_slot);
  3819. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Could not merge stack at depth %d, types not compatible: %s X %s at 0x%04x", i, old_name, new_name, ctx->ip_offset));
  3820. g_free (old_name);
  3821. g_free (new_name);
  3822. goto end_verify;
  3823. }
  3824. //both are reference types, use closest common super type
  3825. if (!mono_class_from_mono_type (old_type)->valuetype
  3826. && !mono_class_from_mono_type (new_type)->valuetype
  3827. && !stack_slot_is_managed_pointer (old_slot)
  3828. && !stack_slot_is_managed_pointer (new_slot)) {
  3829. mono_class_setup_supertypes (old_class);
  3830. mono_class_setup_supertypes (new_class);
  3831. for (j = MIN (old_class->idepth, new_class->idepth) - 1; j > 0; --j) {
  3832. if (mono_metadata_type_equal (&old_class->supertypes [j]->byval_arg, &new_class->supertypes [j]->byval_arg)) {
  3833. match_class = old_class->supertypes [j];
  3834. goto match_found;
  3835. }
  3836. }
  3837. mono_class_setup_interfaces (old_class, &error);
  3838. if (!mono_error_ok (&error)) {
  3839. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot merge stacks due to a TypeLoadException %s at 0x%04x", mono_error_get_message (&error), ctx->ip_offset));
  3840. mono_error_cleanup (&error);
  3841. goto end_verify;
  3842. }
  3843. mono_class_setup_interfaces (new_class, &error);
  3844. if (!mono_error_ok (&error)) {
  3845. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot merge stacks due to a TypeLoadException %s at 0x%04x", mono_error_get_message (&error), ctx->ip_offset));
  3846. mono_error_cleanup (&error);
  3847. goto end_verify;
  3848. }
  3849. for (j = 0; j < old_class->interface_count; ++j) {
  3850. for (k = 0; k < new_class->interface_count; ++k) {
  3851. if (mono_metadata_type_equal (&old_class->interfaces [j]->byval_arg, &new_class->interfaces [k]->byval_arg)) {
  3852. match_class = old_class->interfaces [j];
  3853. goto match_found;
  3854. }
  3855. }
  3856. }
  3857. /* if old class is an interface that new class implements */
  3858. if (old_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
  3859. if (verifier_class_is_assignable_from (old_class, new_class)) {
  3860. match_class = old_class;
  3861. goto match_found;
  3862. }
  3863. for (j = 0; j < old_class->interface_count; ++j) {
  3864. if (verifier_class_is_assignable_from (old_class->interfaces [j], new_class)) {
  3865. match_class = old_class->interfaces [j];
  3866. goto match_found;
  3867. }
  3868. }
  3869. }
  3870. if (new_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
  3871. if (verifier_class_is_assignable_from (new_class, old_class)) {
  3872. match_class = new_class;
  3873. goto match_found;
  3874. }
  3875. for (j = 0; j < new_class->interface_count; ++j) {
  3876. if (verifier_class_is_assignable_from (new_class->interfaces [j], old_class)) {
  3877. match_class = new_class->interfaces [j];
  3878. goto match_found;
  3879. }
  3880. }
  3881. }
  3882. //No decent super type found, use object
  3883. match_class = mono_defaults.object_class;
  3884. goto match_found;
  3885. } else if (is_compatible_boxed_valuetype (ctx,old_type, new_type, new_slot, FALSE) || is_compatible_boxed_valuetype (ctx, new_type, old_type, old_slot, FALSE)) {
  3886. match_class = mono_defaults.object_class;
  3887. goto match_found;
  3888. }
  3889. {
  3890. char *old_name = stack_slot_full_name (old_slot);
  3891. char *new_name = stack_slot_full_name (new_slot);
  3892. CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Could not merge stack at depth %d, types not compatible: %s X %s at 0x%04x", i, old_name, new_name, ctx->ip_offset));
  3893. g_free (old_name);
  3894. g_free (new_name);
  3895. }
  3896. set_stack_value (ctx, old_slot, &new_class->byval_arg, stack_slot_is_managed_pointer (old_slot));
  3897. goto end_verify;
  3898. match_found:
  3899. g_assert (match_class);
  3900. set_stack_value (ctx, old_slot, &match_class->byval_arg, stack_slot_is_managed_pointer (old_slot));
  3901. set_stack_value (ctx, new_slot, &match_class->byval_arg, stack_slot_is_managed_pointer (old_slot));
  3902. continue;
  3903. }
  3904. end_verify:
  3905. if (external)
  3906. to->flags |= IL_CODE_FLAG_WAS_TARGET;
  3907. to->flags |= IL_CODE_STACK_MERGED;
  3908. }
  3909. #define HANDLER_START(clause) ((clause)->flags == MONO_EXCEPTION_CLAUSE_FILTER ? (clause)->data.filter_offset : clause->handler_offset)
  3910. #define IS_CATCH_OR_FILTER(clause) ((clause)->flags == MONO_EXCEPTION_CLAUSE_FILTER || (clause)->flags == MONO_EXCEPTION_CLAUSE_NONE)
  3911. /*
  3912. * is_clause_in_range :
  3913. *
  3914. * Returns TRUE if either the protected block or the handler of @clause is in the @start - @end range.
  3915. */
  3916. static gboolean
  3917. is_clause_in_range (MonoExceptionClause *clause, guint32 start, guint32 end)
  3918. {
  3919. if (clause->try_offset >= start && clause->try_offset < end)
  3920. return TRUE;
  3921. if (HANDLER_START (clause) >= start && HANDLER_START (clause) < end)
  3922. return TRUE;
  3923. return FALSE;
  3924. }
  3925. /*
  3926. * is_clause_inside_range :
  3927. *
  3928. * Returns TRUE if @clause lies completely inside the @start - @end range.
  3929. */
  3930. static gboolean
  3931. is_clause_inside_range (MonoExceptionClause *clause, guint32 start, guint32 end)
  3932. {
  3933. if (clause->try_offset < start || (clause->try_offset + clause->try_len) > end)
  3934. return FALSE;
  3935. if (HANDLER_START (clause) < start || (clause->handler_offset + clause->handler_len) > end)
  3936. return FALSE;
  3937. return TRUE;
  3938. }
  3939. /*
  3940. * is_clause_nested :
  3941. *
  3942. * Returns TRUE if @nested is nested in @clause.
  3943. */
  3944. static gboolean
  3945. is_clause_nested (MonoExceptionClause *clause, MonoExceptionClause *nested)
  3946. {
  3947. if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER && is_clause_inside_range (nested, clause->data.filter_offset, clause->handler_offset))
  3948. return TRUE;
  3949. return is_clause_inside_range (nested, clause->try_offset, clause->try_offset + clause->try_len) ||
  3950. is_clause_inside_range (nested, clause->handler_offset, clause->handler_offset + clause->handler_len);
  3951. }
  3952. /* Test the relationship between 2 exception clauses. Follow P.1 12.4.2.7 of ECMA
  3953. * the each pair of exception must have the following properties:
  3954. * - one is fully nested on another (the outer must not be a filter clause) (the nested one must come earlier)
  3955. * - completely disjoin (none of the 3 regions of each entry overlap with the other 3)
  3956. * - mutual protection (protected block is EXACT the same, handlers are disjoin and all handler are catch or all handler are filter)
  3957. */
  3958. static void
  3959. verify_clause_relationship (VerifyContext *ctx, MonoExceptionClause *clause, MonoExceptionClause *to_test)
  3960. {
  3961. /*clause is nested*/
  3962. if (to_test->flags == MONO_EXCEPTION_CLAUSE_FILTER && is_clause_inside_range (clause, to_test->data.filter_offset, to_test->handler_offset)) {
  3963. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Exception clause inside filter"));
  3964. return;
  3965. }
  3966. /*wrong nesting order.*/
  3967. if (is_clause_nested (clause, to_test)) {
  3968. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Nested exception clause appears after enclosing clause"));
  3969. return;
  3970. }
  3971. /*mutual protection*/
  3972. if (clause->try_offset == to_test->try_offset && clause->try_len == to_test->try_len) {
  3973. /*handlers are not disjoint*/
  3974. if (is_clause_in_range (to_test, HANDLER_START (clause), clause->handler_offset + clause->handler_len)) {
  3975. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Exception handlers overlap"));
  3976. return;
  3977. }
  3978. /* handlers are not catch or filter */
  3979. if (!IS_CATCH_OR_FILTER (clause) || !IS_CATCH_OR_FILTER (to_test)) {
  3980. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Exception clauses with shared protected block are neither catch or filter"));
  3981. return;
  3982. }
  3983. /*OK*/
  3984. return;
  3985. }
  3986. /*not completelly disjoint*/
  3987. if ((is_clause_in_range (to_test, clause->try_offset, clause->try_offset + clause->try_len) ||
  3988. is_clause_in_range (to_test, HANDLER_START (clause), clause->handler_offset + clause->handler_len)) && !is_clause_nested (to_test, clause))
  3989. ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Exception clauses overlap"));
  3990. }
  3991. #define code_bounds_check(size) \
  3992. if (ADDP_IS_GREATER_OR_OVF (ip, size, end)) {\
  3993. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Code overrun starting with 0x%x at 0x%04x", *ip, ctx.ip_offset)); \
  3994. break; \
  3995. } \
  3996. static gboolean
  3997. mono_opcode_is_prefix (int op)
  3998. {
  3999. switch (op) {
  4000. case MONO_CEE_UNALIGNED_:
  4001. case MONO_CEE_VOLATILE_:
  4002. case MONO_CEE_TAIL_:
  4003. case MONO_CEE_CONSTRAINED_:
  4004. case MONO_CEE_READONLY_:
  4005. return TRUE;
  4006. }
  4007. return FALSE;
  4008. }
  4009. /*
  4010. * FIXME: need to distinguish between valid and verifiable.
  4011. * Need to keep track of types on the stack.
  4012. * Verify types for opcodes.
  4013. */
  4014. GSList*
  4015. mono_method_verify (MonoMethod *method, int level)
  4016. {
  4017. MonoError error;
  4018. const unsigned char *ip, *code_start;
  4019. const unsigned char *end;
  4020. MonoSimpleBasicBlock *bb = NULL, *original_bb = NULL;
  4021. int i, n, need_merge = 0, start = 0;
  4022. guint token, ip_offset = 0, prefix = 0;
  4023. MonoGenericContext *generic_context = NULL;
  4024. MonoImage *image;
  4025. VerifyContext ctx;
  4026. GSList *tmp;
  4027. VERIFIER_DEBUG ( printf ("Verify IL for method %s %s %s\n", method->klass->name_space, method->klass->name, method->name); );
  4028. init_verifier_stats ();
  4029. if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
  4030. (method->flags & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT))) {
  4031. return NULL;
  4032. }
  4033. memset (&ctx, 0, sizeof (VerifyContext));
  4034. //FIXME use mono_method_get_signature_full
  4035. ctx.signature = mono_method_signature (method);
  4036. if (!ctx.signature) {
  4037. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Could not decode method signature"));
  4038. finish_collect_stats ();
  4039. return ctx.list;
  4040. }
  4041. if (!method->is_generic && !method->klass->is_generic && ctx.signature->has_type_parameters) {
  4042. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Method and signature don't match in terms of genericity"));
  4043. finish_collect_stats ();
  4044. return ctx.list;
  4045. }
  4046. ctx.header = mono_method_get_header (method);
  4047. if (!ctx.header) {
  4048. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Could not decode method header"));
  4049. finish_collect_stats ();
  4050. return ctx.list;
  4051. }
  4052. ctx.method = method;
  4053. code_start = ip = ctx.header->code;
  4054. end = ip + ctx.header->code_size;
  4055. ctx.image = image = method->klass->image;
  4056. ctx.max_args = ctx.signature->param_count + ctx.signature->hasthis;
  4057. ctx.max_stack = ctx.header->max_stack;
  4058. ctx.verifiable = ctx.valid = 1;
  4059. ctx.level = level;
  4060. ctx.code = g_new (ILCodeDesc, ctx.header->code_size);
  4061. ctx.code_size = ctx.header->code_size;
  4062. MEM_ALLOC (sizeof (ILCodeDesc) * ctx.header->code_size);
  4063. memset(ctx.code, 0, sizeof (ILCodeDesc) * ctx.header->code_size);
  4064. ctx.num_locals = ctx.header->num_locals;
  4065. ctx.locals = g_memdup (ctx.header->locals, sizeof (MonoType*) * ctx.header->num_locals);
  4066. MEM_ALLOC (sizeof (MonoType*) * ctx.header->num_locals);
  4067. if (ctx.num_locals > 0 && !ctx.header->init_locals)
  4068. CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("Method with locals variable but without init locals set"));
  4069. ctx.params = g_new (MonoType*, ctx.max_args);
  4070. MEM_ALLOC (sizeof (MonoType*) * ctx.max_args);
  4071. if (ctx.signature->hasthis)
  4072. ctx.params [0] = method->klass->valuetype ? &method->klass->this_arg : &method->klass->byval_arg;
  4073. memcpy (ctx.params + ctx.signature->hasthis, ctx.signature->params, sizeof (MonoType *) * ctx.signature->param_count);
  4074. if (ctx.signature->is_inflated)
  4075. ctx.generic_context = generic_context = mono_method_get_context (method);
  4076. if (!generic_context && (method->klass->generic_container || method->is_generic)) {
  4077. if (method->is_generic)
  4078. ctx.generic_context = generic_context = &(mono_method_get_generic_container (method)->context);
  4079. else
  4080. ctx.generic_context = generic_context = &method->klass->generic_container->context;
  4081. }
  4082. for (i = 0; i < ctx.num_locals; ++i) {
  4083. MonoType *uninflated = ctx.locals [i];
  4084. ctx.locals [i] = mono_class_inflate_generic_type_checked (ctx.locals [i], ctx.generic_context, &error);
  4085. if (!mono_error_ok (&error)) {
  4086. char *name = mono_type_full_name (ctx.locals [i] ? ctx.locals [i] : uninflated);
  4087. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid local %d of type %s", i, name));
  4088. g_free (name);
  4089. mono_error_cleanup (&error);
  4090. /* we must not free (in cleanup) what was not yet allocated (but only copied) */
  4091. ctx.num_locals = i;
  4092. ctx.max_args = 0;
  4093. goto cleanup;
  4094. }
  4095. }
  4096. for (i = 0; i < ctx.max_args; ++i) {
  4097. MonoType *uninflated = ctx.params [i];
  4098. ctx.params [i] = mono_class_inflate_generic_type_checked (ctx.params [i], ctx.generic_context, &error);
  4099. if (!mono_error_ok (&error)) {
  4100. char *name = mono_type_full_name (ctx.params [i] ? ctx.params [i] : uninflated);
  4101. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid parameter %d of type %s", i, name));
  4102. g_free (name);
  4103. mono_error_cleanup (&error);
  4104. /* we must not free (in cleanup) what was not yet allocated (but only copied) */
  4105. ctx.max_args = i;
  4106. goto cleanup;
  4107. }
  4108. }
  4109. stack_init (&ctx, &ctx.eval);
  4110. for (i = 0; i < ctx.num_locals; ++i) {
  4111. if (!mono_type_is_valid_in_context (&ctx, ctx.locals [i]))
  4112. break;
  4113. if (get_stack_type (ctx.locals [i]) == TYPE_INV) {
  4114. char *name = mono_type_full_name (ctx.locals [i]);
  4115. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid local %i of type %s", i, name));
  4116. g_free (name);
  4117. break;
  4118. }
  4119. }
  4120. for (i = 0; i < ctx.max_args; ++i) {
  4121. if (!mono_type_is_valid_in_context (&ctx, ctx.params [i]))
  4122. break;
  4123. if (get_stack_type (ctx.params [i]) == TYPE_INV) {
  4124. char *name = mono_type_full_name (ctx.params [i]);
  4125. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid parameter %i of type %s", i, name));
  4126. g_free (name);
  4127. break;
  4128. }
  4129. }
  4130. if (!ctx.valid)
  4131. goto cleanup;
  4132. for (i = 0; i < ctx.header->num_clauses && ctx.valid; ++i) {
  4133. MonoExceptionClause *clause = ctx.header->clauses + i;
  4134. VERIFIER_DEBUG (printf ("clause try %x len %x filter at %x handler at %x len %x\n", clause->try_offset, clause->try_len, clause->data.filter_offset, clause->handler_offset, clause->handler_len); );
  4135. if (clause->try_offset > ctx.code_size || ADD_IS_GREATER_OR_OVF (clause->try_offset, clause->try_len, ctx.code_size))
  4136. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("try clause out of bounds at 0x%04x", clause->try_offset));
  4137. if (clause->try_len <= 0)
  4138. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("try clause len <= 0 at 0x%04x", clause->try_offset));
  4139. if (clause->handler_offset > ctx.code_size || ADD_IS_GREATER_OR_OVF (clause->handler_offset, clause->handler_len, ctx.code_size))
  4140. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("handler clause out of bounds at 0x%04x", clause->try_offset));
  4141. if (clause->handler_len <= 0)
  4142. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("handler clause len <= 0 at 0x%04x", clause->try_offset));
  4143. if (clause->try_offset < clause->handler_offset && ADD_IS_GREATER_OR_OVF (clause->try_offset, clause->try_len, HANDLER_START (clause)))
  4144. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("try block (at 0x%04x) includes handler block (at 0x%04x)", clause->try_offset, clause->handler_offset));
  4145. if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
  4146. if (clause->data.filter_offset > ctx.code_size)
  4147. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("filter clause out of bounds at 0x%04x", clause->try_offset));
  4148. if (clause->data.filter_offset >= clause->handler_offset)
  4149. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("filter clause must come before the handler clause at 0x%04x", clause->data.filter_offset));
  4150. }
  4151. for (n = i + 1; n < ctx.header->num_clauses && ctx.valid; ++n)
  4152. verify_clause_relationship (&ctx, clause, ctx.header->clauses + n);
  4153. if (!ctx.valid)
  4154. break;
  4155. ctx.code [clause->try_offset].flags |= IL_CODE_FLAG_WAS_TARGET;
  4156. if (clause->try_offset + clause->try_len < ctx.code_size)
  4157. ctx.code [clause->try_offset + clause->try_len].flags |= IL_CODE_FLAG_WAS_TARGET;
  4158. if (clause->handler_offset + clause->handler_len < ctx.code_size)
  4159. ctx.code [clause->handler_offset + clause->handler_len].flags |= IL_CODE_FLAG_WAS_TARGET;
  4160. if (clause->flags == MONO_EXCEPTION_CLAUSE_NONE) {
  4161. if (!clause->data.catch_class) {
  4162. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Catch clause %d with invalid type", i));
  4163. break;
  4164. }
  4165. init_stack_with_value_at_exception_boundary (&ctx, ctx.code + clause->handler_offset, clause->data.catch_class);
  4166. }
  4167. else if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
  4168. init_stack_with_value_at_exception_boundary (&ctx, ctx.code + clause->data.filter_offset, mono_defaults.exception_class);
  4169. init_stack_with_value_at_exception_boundary (&ctx, ctx.code + clause->handler_offset, mono_defaults.exception_class);
  4170. }
  4171. }
  4172. original_bb = bb = mono_basic_block_split (method, &error);
  4173. if (!mono_error_ok (&error)) {
  4174. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid branch target: %s", mono_error_get_message (&error)));
  4175. mono_error_cleanup (&error);
  4176. goto cleanup;
  4177. }
  4178. g_assert (bb);
  4179. while (ip < end && ctx.valid) {
  4180. int op_size;
  4181. ip_offset = ip - code_start;
  4182. {
  4183. const unsigned char *ip_copy = ip;
  4184. int op;
  4185. if (ip_offset > bb->end) {
  4186. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Branch or EH block at [0x%04x] targets middle instruction at 0x%04x", bb->end, ip_offset));
  4187. goto cleanup;
  4188. }
  4189. if (ip_offset == bb->end)
  4190. bb = bb->next;
  4191. op_size = mono_opcode_value_and_size (&ip_copy, end, &op);
  4192. if (op_size == -1) {
  4193. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid instruction %x at 0x%04x", *ip, ip_offset));
  4194. goto cleanup;
  4195. }
  4196. if (ADD_IS_GREATER_OR_OVF (ip_offset, op_size, bb->end)) {
  4197. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Branch or EH block targets middle of instruction at 0x%04x", ip_offset));
  4198. goto cleanup;
  4199. }
  4200. /*Last Instruction*/
  4201. if (ip_offset + op_size == bb->end && mono_opcode_is_prefix (op)) {
  4202. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Branch or EH block targets between prefix '%s' and instruction at 0x%04x", mono_opcode_name (op), ip_offset));
  4203. goto cleanup;
  4204. }
  4205. }
  4206. ctx.ip_offset = ip_offset = ip - code_start;
  4207. /*We need to check against fallthrou in and out of protected blocks.
  4208. * For fallout we check the once a protected block ends, if the start flag is not set.
  4209. * Likewise for fallthru in, we check if ip is the start of a protected block and start is not set
  4210. * TODO convert these checks to be done using flags and not this loop
  4211. */
  4212. for (i = 0; i < ctx.header->num_clauses && ctx.valid; ++i) {
  4213. MonoExceptionClause *clause = ctx.header->clauses + i;
  4214. if ((clause->try_offset + clause->try_len == ip_offset) && start == 0) {
  4215. CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("fallthru off try block at 0x%04x", ip_offset));
  4216. start = 1;
  4217. }
  4218. if ((clause->handler_offset + clause->handler_len == ip_offset) && start == 0) {
  4219. if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
  4220. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("fallout of handler block at 0x%04x", ip_offset));
  4221. else
  4222. CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("fallout of handler block at 0x%04x", ip_offset));
  4223. start = 1;
  4224. }
  4225. if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER && clause->handler_offset == ip_offset && start == 0) {
  4226. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("fallout of filter block at 0x%04x", ip_offset));
  4227. start = 1;
  4228. }
  4229. if (clause->handler_offset == ip_offset && start == 0) {
  4230. CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("fallthru handler block at 0x%04x", ip_offset));
  4231. start = 1;
  4232. }
  4233. if (clause->try_offset == ip_offset && ctx.eval.size > 0 && start == 0) {
  4234. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Try to enter try block with a non-empty stack at 0x%04x", ip_offset));
  4235. start = 1;
  4236. }
  4237. }
  4238. /*This must be done after fallthru detection otherwise it won't happen.*/
  4239. if (bb->dead) {
  4240. /*FIXME remove this once we move all bad branch checking code to use BB only*/
  4241. ctx.code [ip_offset].flags |= IL_CODE_FLAG_SEEN;
  4242. ip += op_size;
  4243. continue;
  4244. }
  4245. if (!ctx.valid)
  4246. break;
  4247. if (need_merge) {
  4248. VERIFIER_DEBUG ( printf ("extra merge needed! 0x%04x \n", ctx.target); );
  4249. merge_stacks (&ctx, &ctx.eval, &ctx.code [ctx.target], FALSE, TRUE);
  4250. need_merge = 0;
  4251. }
  4252. merge_stacks (&ctx, &ctx.eval, &ctx.code[ip_offset], start, FALSE);
  4253. start = 0;
  4254. /*TODO we can fast detect a forward branch or exception block targeting code after prefix, we should fail fast*/
  4255. #ifdef MONO_VERIFIER_DEBUG
  4256. {
  4257. char *discode;
  4258. discode = mono_disasm_code_one (NULL, method, ip, NULL);
  4259. discode [strlen (discode) - 1] = 0; /* no \n */
  4260. g_print ("[%d] %-29s (%d)\n", ip_offset, discode, ctx.eval.size);
  4261. g_free (discode);
  4262. }
  4263. dump_stack_state (&ctx.code [ip_offset]);
  4264. dump_stack_state (&ctx.eval);
  4265. #endif
  4266. switch (*ip) {
  4267. case CEE_NOP:
  4268. case CEE_BREAK:
  4269. ++ip;
  4270. break;
  4271. case CEE_LDARG_0:
  4272. case CEE_LDARG_1:
  4273. case CEE_LDARG_2:
  4274. case CEE_LDARG_3:
  4275. push_arg (&ctx, *ip - CEE_LDARG_0, FALSE);
  4276. ++ip;
  4277. break;
  4278. case CEE_LDARG_S:
  4279. case CEE_LDARGA_S:
  4280. code_bounds_check (2);
  4281. push_arg (&ctx, ip [1], *ip == CEE_LDARGA_S);
  4282. ip += 2;
  4283. break;
  4284. case CEE_ADD_OVF_UN:
  4285. do_binop (&ctx, *ip, add_ovf_un_table);
  4286. ++ip;
  4287. break;
  4288. case CEE_SUB_OVF_UN:
  4289. do_binop (&ctx, *ip, sub_ovf_un_table);
  4290. ++ip;
  4291. break;
  4292. case CEE_ADD_OVF:
  4293. case CEE_SUB_OVF:
  4294. case CEE_MUL_OVF:
  4295. case CEE_MUL_OVF_UN:
  4296. do_binop (&ctx, *ip, bin_ovf_table);
  4297. ++ip;
  4298. break;
  4299. case CEE_ADD:
  4300. do_binop (&ctx, *ip, add_table);
  4301. ++ip;
  4302. break;
  4303. case CEE_SUB:
  4304. do_binop (&ctx, *ip, sub_table);
  4305. ++ip;
  4306. break;
  4307. case CEE_MUL:
  4308. case CEE_DIV:
  4309. case CEE_REM:
  4310. do_binop (&ctx, *ip, bin_op_table);
  4311. ++ip;
  4312. break;
  4313. case CEE_AND:
  4314. case CEE_DIV_UN:
  4315. case CEE_OR:
  4316. case CEE_REM_UN:
  4317. case CEE_XOR:
  4318. do_binop (&ctx, *ip, int_bin_op_table);
  4319. ++ip;
  4320. break;
  4321. case CEE_SHL:
  4322. case CEE_SHR:
  4323. case CEE_SHR_UN:
  4324. do_binop (&ctx, *ip, shift_op_table);
  4325. ++ip;
  4326. break;
  4327. case CEE_POP:
  4328. if (!check_underflow (&ctx, 1))
  4329. break;
  4330. stack_pop_safe (&ctx);
  4331. ++ip;
  4332. break;
  4333. case CEE_RET:
  4334. do_ret (&ctx);
  4335. ++ip;
  4336. start = 1;
  4337. break;
  4338. case CEE_LDLOC_0:
  4339. case CEE_LDLOC_1:
  4340. case CEE_LDLOC_2:
  4341. case CEE_LDLOC_3:
  4342. /*TODO support definite assignment verification? */
  4343. push_local (&ctx, *ip - CEE_LDLOC_0, FALSE);
  4344. ++ip;
  4345. break;
  4346. case CEE_STLOC_0:
  4347. case CEE_STLOC_1:
  4348. case CEE_STLOC_2:
  4349. case CEE_STLOC_3:
  4350. store_local (&ctx, *ip - CEE_STLOC_0);
  4351. ++ip;
  4352. break;
  4353. case CEE_STLOC_S:
  4354. code_bounds_check (2);
  4355. store_local (&ctx, ip [1]);
  4356. ip += 2;
  4357. break;
  4358. case CEE_STARG_S:
  4359. code_bounds_check (2);
  4360. store_arg (&ctx, ip [1]);
  4361. ip += 2;
  4362. break;
  4363. case CEE_LDC_I4_M1:
  4364. case CEE_LDC_I4_0:
  4365. case CEE_LDC_I4_1:
  4366. case CEE_LDC_I4_2:
  4367. case CEE_LDC_I4_3:
  4368. case CEE_LDC_I4_4:
  4369. case CEE_LDC_I4_5:
  4370. case CEE_LDC_I4_6:
  4371. case CEE_LDC_I4_7:
  4372. case CEE_LDC_I4_8:
  4373. if (check_overflow (&ctx))
  4374. stack_push_val (&ctx, TYPE_I4, &mono_defaults.int32_class->byval_arg);
  4375. ++ip;
  4376. break;
  4377. case CEE_LDC_I4_S:
  4378. code_bounds_check (2);
  4379. if (check_overflow (&ctx))
  4380. stack_push_val (&ctx, TYPE_I4, &mono_defaults.int32_class->byval_arg);
  4381. ip += 2;
  4382. break;
  4383. case CEE_LDC_I4:
  4384. code_bounds_check (5);
  4385. if (check_overflow (&ctx))
  4386. stack_push_val (&ctx,TYPE_I4, &mono_defaults.int32_class->byval_arg);
  4387. ip += 5;
  4388. break;
  4389. case CEE_LDC_I8:
  4390. code_bounds_check (9);
  4391. if (check_overflow (&ctx))
  4392. stack_push_val (&ctx,TYPE_I8, &mono_defaults.int64_class->byval_arg);
  4393. ip += 9;
  4394. break;
  4395. case CEE_LDC_R4:
  4396. code_bounds_check (5);
  4397. if (check_overflow (&ctx))
  4398. stack_push_val (&ctx, TYPE_R8, &mono_defaults.double_class->byval_arg);
  4399. ip += 5;
  4400. break;
  4401. case CEE_LDC_R8:
  4402. code_bounds_check (9);
  4403. if (check_overflow (&ctx))
  4404. stack_push_val (&ctx, TYPE_R8, &mono_defaults.double_class->byval_arg);
  4405. ip += 9;
  4406. break;
  4407. case CEE_LDNULL:
  4408. if (check_overflow (&ctx))
  4409. stack_push_val (&ctx, TYPE_COMPLEX | NULL_LITERAL_MASK, &mono_defaults.object_class->byval_arg);
  4410. ++ip;
  4411. break;
  4412. case CEE_BEQ_S:
  4413. case CEE_BNE_UN_S:
  4414. code_bounds_check (2);
  4415. do_branch_op (&ctx, (signed char)ip [1] + 2, cmp_br_eq_op);
  4416. ip += 2;
  4417. need_merge = 1;
  4418. break;
  4419. case CEE_BGE_S:
  4420. case CEE_BGT_S:
  4421. case CEE_BLE_S:
  4422. case CEE_BLT_S:
  4423. case CEE_BGE_UN_S:
  4424. case CEE_BGT_UN_S:
  4425. case CEE_BLE_UN_S:
  4426. case CEE_BLT_UN_S:
  4427. code_bounds_check (2);
  4428. do_branch_op (&ctx, (signed char)ip [1] + 2, cmp_br_op);
  4429. ip += 2;
  4430. need_merge = 1;
  4431. break;
  4432. case CEE_BEQ:
  4433. case CEE_BNE_UN:
  4434. code_bounds_check (5);
  4435. do_branch_op (&ctx, (gint32)read32 (ip + 1) + 5, cmp_br_eq_op);
  4436. ip += 5;
  4437. need_merge = 1;
  4438. break;
  4439. case CEE_BGE:
  4440. case CEE_BGT:
  4441. case CEE_BLE:
  4442. case CEE_BLT:
  4443. case CEE_BGE_UN:
  4444. case CEE_BGT_UN:
  4445. case CEE_BLE_UN:
  4446. case CEE_BLT_UN:
  4447. code_bounds_check (5);
  4448. do_branch_op (&ctx, (gint32)read32 (ip + 1) + 5, cmp_br_op);
  4449. ip += 5;
  4450. need_merge = 1;
  4451. break;
  4452. case CEE_LDLOC_S:
  4453. case CEE_LDLOCA_S:
  4454. code_bounds_check (2);
  4455. push_local (&ctx, ip[1], *ip == CEE_LDLOCA_S);
  4456. ip += 2;
  4457. break;
  4458. case CEE_UNUSED99:
  4459. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Use of the `unused' opcode"));
  4460. ++ip;
  4461. break;
  4462. case CEE_DUP: {
  4463. ILStackDesc *top;
  4464. if (!check_underflow (&ctx, 1))
  4465. break;
  4466. if (!check_overflow (&ctx))
  4467. break;
  4468. top = stack_push (&ctx);
  4469. copy_stack_value (top, stack_peek (&ctx, 1));
  4470. ++ip;
  4471. break;
  4472. }
  4473. case CEE_JMP:
  4474. code_bounds_check (5);
  4475. if (ctx.eval.size)
  4476. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Eval stack must be empty in jmp at 0x%04x", ip_offset));
  4477. token = read32 (ip + 1);
  4478. if (in_any_block (ctx.header, ip_offset))
  4479. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("jmp cannot escape exception blocks at 0x%04x", ip_offset));
  4480. CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("Intruction jmp is not verifiable at 0x%04x", ctx.ip_offset));
  4481. /*
  4482. * FIXME: check signature, retval, arguments etc.
  4483. */
  4484. ip += 5;
  4485. break;
  4486. case CEE_CALL:
  4487. case CEE_CALLVIRT:
  4488. code_bounds_check (5);
  4489. do_invoke_method (&ctx, read32 (ip + 1), *ip == CEE_CALLVIRT);
  4490. ip += 5;
  4491. break;
  4492. case CEE_CALLI:
  4493. code_bounds_check (5);
  4494. token = read32 (ip + 1);
  4495. /*
  4496. * FIXME: check signature, retval, arguments etc.
  4497. * FIXME: check requirements for tail call
  4498. */
  4499. CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("Intruction calli is not verifiable at 0x%04x", ctx.ip_offset));
  4500. ip += 5;
  4501. break;
  4502. case CEE_BR_S:
  4503. code_bounds_check (2);
  4504. do_static_branch (&ctx, (signed char)ip [1] + 2);
  4505. need_merge = 1;
  4506. ip += 2;
  4507. start = 1;
  4508. break;
  4509. case CEE_BRFALSE_S:
  4510. case CEE_BRTRUE_S:
  4511. code_bounds_check (2);
  4512. do_boolean_branch_op (&ctx, (signed char)ip [1] + 2);
  4513. ip += 2;
  4514. need_merge = 1;
  4515. break;
  4516. case CEE_BR:
  4517. code_bounds_check (5);
  4518. do_static_branch (&ctx, (gint32)read32 (ip + 1) + 5);
  4519. need_merge = 1;
  4520. ip += 5;
  4521. start = 1;
  4522. break;
  4523. case CEE_BRFALSE:
  4524. case CEE_BRTRUE:
  4525. code_bounds_check (5);
  4526. do_boolean_branch_op (&ctx, (gint32)read32 (ip + 1) + 5);
  4527. ip += 5;
  4528. need_merge = 1;
  4529. break;
  4530. case CEE_SWITCH: {
  4531. guint32 entries;
  4532. code_bounds_check (5);
  4533. entries = read32 (ip + 1);
  4534. if (entries > 0xFFFFFFFFU / sizeof (guint32))
  4535. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Too many switch entries %x at 0x%04x", entries, ctx.ip_offset));
  4536. ip += 5;
  4537. code_bounds_check (sizeof (guint32) * entries);
  4538. do_switch (&ctx, entries, ip);
  4539. ip += sizeof (guint32) * entries;
  4540. break;
  4541. }
  4542. case CEE_LDIND_I1:
  4543. case CEE_LDIND_U1:
  4544. case CEE_LDIND_I2:
  4545. case CEE_LDIND_U2:
  4546. case CEE_LDIND_I4:
  4547. case CEE_LDIND_U4:
  4548. case CEE_LDIND_I8:
  4549. case CEE_LDIND_I:
  4550. case CEE_LDIND_R4:
  4551. case CEE_LDIND_R8:
  4552. case CEE_LDIND_REF:
  4553. do_load_indirect (&ctx, *ip);
  4554. ++ip;
  4555. break;
  4556. case CEE_STIND_REF:
  4557. case CEE_STIND_I1:
  4558. case CEE_STIND_I2:
  4559. case CEE_STIND_I4:
  4560. case CEE_STIND_I8:
  4561. case CEE_STIND_R4:
  4562. case CEE_STIND_R8:
  4563. case CEE_STIND_I:
  4564. do_store_indirect (&ctx, *ip);
  4565. ++ip;
  4566. break;
  4567. case CEE_NOT:
  4568. case CEE_NEG:
  4569. do_unary_math_op (&ctx, *ip);
  4570. ++ip;
  4571. break;
  4572. case CEE_CONV_I1:
  4573. case CEE_CONV_I2:
  4574. case CEE_CONV_I4:
  4575. case CEE_CONV_U1:
  4576. case CEE_CONV_U2:
  4577. case CEE_CONV_U4:
  4578. do_conversion (&ctx, TYPE_I4);
  4579. ++ip;
  4580. break;
  4581. case CEE_CONV_I8:
  4582. case CEE_CONV_U8:
  4583. do_conversion (&ctx, TYPE_I8);
  4584. ++ip;
  4585. break;
  4586. case CEE_CONV_R4:
  4587. case CEE_CONV_R8:
  4588. case CEE_CONV_R_UN:
  4589. do_conversion (&ctx, TYPE_R8);
  4590. ++ip;
  4591. break;
  4592. case CEE_CONV_I:
  4593. case CEE_CONV_U:
  4594. do_conversion (&ctx, TYPE_NATIVE_INT);
  4595. ++ip;
  4596. break;
  4597. case CEE_CPOBJ:
  4598. code_bounds_check (5);
  4599. do_cpobj (&ctx, read32 (ip + 1));
  4600. ip += 5;
  4601. break;
  4602. case CEE_LDOBJ:
  4603. code_bounds_check (5);
  4604. do_ldobj_value (&ctx, read32 (ip + 1));
  4605. ip += 5;
  4606. break;
  4607. case CEE_LDSTR:
  4608. code_bounds_check (5);
  4609. do_ldstr (&ctx, read32 (ip + 1));
  4610. ip += 5;
  4611. break;
  4612. case CEE_NEWOBJ:
  4613. code_bounds_check (5);
  4614. do_newobj (&ctx, read32 (ip + 1));
  4615. ip += 5;
  4616. break;
  4617. case CEE_CASTCLASS:
  4618. case CEE_ISINST:
  4619. code_bounds_check (5);
  4620. do_cast (&ctx, read32 (ip + 1), *ip == CEE_CASTCLASS ? "castclass" : "isinst");
  4621. ip += 5;
  4622. break;
  4623. case CEE_UNUSED58:
  4624. case CEE_UNUSED1:
  4625. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Use of the `unused' opcode"));
  4626. ++ip;
  4627. break;
  4628. case CEE_UNBOX:
  4629. code_bounds_check (5);
  4630. do_unbox_value (&ctx, read32 (ip + 1));
  4631. ip += 5;
  4632. break;
  4633. case CEE_THROW:
  4634. do_throw (&ctx);
  4635. start = 1;
  4636. ++ip;
  4637. break;
  4638. case CEE_LDFLD:
  4639. case CEE_LDFLDA:
  4640. code_bounds_check (5);
  4641. do_push_field (&ctx, read32 (ip + 1), *ip == CEE_LDFLDA);
  4642. ip += 5;
  4643. break;
  4644. case CEE_LDSFLD:
  4645. case CEE_LDSFLDA:
  4646. code_bounds_check (5);
  4647. do_push_static_field (&ctx, read32 (ip + 1), *ip == CEE_LDSFLDA);
  4648. ip += 5;
  4649. break;
  4650. case CEE_STFLD:
  4651. code_bounds_check (5);
  4652. do_store_field (&ctx, read32 (ip + 1));
  4653. ip += 5;
  4654. break;
  4655. case CEE_STSFLD:
  4656. code_bounds_check (5);
  4657. do_store_static_field (&ctx, read32 (ip + 1));
  4658. ip += 5;
  4659. break;
  4660. case CEE_STOBJ:
  4661. code_bounds_check (5);
  4662. do_stobj (&ctx, read32 (ip + 1));
  4663. ip += 5;
  4664. break;
  4665. case CEE_CONV_OVF_I1_UN:
  4666. case CEE_CONV_OVF_I2_UN:
  4667. case CEE_CONV_OVF_I4_UN:
  4668. case CEE_CONV_OVF_U1_UN:
  4669. case CEE_CONV_OVF_U2_UN:
  4670. case CEE_CONV_OVF_U4_UN:
  4671. do_conversion (&ctx, TYPE_I4);
  4672. ++ip;
  4673. break;
  4674. case CEE_CONV_OVF_I8_UN:
  4675. case CEE_CONV_OVF_U8_UN:
  4676. do_conversion (&ctx, TYPE_I8);
  4677. ++ip;
  4678. break;
  4679. case CEE_CONV_OVF_I_UN:
  4680. case CEE_CONV_OVF_U_UN:
  4681. do_conversion (&ctx, TYPE_NATIVE_INT);
  4682. ++ip;
  4683. break;
  4684. case CEE_BOX:
  4685. code_bounds_check (5);
  4686. do_box_value (&ctx, read32 (ip + 1));
  4687. ip += 5;
  4688. break;
  4689. case CEE_NEWARR:
  4690. code_bounds_check (5);
  4691. do_newarr (&ctx, read32 (ip + 1));
  4692. ip += 5;
  4693. break;
  4694. case CEE_LDLEN:
  4695. do_ldlen (&ctx);
  4696. ++ip;
  4697. break;
  4698. case CEE_LDELEMA:
  4699. code_bounds_check (5);
  4700. do_ldelema (&ctx, read32 (ip + 1));
  4701. ip += 5;
  4702. break;
  4703. case CEE_LDELEM_I1:
  4704. case CEE_LDELEM_U1:
  4705. case CEE_LDELEM_I2:
  4706. case CEE_LDELEM_U2:
  4707. case CEE_LDELEM_I4:
  4708. case CEE_LDELEM_U4:
  4709. case CEE_LDELEM_I8:
  4710. case CEE_LDELEM_I:
  4711. case CEE_LDELEM_R4:
  4712. case CEE_LDELEM_R8:
  4713. case CEE_LDELEM_REF:
  4714. do_ldelem (&ctx, *ip, 0);
  4715. ++ip;
  4716. break;
  4717. case CEE_STELEM_I:
  4718. case CEE_STELEM_I1:
  4719. case CEE_STELEM_I2:
  4720. case CEE_STELEM_I4:
  4721. case CEE_STELEM_I8:
  4722. case CEE_STELEM_R4:
  4723. case CEE_STELEM_R8:
  4724. case CEE_STELEM_REF:
  4725. do_stelem (&ctx, *ip, 0);
  4726. ++ip;
  4727. break;
  4728. case CEE_LDELEM:
  4729. code_bounds_check (5);
  4730. do_ldelem (&ctx, *ip, read32 (ip + 1));
  4731. ip += 5;
  4732. break;
  4733. case CEE_STELEM:
  4734. code_bounds_check (5);
  4735. do_stelem (&ctx, *ip, read32 (ip + 1));
  4736. ip += 5;
  4737. break;
  4738. case CEE_UNBOX_ANY:
  4739. code_bounds_check (5);
  4740. do_unbox_any (&ctx, read32 (ip + 1));
  4741. ip += 5;
  4742. break;
  4743. case CEE_CONV_OVF_I1:
  4744. case CEE_CONV_OVF_U1:
  4745. case CEE_CONV_OVF_I2:
  4746. case CEE_CONV_OVF_U2:
  4747. case CEE_CONV_OVF_I4:
  4748. case CEE_CONV_OVF_U4:
  4749. do_conversion (&ctx, TYPE_I4);
  4750. ++ip;
  4751. break;
  4752. case CEE_CONV_OVF_I8:
  4753. case CEE_CONV_OVF_U8:
  4754. do_conversion (&ctx, TYPE_I8);
  4755. ++ip;
  4756. break;
  4757. case CEE_CONV_OVF_I:
  4758. case CEE_CONV_OVF_U:
  4759. do_conversion (&ctx, TYPE_NATIVE_INT);
  4760. ++ip;
  4761. break;
  4762. case CEE_REFANYVAL:
  4763. code_bounds_check (5);
  4764. do_refanyval (&ctx, read32 (ip + 1));
  4765. ip += 5;
  4766. break;
  4767. case CEE_CKFINITE:
  4768. do_ckfinite (&ctx);
  4769. ++ip;
  4770. break;
  4771. case CEE_MKREFANY:
  4772. code_bounds_check (5);
  4773. do_mkrefany (&ctx, read32 (ip + 1));
  4774. ip += 5;
  4775. break;
  4776. case CEE_LDTOKEN:
  4777. code_bounds_check (5);
  4778. do_load_token (&ctx, read32 (ip + 1));
  4779. ip += 5;
  4780. break;
  4781. case CEE_ENDFINALLY:
  4782. if (!is_correct_endfinally (ctx.header, ip_offset))
  4783. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("endfinally must be used inside a finally/fault handler at 0x%04x", ctx.ip_offset));
  4784. ctx.eval.size = 0;
  4785. start = 1;
  4786. ++ip;
  4787. break;
  4788. case CEE_LEAVE:
  4789. code_bounds_check (5);
  4790. do_leave (&ctx, read32 (ip + 1) + 5);
  4791. ip += 5;
  4792. start = 1;
  4793. need_merge = 1;
  4794. break;
  4795. case CEE_LEAVE_S:
  4796. code_bounds_check (2);
  4797. do_leave (&ctx, (signed char)ip [1] + 2);
  4798. ip += 2;
  4799. start = 1;
  4800. need_merge = 1;
  4801. break;
  4802. case CEE_PREFIX1:
  4803. code_bounds_check (2);
  4804. ++ip;
  4805. switch (*ip) {
  4806. case CEE_STLOC:
  4807. code_bounds_check (3);
  4808. store_local (&ctx, read16 (ip + 1));
  4809. ip += 3;
  4810. break;
  4811. case CEE_CEQ:
  4812. do_cmp_op (&ctx, cmp_br_eq_op, *ip);
  4813. ++ip;
  4814. break;
  4815. case CEE_CGT:
  4816. case CEE_CGT_UN:
  4817. case CEE_CLT:
  4818. case CEE_CLT_UN:
  4819. do_cmp_op (&ctx, cmp_br_op, *ip);
  4820. ++ip;
  4821. break;
  4822. case CEE_STARG:
  4823. code_bounds_check (3);
  4824. store_arg (&ctx, read16 (ip + 1) );
  4825. ip += 3;
  4826. break;
  4827. case CEE_ARGLIST:
  4828. if (!check_overflow (&ctx))
  4829. break;
  4830. if (ctx.signature->call_convention != MONO_CALL_VARARG)
  4831. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Cannot use arglist on method without VARGARG calling convention at 0x%04x", ctx.ip_offset));
  4832. set_stack_value (&ctx, stack_push (&ctx), &mono_defaults.argumenthandle_class->byval_arg, FALSE);
  4833. ++ip;
  4834. break;
  4835. case CEE_LDFTN:
  4836. code_bounds_check (5);
  4837. do_load_function_ptr (&ctx, read32 (ip + 1), FALSE);
  4838. ip += 5;
  4839. break;
  4840. case CEE_LDVIRTFTN:
  4841. code_bounds_check (5);
  4842. do_load_function_ptr (&ctx, read32 (ip + 1), TRUE);
  4843. ip += 5;
  4844. break;
  4845. case CEE_LDARG:
  4846. case CEE_LDARGA:
  4847. code_bounds_check (3);
  4848. push_arg (&ctx, read16 (ip + 1), *ip == CEE_LDARGA);
  4849. ip += 3;
  4850. break;
  4851. case CEE_LDLOC:
  4852. case CEE_LDLOCA:
  4853. code_bounds_check (3);
  4854. push_local (&ctx, read16 (ip + 1), *ip == CEE_LDLOCA);
  4855. ip += 3;
  4856. break;
  4857. case CEE_LOCALLOC:
  4858. do_localloc (&ctx);
  4859. ++ip;
  4860. break;
  4861. case CEE_UNUSED56:
  4862. case CEE_UNUSED57:
  4863. case CEE_UNUSED70:
  4864. case CEE_UNUSED:
  4865. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Use of the `unused' opcode"));
  4866. ++ip;
  4867. break;
  4868. case CEE_ENDFILTER:
  4869. do_endfilter (&ctx);
  4870. start = 1;
  4871. ++ip;
  4872. break;
  4873. case CEE_UNALIGNED_:
  4874. code_bounds_check (2);
  4875. prefix |= PREFIX_UNALIGNED;
  4876. ip += 2;
  4877. break;
  4878. case CEE_VOLATILE_:
  4879. prefix |= PREFIX_VOLATILE;
  4880. ++ip;
  4881. break;
  4882. case CEE_TAIL_:
  4883. prefix |= PREFIX_TAIL;
  4884. ++ip;
  4885. if (ip < end && (*ip != CEE_CALL && *ip != CEE_CALLI && *ip != CEE_CALLVIRT))
  4886. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("tail prefix must be used only with call opcodes at 0x%04x", ip_offset));
  4887. break;
  4888. case CEE_INITOBJ:
  4889. code_bounds_check (5);
  4890. do_initobj (&ctx, read32 (ip + 1));
  4891. ip += 5;
  4892. break;
  4893. case CEE_CONSTRAINED_:
  4894. code_bounds_check (5);
  4895. ctx.constrained_type = get_boxable_mono_type (&ctx, read32 (ip + 1), "constrained.");
  4896. prefix |= PREFIX_CONSTRAINED;
  4897. ip += 5;
  4898. break;
  4899. case CEE_READONLY_:
  4900. prefix |= PREFIX_READONLY;
  4901. ip++;
  4902. break;
  4903. case CEE_CPBLK:
  4904. CLEAR_PREFIX (&ctx, PREFIX_UNALIGNED | PREFIX_VOLATILE);
  4905. if (!check_underflow (&ctx, 3))
  4906. break;
  4907. CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("Instruction cpblk is not verifiable at 0x%04x", ctx.ip_offset));
  4908. ip++;
  4909. break;
  4910. case CEE_INITBLK:
  4911. CLEAR_PREFIX (&ctx, PREFIX_UNALIGNED | PREFIX_VOLATILE);
  4912. if (!check_underflow (&ctx, 3))
  4913. break;
  4914. CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("Instruction initblk is not verifiable at 0x%04x", ctx.ip_offset));
  4915. ip++;
  4916. break;
  4917. case CEE_NO_:
  4918. ip += 2;
  4919. break;
  4920. case CEE_RETHROW:
  4921. if (!is_correct_rethrow (ctx.header, ip_offset))
  4922. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("rethrow must be used inside a catch handler at 0x%04x", ctx.ip_offset));
  4923. ctx.eval.size = 0;
  4924. start = 1;
  4925. ++ip;
  4926. break;
  4927. case CEE_SIZEOF:
  4928. code_bounds_check (5);
  4929. do_sizeof (&ctx, read32 (ip + 1));
  4930. ip += 5;
  4931. break;
  4932. case CEE_REFANYTYPE:
  4933. do_refanytype (&ctx);
  4934. ++ip;
  4935. break;
  4936. default:
  4937. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid instruction FE %x at 0x%04x", *ip, ctx.ip_offset));
  4938. ++ip;
  4939. }
  4940. break;
  4941. default:
  4942. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid instruction %x at 0x%04x", *ip, ctx.ip_offset));
  4943. ++ip;
  4944. }
  4945. /*TODO we can fast detect a forward branch or exception block targeting code after prefix, we should fail fast*/
  4946. if (prefix) {
  4947. if (!ctx.prefix_set) //first prefix
  4948. ctx.code [ctx.ip_offset].flags |= IL_CODE_FLAG_SEEN;
  4949. ctx.prefix_set |= prefix;
  4950. ctx.has_flags = TRUE;
  4951. prefix = 0;
  4952. } else {
  4953. if (!ctx.has_flags)
  4954. ctx.code [ctx.ip_offset].flags |= IL_CODE_FLAG_SEEN;
  4955. if (ctx.prefix_set & PREFIX_CONSTRAINED)
  4956. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid instruction after constrained prefix at 0x%04x", ctx.ip_offset));
  4957. if (ctx.prefix_set & PREFIX_READONLY)
  4958. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid instruction after readonly prefix at 0x%04x", ctx.ip_offset));
  4959. if (ctx.prefix_set & PREFIX_VOLATILE)
  4960. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid instruction after volatile prefix at 0x%04x", ctx.ip_offset));
  4961. if (ctx.prefix_set & PREFIX_UNALIGNED)
  4962. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Invalid instruction after unaligned prefix at 0x%04x", ctx.ip_offset));
  4963. ctx.prefix_set = prefix = 0;
  4964. ctx.has_flags = FALSE;
  4965. }
  4966. }
  4967. /*
  4968. * if ip != end we overflowed: mark as error.
  4969. */
  4970. if ((ip != end || !start) && ctx.verifiable && !ctx.list) {
  4971. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Run ahead of method code at 0x%04x", ip_offset));
  4972. }
  4973. /*We should guard against the last decoded opcode, otherwise we might add errors that doesn't make sense.*/
  4974. for (i = 0; i < ctx.code_size && i < ip_offset; ++i) {
  4975. if (ctx.code [i].flags & IL_CODE_FLAG_WAS_TARGET) {
  4976. if (!(ctx.code [i].flags & IL_CODE_FLAG_SEEN))
  4977. ADD_VERIFY_ERROR (&ctx, g_strdup_printf ("Branch or exception block target middle of intruction at 0x%04x", i));
  4978. if (ctx.code [i].flags & IL_CODE_DELEGATE_SEQUENCE)
  4979. CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("Branch to delegate code sequence at 0x%04x", i));
  4980. }
  4981. if ((ctx.code [i].flags & IL_CODE_LDFTN_DELEGATE_NONFINAL_VIRTUAL) && ctx.has_this_store)
  4982. CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("Invalid ldftn with virtual function in method with stdarg 0 at 0x%04x", i));
  4983. if ((ctx.code [i].flags & IL_CODE_CALL_NONFINAL_VIRTUAL) && ctx.has_this_store)
  4984. CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("Invalid call to a non-final virtual function in method with stdarg.0 or ldarga.0 at 0x%04x", i));
  4985. }
  4986. if (mono_method_is_constructor (ctx.method) && !ctx.super_ctor_called && !ctx.method->klass->valuetype && ctx.method->klass != mono_defaults.object_class) {
  4987. char *method_name = mono_method_full_name (ctx.method, TRUE);
  4988. char *type = mono_type_get_full_name (ctx.method->klass);
  4989. if (ctx.method->klass->parent && ctx.method->klass->parent->exception_type != MONO_EXCEPTION_NONE)
  4990. CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("Constructor %s for type %s not calling base type ctor due to a TypeLoadException on base type.", method_name, type));
  4991. else
  4992. CODE_NOT_VERIFIABLE (&ctx, g_strdup_printf ("Constructor %s for type %s not calling base type ctor.", method_name, type));
  4993. g_free (method_name);
  4994. g_free (type);
  4995. }
  4996. cleanup:
  4997. if (ctx.code) {
  4998. for (i = 0; i < ctx.header->code_size; ++i) {
  4999. if (ctx.code [i].stack)
  5000. g_free (ctx.code [i].stack);
  5001. }
  5002. }
  5003. for (tmp = ctx.funptrs; tmp; tmp = tmp->next)
  5004. g_free (tmp->data);
  5005. g_slist_free (ctx.funptrs);
  5006. for (tmp = ctx.exception_types; tmp; tmp = tmp->next)
  5007. mono_metadata_free_type (tmp->data);
  5008. g_slist_free (ctx.exception_types);
  5009. for (i = 0; i < ctx.num_locals; ++i) {
  5010. if (ctx.locals [i])
  5011. mono_metadata_free_type (ctx.locals [i]);
  5012. }
  5013. for (i = 0; i < ctx.max_args; ++i) {
  5014. if (ctx.params [i])
  5015. mono_metadata_free_type (ctx.params [i]);
  5016. }
  5017. if (ctx.eval.stack)
  5018. g_free (ctx.eval.stack);
  5019. if (ctx.code)
  5020. g_free (ctx.code);
  5021. g_free (ctx.locals);
  5022. g_free (ctx.params);
  5023. mono_basic_block_free (original_bb);
  5024. mono_metadata_free_mh (ctx.header);
  5025. finish_collect_stats ();
  5026. return ctx.list;
  5027. }
  5028. char*
  5029. mono_verify_corlib ()
  5030. {
  5031. /* This is a public API function so cannot be removed */
  5032. return NULL;
  5033. }
  5034. /*
  5035. * Returns true if @method needs to be verified.
  5036. *
  5037. */
  5038. gboolean
  5039. mono_verifier_is_enabled_for_method (MonoMethod *method)
  5040. {
  5041. return mono_verifier_is_enabled_for_class (method->klass) && (method->wrapper_type == MONO_WRAPPER_NONE || method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD);
  5042. }
  5043. /*
  5044. * Returns true if @klass need to be verified.
  5045. *
  5046. */
  5047. gboolean
  5048. mono_verifier_is_enabled_for_class (MonoClass *klass)
  5049. {
  5050. return verify_all || (verifier_mode > MONO_VERIFIER_MODE_OFF && !(klass->image->assembly && klass->image->assembly->in_gac) && klass->image != mono_defaults.corlib);
  5051. }
  5052. gboolean
  5053. mono_verifier_is_enabled_for_image (MonoImage *image)
  5054. {
  5055. return verify_all || verifier_mode > MONO_VERIFIER_MODE_OFF;
  5056. }
  5057. /*
  5058. * Dynamic methods are not considered full trust since if the user is trusted and need to
  5059. * generate unsafe code, make the method skip verification - this is a known good way to do it.
  5060. */
  5061. gboolean
  5062. mono_verifier_is_method_full_trust (MonoMethod *method)
  5063. {
  5064. return mono_verifier_is_class_full_trust (method->klass) && !method->dynamic;
  5065. }
  5066. /*
  5067. * Returns if @klass is under full trust or not.
  5068. *
  5069. * TODO This code doesn't take CAS into account.
  5070. *
  5071. * Under verify_all all user code must be verifiable if no security option was set
  5072. *
  5073. */
  5074. gboolean
  5075. mono_verifier_is_class_full_trust (MonoClass *klass)
  5076. {
  5077. /* under CoreCLR code is trusted if it is part of the "platform" otherwise all code inside the GAC is trusted */
  5078. gboolean trusted_location = (mono_security_get_mode () != MONO_SECURITY_MODE_CORE_CLR) ?
  5079. (klass->image->assembly && klass->image->assembly->in_gac) : mono_security_core_clr_is_platform_image (klass->image);
  5080. if (verify_all && verifier_mode == MONO_VERIFIER_MODE_OFF)
  5081. return trusted_location || klass->image == mono_defaults.corlib;
  5082. return verifier_mode < MONO_VERIFIER_MODE_VERIFIABLE || trusted_location || klass->image == mono_defaults.corlib;
  5083. }
  5084. GSList*
  5085. mono_method_verify_with_current_settings (MonoMethod *method, gboolean skip_visibility, gboolean is_fulltrust)
  5086. {
  5087. return mono_method_verify (method,
  5088. (verifier_mode != MONO_VERIFIER_MODE_STRICT ? MONO_VERIFY_NON_STRICT: 0)
  5089. | (!is_fulltrust && !mono_verifier_is_method_full_trust (method) ? MONO_VERIFY_FAIL_FAST : 0)
  5090. | (skip_visibility ? MONO_VERIFY_SKIP_VISIBILITY : 0));
  5091. }
  5092. static int
  5093. get_field_end (MonoClassField *field)
  5094. {
  5095. int align;
  5096. int size = mono_type_size (field->type, &align);
  5097. if (size == 0)
  5098. size = 4; /*FIXME Is this a safe bet?*/
  5099. return size + field->offset;
  5100. }
  5101. static gboolean
  5102. verify_class_for_overlapping_reference_fields (MonoClass *class)
  5103. {
  5104. int i = 0, j;
  5105. gpointer iter = NULL;
  5106. MonoClassField *field;
  5107. gboolean is_fulltrust = mono_verifier_is_class_full_trust (class);
  5108. /*We can't skip types with !has_references since this is calculated after we have run.*/
  5109. if (!((class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT))
  5110. return TRUE;
  5111. /*We must check for stuff overlapping reference fields.
  5112. The outer loop uses mono_class_get_fields to ensure that MonoClass:fields get inited.
  5113. */
  5114. while ((field = mono_class_get_fields (class, &iter))) {
  5115. int fieldEnd = get_field_end (field);
  5116. gboolean is_valuetype = !MONO_TYPE_IS_REFERENCE (field->type);
  5117. ++i;
  5118. if (mono_field_is_deleted (field) || (field->type->attrs & FIELD_ATTRIBUTE_STATIC))
  5119. continue;
  5120. for (j = i; j < class->field.count; ++j) {
  5121. MonoClassField *other = &class->fields [j];
  5122. int otherEnd = get_field_end (other);
  5123. if (mono_field_is_deleted (other) || (is_valuetype && !MONO_TYPE_IS_REFERENCE (other->type)) || (other->type->attrs & FIELD_ATTRIBUTE_STATIC))
  5124. continue;
  5125. if (!is_valuetype && MONO_TYPE_IS_REFERENCE (other->type) && field->offset == other->offset && is_fulltrust)
  5126. continue;
  5127. if ((otherEnd > field->offset && otherEnd <= fieldEnd) || (other->offset >= field->offset && other->offset < fieldEnd))
  5128. return FALSE;
  5129. }
  5130. }
  5131. return TRUE;
  5132. }
  5133. static guint
  5134. field_hash (gconstpointer key)
  5135. {
  5136. const MonoClassField *field = key;
  5137. return g_str_hash (field->name) ^ mono_metadata_type_hash (field->type); /**/
  5138. }
  5139. static gboolean
  5140. field_equals (gconstpointer _a, gconstpointer _b)
  5141. {
  5142. const MonoClassField *a = _a;
  5143. const MonoClassField *b = _b;
  5144. return !strcmp (a->name, b->name) && mono_metadata_type_equal (a->type, b->type);
  5145. }
  5146. static gboolean
  5147. verify_class_fields (MonoClass *class)
  5148. {
  5149. gpointer iter = NULL;
  5150. MonoClassField *field;
  5151. MonoGenericContext *context = mono_class_get_context (class);
  5152. GHashTable *unique_fields = g_hash_table_new_full (&field_hash, &field_equals, NULL, NULL);
  5153. if (class->generic_container)
  5154. context = &class->generic_container->context;
  5155. while ((field = mono_class_get_fields (class, &iter)) != NULL) {
  5156. if (!mono_type_is_valid_type_in_context (field->type, context)) {
  5157. g_hash_table_destroy (unique_fields);
  5158. return FALSE;
  5159. }
  5160. if (g_hash_table_lookup (unique_fields, field)) {
  5161. g_hash_table_destroy (unique_fields);
  5162. return FALSE;
  5163. }
  5164. g_hash_table_insert (unique_fields, field, field);
  5165. }
  5166. g_hash_table_destroy (unique_fields);
  5167. return TRUE;
  5168. }
  5169. static gboolean
  5170. verify_interfaces (MonoClass *class)
  5171. {
  5172. int i;
  5173. for (i = 0; i < class->interface_count; ++i) {
  5174. MonoClass *iface = class->interfaces [i];
  5175. if (!(iface->flags & TYPE_ATTRIBUTE_INTERFACE))
  5176. return FALSE;
  5177. }
  5178. return TRUE;
  5179. }
  5180. static gboolean
  5181. verify_valuetype_layout_with_target (MonoClass *class, MonoClass *target_class)
  5182. {
  5183. int type;
  5184. gpointer iter = NULL;
  5185. MonoClassField *field;
  5186. MonoClass *field_class;
  5187. if (!class->valuetype)
  5188. return TRUE;
  5189. type = class->byval_arg.type;
  5190. /*primitive type fields are not properly decoded*/
  5191. if ((type >= MONO_TYPE_BOOLEAN && type <= MONO_TYPE_R8) || (type >= MONO_TYPE_I && type <= MONO_TYPE_U))
  5192. return TRUE;
  5193. while ((field = mono_class_get_fields (class, &iter)) != NULL) {
  5194. if (!field->type)
  5195. return FALSE;
  5196. if (field->type->attrs & (FIELD_ATTRIBUTE_STATIC | FIELD_ATTRIBUTE_HAS_FIELD_RVA))
  5197. continue;
  5198. field_class = mono_class_get_generic_type_definition (mono_class_from_mono_type (field->type));
  5199. if (field_class == target_class || class == field_class || !verify_valuetype_layout_with_target (field_class, target_class))
  5200. return FALSE;
  5201. }
  5202. return TRUE;
  5203. }
  5204. static gboolean
  5205. verify_valuetype_layout (MonoClass *class)
  5206. {
  5207. gboolean res;
  5208. res = verify_valuetype_layout_with_target (class, class);
  5209. return res;
  5210. }
  5211. static gboolean
  5212. recursive_mark_constraint_args (MonoBitSet *used_args, MonoGenericContainer *gc, MonoType *type)
  5213. {
  5214. int idx;
  5215. MonoClass **constraints;
  5216. MonoGenericParamInfo *param_info;
  5217. g_assert (mono_type_is_generic_argument (type));
  5218. idx = mono_type_get_generic_param_num (type);
  5219. if (mono_bitset_test_fast (used_args, idx))
  5220. return FALSE;
  5221. mono_bitset_set_fast (used_args, idx);
  5222. param_info = mono_generic_container_get_param_info (gc, idx);
  5223. if (!param_info->constraints)
  5224. return TRUE;
  5225. for (constraints = param_info->constraints; *constraints; ++constraints) {
  5226. MonoClass *ctr = *constraints;
  5227. MonoType *constraint_type = &ctr->byval_arg;
  5228. if (mono_type_is_generic_argument (constraint_type) && !recursive_mark_constraint_args (used_args, gc, constraint_type))
  5229. return FALSE;
  5230. }
  5231. return TRUE;
  5232. }
  5233. static gboolean
  5234. verify_generic_parameters (MonoClass *class)
  5235. {
  5236. int i;
  5237. MonoGenericContainer *gc = class->generic_container;
  5238. MonoBitSet *used_args = mono_bitset_new (gc->type_argc, 0);
  5239. for (i = 0; i < gc->type_argc; ++i) {
  5240. MonoGenericParamInfo *param_info = mono_generic_container_get_param_info (gc, i);
  5241. MonoClass **constraints;
  5242. if (!param_info->constraints)
  5243. continue;
  5244. mono_bitset_clear_all (used_args);
  5245. mono_bitset_set_fast (used_args, i);
  5246. for (constraints = param_info->constraints; *constraints; ++constraints) {
  5247. MonoClass *ctr = *constraints;
  5248. MonoType *constraint_type = &ctr->byval_arg;
  5249. if (!mono_type_is_valid_type_in_context (constraint_type, &gc->context))
  5250. goto fail;
  5251. if (mono_type_is_generic_argument (constraint_type) && !recursive_mark_constraint_args (used_args, gc, constraint_type))
  5252. goto fail;
  5253. if (ctr->generic_class && !mono_class_is_valid_generic_instantiation (NULL, ctr))
  5254. goto fail;
  5255. }
  5256. }
  5257. mono_bitset_free (used_args);
  5258. return TRUE;
  5259. fail:
  5260. mono_bitset_free (used_args);
  5261. return FALSE;
  5262. }
  5263. /*
  5264. * Check if the class is verifiable.
  5265. *
  5266. * Right now there are no conditions that make a class a valid but not verifiable. Both overlapping reference
  5267. * field and invalid generic instantiation are fatal errors.
  5268. *
  5269. * This method must be safe to be called from mono_class_init and all code must be carefull about that.
  5270. *
  5271. */
  5272. gboolean
  5273. mono_verifier_verify_class (MonoClass *class)
  5274. {
  5275. /*Neither <Module>, object or ifaces have parent.*/
  5276. if (!class->parent &&
  5277. class != mono_defaults.object_class &&
  5278. !MONO_CLASS_IS_INTERFACE (class) &&
  5279. (!class->image->dynamic && class->type_token != 0x2000001)) /*<Module> is the first type in the assembly*/
  5280. return FALSE;
  5281. if (class->parent) {
  5282. if (MONO_CLASS_IS_INTERFACE (class->parent))
  5283. return FALSE;
  5284. if (!class->generic_class && class->parent->generic_container)
  5285. return FALSE;
  5286. if (class->parent->generic_class && !class->generic_class) {
  5287. MonoGenericContext *context = mono_class_get_context (class);
  5288. if (class->generic_container)
  5289. context = &class->generic_container->context;
  5290. if (!mono_type_is_valid_type_in_context (&class->parent->byval_arg, context))
  5291. return FALSE;
  5292. }
  5293. }
  5294. if (class->generic_container && (class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT)
  5295. return FALSE;
  5296. if (class->generic_container && !verify_generic_parameters (class))
  5297. return FALSE;
  5298. if (!verify_class_for_overlapping_reference_fields (class))
  5299. return FALSE;
  5300. if (class->generic_class && !mono_class_is_valid_generic_instantiation (NULL, class))
  5301. return FALSE;
  5302. if (class->generic_class == NULL && !verify_class_fields (class))
  5303. return FALSE;
  5304. if (class->valuetype && !verify_valuetype_layout (class))
  5305. return FALSE;
  5306. if (!verify_interfaces (class))
  5307. return FALSE;
  5308. return TRUE;
  5309. }
  5310. gboolean
  5311. mono_verifier_class_is_valid_generic_instantiation (MonoClass *class)
  5312. {
  5313. return mono_class_is_valid_generic_instantiation (NULL, class);
  5314. }
  5315. gboolean
  5316. mono_verifier_is_method_valid_generic_instantiation (MonoMethod *method)
  5317. {
  5318. if (!method->is_inflated)
  5319. return TRUE;
  5320. return mono_method_is_valid_generic_instantiation (NULL, method);
  5321. }
  5322. #else
  5323. gboolean
  5324. mono_verifier_verify_class (MonoClass *class)
  5325. {
  5326. /* The verifier was disabled at compile time */
  5327. return TRUE;
  5328. }
  5329. GSList*
  5330. mono_method_verify_with_current_settings (MonoMethod *method, gboolean skip_visibility, gboolean is_fulltrust)
  5331. {
  5332. /* The verifier was disabled at compile time */
  5333. return NULL;
  5334. }
  5335. gboolean
  5336. mono_verifier_is_class_full_trust (MonoClass *klass)
  5337. {
  5338. /* The verifier was disabled at compile time */
  5339. return TRUE;
  5340. }
  5341. gboolean
  5342. mono_verifier_is_method_full_trust (MonoMethod *method)
  5343. {
  5344. /* The verifier was disabled at compile time */
  5345. return TRUE;
  5346. }
  5347. gboolean
  5348. mono_verifier_is_enabled_for_image (MonoImage *image)
  5349. {
  5350. /* The verifier was disabled at compile time */
  5351. return FALSE;
  5352. }
  5353. gboolean
  5354. mono_verifier_is_enabled_for_class (MonoClass *klass)
  5355. {
  5356. /* The verifier was disabled at compile time */
  5357. return FALSE;
  5358. }
  5359. gboolean
  5360. mono_verifier_is_enabled_for_method (MonoMethod *method)
  5361. {
  5362. /* The verifier was disabled at compile time */
  5363. return FALSE;
  5364. }
  5365. GSList*
  5366. mono_method_verify (MonoMethod *method, int level)
  5367. {
  5368. /* The verifier was disabled at compile time */
  5369. return NULL;
  5370. }
  5371. void
  5372. mono_free_verify_list (GSList *list)
  5373. {
  5374. /* The verifier was disabled at compile time */
  5375. /* will always be null if verifier is disabled */
  5376. }
  5377. gboolean
  5378. mono_verifier_class_is_valid_generic_instantiation (MonoClass *class)
  5379. {
  5380. return TRUE;
  5381. }
  5382. gboolean
  5383. mono_verifier_is_method_valid_generic_instantiation (MonoMethod *method)
  5384. {
  5385. return TRUE;
  5386. }
  5387. #endif