TODO verify in the CLI header entry point and resources
TODO implement null token typeref validation
TODO verify table wide invariants for typedef (sorting and uniqueness)
+ TODO implement proper authenticode data directory validation
+ TODO verify properties that require multiple tables to be valid
FIXME use subtraction based bounds checking to avoid overflows
FIXME get rid of metadata_streams and other fields from VerifyContext
*/
#endif
#define INVALID_OFFSET ((guint32)-1)
+#define INVALID_ADDRESS 0xffffffff
enum {
STAGE_PE,
enum {
IMPORT_TABLE_IDX = 1,
RESOURCE_TABLE_IDX = 2,
+ CERTIFICATE_TABLE_IDX = 4,
RELOCATION_TABLE_IDX = 5,
IAT_IDX = 12,
CLI_HEADER_IDX = 14,
guint32 rva = read32 (ptr);
guint32 size = read32 (ptr + 4);
+ /*LAMESPEC the authenticode data directory format is different. We don't support CAS, so lets ignore for now.*/
+ if (i == CERTIFICATE_TABLE_IDX) {
+ ptr += 8;
+ continue;
+ }
if ((rva != 0 || size != 0) && !is_valid_data_directory (i))
ADD_ERROR (ctx, g_strdup_printf ("Invalid data directory %d", i));
}
static gboolean
-is_valid_non_empty_string (VerifyContext *ctx, guint32 offset)
+is_valid_string_full (VerifyContext *ctx, guint32 offset, gboolean allow_empty)
{
OffsetAndSize strings = get_metadata_stream (ctx, &ctx->image->heap_strings);
glong length;
if (!mono_utf8_validate_and_len_with_bounds (data + offset, strings.size - offset, &length, NULL))
return FALSE;
- return length > 0;
+ return allow_empty || length > 0;
+}
+
+static gboolean
+is_valid_string (VerifyContext *ctx, guint32 offset)
+{
+ return is_valid_string_full (ctx, offset, TRUE);
+}
+
+static gboolean
+is_valid_non_empty_string (VerifyContext *ctx, guint32 offset)
+{
+ return is_valid_string_full (ctx, offset, FALSE);
}
static gboolean
}
static guint32
-get_coded_index_token (VerifyContext *ctx, int token_kind, guint32 coded_token)
+get_coded_index_token (int token_kind, guint32 coded_token)
{
guint32 bits = coded_index_desc [token_kind];
return coded_token >> bits;
return (res - base) / tinfo->rows;
}
+/*WARNING: This function doesn't verify if the strings @offset points to a valid string*/
+static const char*
+get_string_ptr (VerifyContext *ctx, guint offset)
+{
+ return ctx->image->heap_strings.data + offset;
+}
+
/*WARNING: This function doesn't verify if the strings @offset points to a valid string*/
static int
string_cmp (VerifyContext *ctx, const char *str, guint offset)
if (offset == 0)
return strcmp (str, "");
- return strcmp (str, ctx->image->heap_strings.data + offset);
+ return strcmp (str, get_string_ptr (ctx, offset));
}
static gboolean
return ctx->is_corlib && !string_cmp (ctx, "System", data [MONO_TYPEDEF_NAME]) && !string_cmp (ctx, "Object", data [MONO_TYPEDEF_NAMESPACE]);
}
+static gboolean
+is_valid_field_signature (VerifyContext *ctx, guint32 offset)
+{
+ OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
+ //TODO do proper verification
+ return blob.size >= 2 && blob.size - 2 >= offset;
+}
+
+static gboolean
+is_valid_method_signature (VerifyContext *ctx, guint32 offset)
+{
+ OffsetAndSize blob = get_metadata_stream (ctx, &ctx->image->heap_blob);
+ //TODO do proper verification
+ return blob.size >= 2 && blob.size - 2 >= offset;
+}
+
+static gboolean
+is_valid_method_header (VerifyContext *ctx, guint32 rva)
+{
+ //TODO do proper method header validation
+ return mono_cli_rva_image_map (ctx->image, rva) != INVALID_ADDRESS;
+}
+
static void
verify_module_table (VerifyContext *ctx)
{
if (!is_valid_coded_index (ctx, RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE]))
ADD_ERROR (ctx, g_strdup_printf ("Invalid typeref row %d coded index 0x%08x", i, data [MONO_TYPEREF_SCOPE]));
- if (!get_coded_index_token (ctx, RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE]))
+ if (!get_coded_index_token (RES_SCOPE_DESC, data [MONO_TYPEREF_SCOPE]))
ADD_ERROR (ctx, g_strdup_printf ("The metadata verifier doesn't support null ResolutionScope tokens for typeref row %d", i));
if (!data [MONO_TYPEREF_NAME] || !is_valid_non_empty_string (ctx, data [MONO_TYPEREF_NAME]))
if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]))
ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d extend field coded index 0x%08x", i, data [MONO_TYPEDEF_EXTENDS]));
- if (!get_coded_index_token (ctx, TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]))
+ if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_TYPEDEF_EXTENDS]))
ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d for non-interface type must have a non-null extend field", i));
}
}
if (data [MONO_TYPEDEF_FIELD_LIST] == 0)
ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList be be >= 1", i));
+ if (data [MONO_TYPEDEF_FIELD_LIST] > ctx->image->tables [MONO_TABLE_FIELD].rows + 1)
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList rowid 0x%08x is out of range", i, data [MONO_TYPEDEF_FIELD_LIST]));
+
if (data [MONO_TYPEDEF_FIELD_LIST] < fieldlist)
ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d FieldList rowid 0x%08x can't be smaller than of previous row 0x%08x", i, data [MONO_TYPEDEF_FIELD_LIST], fieldlist));
if (data [MONO_TYPEDEF_METHOD_LIST] == 0)
ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList be be >= 1", i));
+ if (data [MONO_TYPEDEF_METHOD_LIST] > ctx->image->tables [MONO_TABLE_METHOD].rows + 1)
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList rowid 0x%08x is out of range", i, data [MONO_TYPEDEF_METHOD_LIST]));
+
if (data [MONO_TYPEDEF_METHOD_LIST] < methodlist)
ADD_ERROR (ctx, g_strdup_printf ("Invalid typedef row %d MethodList rowid 0x%08x can't be smaller than of previous row 0x%08x", i, data [MONO_TYPEDEF_METHOD_LIST], methodlist));
+
fieldlist = data [MONO_TYPEDEF_FIELD_LIST];
methodlist = data [MONO_TYPEDEF_METHOD_LIST];
}
verify_field_table (VerifyContext *ctx)
{
MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_FIELD];
- guint32 data [MONO_FIELD_SIZE], flags;
+ guint32 data [MONO_FIELD_SIZE], flags, module_field_list;
int i;
+ module_field_list = (guint32)-1;
+ if (ctx->image->tables [MONO_TABLE_TYPEDEF].rows > 1) {
+ MonoTableInfo *type = &ctx->image->tables [MONO_TABLE_TYPEDEF];
+ module_field_list = mono_metadata_decode_row_col (type, 1, MONO_TYPEDEF_FIELD_LIST);
+ }
+
for (i = 0; i < table->rows; ++i) {
mono_metadata_decode_row (table, i, data, MONO_FIELD_SIZE);
flags = data [MONO_FIELD_FLAGS];
search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_FIELD, i)) == -1)
ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i));
+ if ((flags & FIELD_ATTRIBUTE_LITERAL) &&
+ search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_FIELD, i)) == -1)
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is Literal but there is no corresponding row in the Constant table", i));
+
if ((flags & FIELD_ATTRIBUTE_HAS_FIELD_RVA) &&
search_sorted_table (ctx, MONO_TABLE_FIELDRVA, MONO_FIELD_RVA_FIELD, i + 1) == -1)
ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d has Default but there is no corresponding row in the Constant table", i));
if (!data [MONO_FIELD_NAME] || !is_valid_non_empty_string (ctx, data [MONO_FIELD_NAME]))
ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid name token %08x", i, data [MONO_FIELD_NAME]));
+ //TODO verify contant flag
+ if (!data [MONO_FIELD_SIGNATURE] || !is_valid_field_signature (ctx, data [MONO_FIELD_SIGNATURE]))
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d invalid signature token %08x", i, data [MONO_FIELD_SIGNATURE]));
+
+ if (i + 1 < module_field_list) {
+ guint32 access = flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK;
+ if (!(flags & FIELD_ATTRIBUTE_STATIC))
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is a global variable but is not static", i));
+ if (access != FIELD_ATTRIBUTE_COMPILER_CONTROLLED && access != FIELD_ATTRIBUTE_PRIVATE && access != FIELD_ATTRIBUTE_PUBLIC)
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid field row %d is a global variable but have wrong visibility %x", i, access));
+ }
+ }
+}
+
+/*bits 6,8,9,10,11,13,14,15*/
+#define INVALID_METHOD_IMPLFLAG_BITS ((1 << 6) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 13) | (1 << 14) | (1 << 15))
+static void
+verify_method_table (VerifyContext *ctx)
+{
+ MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
+ guint32 data [MONO_METHOD_SIZE], flags, implflags, rva, module_method_list, access, code_type;
+ guint32 paramlist = 1;
+ gboolean is_ctor, is_cctor;
+ const char *name;
+ int i;
+
+ module_method_list = (guint32)-1;
+ if (ctx->image->tables [MONO_TABLE_TYPEDEF].rows > 1) {
+ MonoTableInfo *type = &ctx->image->tables [MONO_TABLE_TYPEDEF];
+ module_method_list = mono_metadata_decode_row_col (type, 1, MONO_TYPEDEF_METHOD_LIST);
+ }
+
+ for (i = 0; i < table->rows; ++i) {
+ mono_metadata_decode_row (table, i, data, MONO_METHOD_SIZE);
+ rva = data [MONO_METHOD_RVA];
+ implflags = data [MONO_METHOD_IMPLFLAGS];
+ flags = data [MONO_METHOD_FLAGS];
+ access = flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK;
+ code_type = implflags & METHOD_IMPL_ATTRIBUTE_CODE_TYPE_MASK;
+
+
+ if (implflags & INVALID_METHOD_IMPLFLAG_BITS)
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid implflags field 0x%08x", i, implflags));
+
+ if (access == 0x7)
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid MemberAccessMask 0x7", i));
+
+ if (!data [MONO_METHOD_NAME] || !is_valid_non_empty_string (ctx, data [MONO_METHOD_NAME]))
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid name field 0x%08x", i, data [MONO_METHOD_NAME]));
+
+ name = get_string_ptr (ctx, data [MONO_METHOD_NAME]);
+ is_ctor = !strcmp (".ctor", name);
+ is_cctor = !strcmp (".cctor", name);
+
+ if ((is_ctor || is_cctor) &&
+ search_sorted_table (ctx, MONO_TABLE_GENERICPARAM, MONO_GENERICPARAM_OWNER, make_coded_token (TYPE_OR_METHODDEF_DESC, MONO_TABLE_METHOD, i)) != -1)
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d .ctor or .cctor has generic param", i));
+
+ if ((flags & METHOD_ATTRIBUTE_STATIC) && (flags & (METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_VIRTUAL | METHOD_ATTRIBUTE_NEW_SLOT)))
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is static and (final, virtual or new slot)", i));
+
+ if (flags & METHOD_ATTRIBUTE_ABSTRACT) {
+ if (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract and PinvokeImpl", i));
+ if (!(flags & METHOD_ATTRIBUTE_VIRTUAL))
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is Abstract but not Virtual", i));
+ }
+
+ if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && (flags & (METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME)))
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is CompileControlled and SpecialName or RtSpecialName", i));
+
+ if ((flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME) && !(flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RTSpecialName but not SpecialName", i));
+
+ //XXX no checks against cas stuff 10,11,12,13)
+
+ //TODO check iface with .ctor (15,16)
+
+ if (!data [MONO_METHOD_SIGNATURE] || !is_valid_method_signature (ctx, data [MONO_METHOD_SIGNATURE]))
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d invalid signature token %08x", i, data [MONO_METHOD_SIGNATURE]));
+
+ if (i + 1 < module_method_list) {
+ if (!(flags & METHOD_ATTRIBUTE_STATIC))
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but not Static", i));
+ if (flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_VIRTUAL))
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but is Abstract or Virtual", i));
+ if (!(access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED || access == METHOD_ATTRIBUTE_PUBLIC || access == METHOD_ATTRIBUTE_PRIVATE))
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is a global method but not CompilerControled, Public or Private", i));
+ }
+
+ //TODO check valuetype for synchronized
+
+ if ((flags & (METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_NEW_SLOT | METHOD_ATTRIBUTE_STRICT)) && !(flags & METHOD_ATTRIBUTE_VIRTUAL))
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is (Final, NewSlot or Strict) but not Virtual", i));
+
+ if ((flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) && (flags & METHOD_ATTRIBUTE_VIRTUAL))
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl and Virtual", i));
+
+ if (!(flags & METHOD_ATTRIBUTE_ABSTRACT) && !rva && !(flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) &&
+ !(implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && code_type != METHOD_IMPL_ATTRIBUTE_RUNTIME)
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is not Abstract and neither PinvokeImpl, Runtime, InternalCall or with RVA != 0", i));
+
+ if (access == METHOD_ATTRIBUTE_COMPILER_CONTROLLED && !(rva || (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)))
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is CompilerControlled but neither RVA != 0 or PinvokeImpl", i));
+
+ //TODO check signature contents
+
+ if (rva) {
+ if (flags & METHOD_ATTRIBUTE_ABSTRACT)
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA != 0 but is Abstract", i));
+ if (code_type == METHOD_IMPL_ATTRIBUTE_OPTIL)
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA != 0 but is CodeTypeMask is neither Native, CIL or Runtime", i));
+ if (!is_valid_method_header (ctx, rva))
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d RVA points to an invalid method header", i));
+ } else {
+ if (!(flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_PINVOKE_IMPL)) && !(implflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && code_type != METHOD_IMPL_ATTRIBUTE_RUNTIME)
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d has RVA = 0 but neither Abstract, InternalCall, Runtime or PinvokeImpl", i));
+ }
+
+ if ((flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
+ if (rva)
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has RVA != 0", i));
+ if (search_sorted_table (ctx, MONO_TABLE_IMPLMAP, MONO_IMPLMAP_MEMBER, make_coded_token (MEMBER_FORWARDED_DESC, MONO_TABLE_METHOD, i)) == -1)
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is PinvokeImpl but has no row in the ImplMap table", i));
+ }
+ if (flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME && !is_ctor && !is_cctor)
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is RtSpecialName but not named .ctor or .cctor", i));
+
+ if ((is_ctor || is_cctor) && !(flags & METHOD_ATTRIBUTE_RT_SPECIAL_NAME))
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d is named .ctor or .cctor but is not RtSpecialName", i));
+
+ if (data [MONO_METHOD_PARAMLIST] == 0)
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList be be >= 1", i));
+
+ if (data [MONO_METHOD_PARAMLIST] < paramlist)
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList rowid 0x%08x can't be smaller than of previous row 0x%08x", i, data [MONO_METHOD_PARAMLIST], paramlist));
+
+ if (data [MONO_METHOD_PARAMLIST] > ctx->image->tables [MONO_TABLE_PARAM].rows + 1)
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid method row %d ParamList rowid 0x%08x is out of range", i, data [MONO_METHOD_PARAMLIST]));
+
+ paramlist = data [MONO_METHOD_PARAMLIST];
+
+ }
+}
+
+static guint32
+get_next_param_count (VerifyContext *ctx, guint32 *current_method)
+{
+ MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_METHOD];
+ guint32 row = *current_method;
+ guint32 paramlist, tmp;
+
+
+ paramlist = mono_metadata_decode_row_col (table, row++, MONO_METHOD_PARAMLIST);
+ while (row < table->rows) {
+ tmp = mono_metadata_decode_row_col (table, row, MONO_METHOD_PARAMLIST);
+ if (tmp > paramlist) {
+ *current_method = row;
+ return tmp - paramlist;
+ }
+ ++row;
+ }
+
+ /*no more methods, all params apply to the last one*/
+ *current_method = table->rows;
+ return (guint32)-1;
+}
+
+
+#define INVALID_PARAM_FLAGS_BITS ((1 << 2) | (1 << 3) | (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8) | (1 << 9) | (1 << 10) | (1 << 11) | (1 << 14) | (1 << 15))
+static void
+verify_param_table (VerifyContext *ctx)
+{
+ MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_PARAM];
+ guint32 data [MONO_PARAM_SIZE], flags, sequence = 0, remaining_params, current_method = 0;
+ gboolean first_param = TRUE;
+ int i;
+
+ remaining_params = get_next_param_count (ctx, ¤t_method);
+
+ for (i = 0; i < table->rows; ++i) {
+ mono_metadata_decode_row (table, i, data, MONO_PARAM_SIZE);
+ flags = data [MONO_PARAM_FLAGS];
+
+ if (flags & INVALID_PARAM_FLAGS_BITS)
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d bad Flags value 0x%08x", i, flags));
+
+ if (search_sorted_table (ctx, MONO_TABLE_CONSTANT, MONO_CONSTANT_PARENT, make_coded_token (HAS_CONSTANT_DESC, MONO_TABLE_PARAM, i)) == -1) {
+ if (flags & PARAM_ATTRIBUTE_HAS_DEFAULT)
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasDefault = 1 but no owned row in Contant table", i));
+ } else {
+ if (!(flags & PARAM_ATTRIBUTE_HAS_DEFAULT))
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasDefault = 0 but has owned row in Contant table", i));
+ }
+
+ if ((flags & PARAM_ATTRIBUTE_HAS_FIELD_MARSHAL) && search_sorted_table (ctx, MONO_TABLE_FIELDMARSHAL, MONO_FIELD_MARSHAL_PARENT, make_coded_token (HAS_FIELD_MARSHAL_DESC, MONO_TABLE_PARAM, i)) == -1)
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d HasFieldMarshal = 1 but no owned row in FieldMarshal table", i));
+
+ if (!is_valid_string (ctx, data [MONO_PARAM_NAME]))
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d Name = 1 bad token 0x%08x", i, data [MONO_PARAM_NAME]));
+
+ if (!first_param && data [MONO_PARAM_SEQUENCE] <= sequence)
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid param row %d sequece = %d previus param has %d", i, data [MONO_PARAM_SEQUENCE], sequence));
+
+ first_param = FALSE;
+ sequence = data [MONO_PARAM_SEQUENCE];
+ if (--remaining_params == 0) {
+ remaining_params = get_next_param_count (ctx, ¤t_method);
+ first_param = TRUE;
+ }
+ }
+}
+
+static void
+verify_interfaceimpl_table (VerifyContext *ctx)
+{
+ MonoTableInfo *table = &ctx->image->tables [MONO_TABLE_INTERFACEIMPL];
+ guint32 data [MONO_INTERFACEIMPL_SIZE];
+ int i;
+
+ for (i = 0; i < table->rows; ++i) {
+ mono_metadata_decode_row (table, i, data, MONO_INTERFACEIMPL_SIZE);
+ if (data [MONO_INTERFACEIMPL_CLASS] && data [MONO_INTERFACEIMPL_CLASS] > ctx->image->tables [MONO_TABLE_TYPEDEF].rows)
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Class field 0x%08x", i, data [MONO_TABLE_TYPEDEF]));
+
+ if (!is_valid_coded_index (ctx, TYPEDEF_OR_REF_DESC, data [MONO_INTERFACEIMPL_INTERFACE]))
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field coded index 0x%08x", i, data [MONO_INTERFACEIMPL_INTERFACE]));
+
+ if (!get_coded_index_token (TYPEDEF_OR_REF_DESC, data [MONO_INTERFACEIMPL_INTERFACE]))
+ ADD_ERROR (ctx, g_strdup_printf ("Invalid InterfaceImpl row %d Inteface field is null", i));
}
}
verify_typedef_table (ctx);
CHECK_ERROR ();
verify_field_table (ctx);
+ CHECK_ERROR ();
+ verify_method_table (ctx);
+ CHECK_ERROR ();
+ verify_param_table (ctx);
+ CHECK_ERROR ();
+ verify_interfaceimpl_table (ctx);
}
static gboolean
{
VerifyContext ctx;
- /* a temporary workaround for bug #496453 */
- return TRUE;
-
if (!mono_verifier_is_enabled_for_image (image))
return TRUE;