[Mono-dev] [PATCH] Implement field load/store verification

Paolo Molaro lupus at ximian.com
Thu Jun 21 09:24:24 EDT 2007


On 06/20/07 Rodrigo Kumpera wrote:
> The attached patch does the following:
> 
> -implement all field load/store verifications
> -fixes a small typo in a class.c comment
> -function pointer validation now handles call convention
> -fixed: brtrue/false flaged unmanaged pointers as invalid types (now just
> flags as unverifiable)

> Index: verify.c
> ===================================================================
> --- verify.c	(revision 80327)
> +++ verify.c	(working copy)
> @@ -2359,6 +2362,156 @@
>  	}
>  }
>  
> +static void
> +do_push_static_field (VerifyContext *ctx, int token, gboolean take_addr)
> +{
> +	MonoClassField *field;
> +	MonoClass *klass;
> +
> +	field = mono_field_from_token (ctx->image, token, &klass, ctx->generic_context);
> +	if (!field) {
> +		ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Cannot load field from token 0x%08x at 0x%04x", token, ctx->ip_offset));
> +		return;
> +	}
> +
> +	if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) { 
> +		ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Cannot load non static field at 0x%04x", ctx->ip_offset));
> +		return;
> +	}
> +
> +	if (take_addr && (field->type->attrs & FIELD_ATTRIBUTE_INIT_ONLY))
> +		CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Cannot take the address of a init-only field at 0x%04x", ctx->ip_offset));

This should be allowed in the .cctor for the class (same for the
equivalent case of an instance field and the .ctor): a test case is
something like:

	readonly static MyValueType v = new MyValueType (5);

Note, eventually you also need to add accessibility checks: the method
needs to be able to access the field keeping in mind both the field's
and the field's class visibility.

> +static gboolean
> +check_is_valid_type_for_field_ops (VerifyContext *ctx, int token, ILStackDesc *obj, MonoClassField **ret_field)
> +{
> +	MonoClassField *field;
> +	MonoClass *klass;
> +
> +	/*must be one of: object type, managed pointer, unmanaged pointer (native int) or an instance of a value type */
> +	if (!((obj->stype == TYPE_COMPLEX)
> +		/* the managed reference must be to an object or value type */
> +		|| ((obj->stype & POINTER_MASK) && (UNMASK_TYPE (obj->stype) == TYPE_COMPLEX))
> +		|| (obj->stype == TYPE_NATIVE_INT)
> +		|| (obj->stype == TYPE_PTR)
> +		|| (obj->stype == TYPE_COMPLEX))) {
> +		ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Invalid argument %s to load field at 0x%04x", type_names [UNMASK_TYPE (obj->stype)], ctx->ip_offset));
> +		return FALSE;
> +	}
> +
> +	field = mono_field_from_token (ctx->image, token, &klass, ctx->generic_context);
> +	if (!field) {
> +		ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Cannot load field from token 0x%08x at 0x%04x", token, ctx->ip_offset));
> +		return FALSE;
> +	}
> +
> +	*ret_field = field;
> +
> +	g_assert (obj->type);
> +
> +	/*The value on the stack must be a subclass of the defining type of the field*/ 
> +	/* we need to check if we can load the field from the stack value*/
> +	if (UNMASK_TYPE (obj->stype) == TYPE_COMPLEX) {
> +		MonoType *type = obj->type->byref ? &field->parent->this_arg : &field->parent->byval_arg;
> +
> +		if (!verify_stack_type_compatibility (ctx, type, obj->type, FALSE)) {
> +			ADD_VERIFY_ERROR (ctx, g_strdup_printf ("Type at stack is not compatible to reference the field at 0x%04x", ctx->ip_offset));
> +			return FALSE;
> +		}
> +	}
> +
> +	if (MONO_TYPE_IS_REFERENCE (field->type) && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
> +		MonoClass *p;
> +		MonoClassField * other;
> +
> +		for (p = field->parent; p != NULL; p = p->parent) {
> +			gpointer iter = NULL;
> +			while ((other = mono_class_get_fields (p, &iter))) {
> +				if (other != field && other->offset == field->offset && !(other->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
> +					CODE_NOT_VERIFIABLE (ctx, g_strdup_printf ("Overlapped reference field at 0x%04x", ctx->ip_offset));
> +					goto overlap_check_end;
> +				}
> +			}
> +		}
> +	}

The code for overlapped fields is not as trivial as this. It is moreover
something you should do on a per-type basis instead of per-field access
in the IL code. metadata/object.c has the code to do proper overlapping
field detection: that code should not be duplicated.

Thanks!

lupus

-- 
-----------------------------------------------------------------
lupus at debian.org                                     debian/rules
lupus at ximian.com                             Monkeys do it better



More information about the Mono-devel-list mailing list