MonoDomain *domain = mono_domain_get ();
char *name, *filename;
MonoImageOpenStatus status = MONO_IMAGE_OK;
- MonoAssembly *ass;
+ MonoAssembly *ass = NULL;
+
+ name = NULL;
+ result = NULL;
+
+ mono_error_init (&error);
if (fname == NULL) {
- MonoException *exc = mono_get_exception_argument_null ("assemblyFile");
- mono_set_pending_exception (exc);
- return NULL;
+ mono_error_set_argument_null (&error, "assemblyFile", "");
+ goto leave;
}
name = filename = mono_string_to_utf8_checked (fname, &error);
- if (mono_error_set_pending_exception (&error))
- return NULL;
+ if (!is_ok (&error))
+ goto leave;
ass = mono_assembly_open_full (filename, &status, refOnly);
if (!ass) {
- MonoException *exc;
-
if (status == MONO_IMAGE_IMAGE_INVALID)
- exc = mono_get_exception_bad_image_format2 (NULL, fname);
+ mono_error_set_bad_image_name (&error, name, "");
else
- exc = mono_get_exception_file_not_found2 (NULL, fname);
- g_free (name);
- mono_set_pending_exception (exc);
- return NULL;
+ mono_error_set_exception_instance (&error, mono_get_exception_file_not_found2 (NULL, fname));
+ goto leave;
}
- g_free (name);
-
result = mono_assembly_get_object_checked (domain, ass, &error);
- if (!result)
- mono_error_set_pending_exception (&error);
+
+leave:
+ mono_error_set_pending_exception (&error);
+ g_free (name);
return result;
}
MonoAssembly *ass;
MonoAssemblyName aname;
MonoReflectionAssembly *refass = NULL;
- gchar *name;
+ gchar *name = NULL;
gboolean parsed;
g_assert (assRef);
if (mono_error_set_pending_exception (&error))
return NULL;
parsed = mono_assembly_name_parse (name, &aname);
- g_free (name);
if (!parsed) {
/* This is a parse error... */
if (!refOnly) {
refass = mono_try_assembly_resolve (domain, assRef, NULL, refOnly, &error);
- if (!mono_error_ok (&error)) {
- mono_error_set_pending_exception (&error);
- return NULL;
- }
+ if (!is_ok (&error))
+ goto leave;
}
return refass;
}
/* MS.NET doesn't seem to call the assembly resolve handler for refonly assemblies */
if (!refOnly) {
refass = mono_try_assembly_resolve (domain, assRef, NULL, refOnly, &error);
- if (!mono_error_ok (&error)) {
- mono_error_set_pending_exception (&error);
- return NULL;
- }
+ if (!is_ok (&error))
+ goto leave;
}
else
refass = NULL;
- if (!refass) {
- return NULL;
- }
+ if (!refass)
+ goto leave;
+ ass = refass->assembly;
}
- if (refass == NULL)
+ g_assert (ass);
+ if (refass == NULL) {
refass = mono_assembly_get_object_checked (domain, ass, &error);
+ if (!is_ok (&error))
+ goto leave;
+ }
- if (refass == NULL)
- mono_error_set_pending_exception (&error);
- else
- MONO_OBJECT_SETREF (refass, evidence, evidence);
+ MONO_OBJECT_SETREF (refass, evidence, evidence);
+
+leave:
+ g_free (name);
+ mono_error_set_pending_exception (&error);
return refass;
}
static MonoBoolean
mono_assembly_is_in_gac (const gchar *filanem);
+static MonoAssembly*
+prevent_reference_assembly_from_running (MonoAssembly* candidate, gboolean refonly);
+
static gchar*
encode_public_tok (const guchar *token, gint32 len)
{
aname.major, aname.minor, aname.build, aname.revision,
strlen ((char*)aname.public_key_token) == 0 ? "(none)" : (char*)aname.public_key_token, extra_msg);
g_free (extra_msg);
+
}
mono_assemblies_lock ();
/**
- * mono_assembly_get_reference_assembly_attribute:
+ * mono_assembly_has_reference_assembly_attribute:
* @assembly: a MonoAssembly
* @error: set on error.
*
* On error returns FALSE and sets @error.
*/
gboolean
-mono_assembly_get_reference_assembly_attribute (MonoAssembly *assembly, MonoError *error)
+mono_assembly_has_reference_assembly_attribute (MonoAssembly *assembly, MonoError *error)
{
mono_error_init (error);
if (!attrs)
return FALSE;
MonoClass *ref_asm_class = mono_class_try_get_reference_assembly_class ();
- gboolean result = FALSE;
- for (int i = 0; i < attrs->num_attrs; ++i) {
- MonoCustomAttrEntry *attr = &attrs->attrs [i];
- if (attr->ctor && attr->ctor->klass && attr->ctor->klass == ref_asm_class) {
- result = TRUE;
- break;
- }
- }
+ g_assert (ref_asm_class != NULL && ref_asm_class != mono_defaults.object_class && !strcmp(ref_asm_class->name, "ReferenceAssemblyAttribute") );
+ gboolean result = mono_custom_attrs_has_attr (attrs, ref_asm_class);
mono_custom_attrs_free (attrs);
return result;
}
return ass2;
}
+ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Prepared to set up assembly '%s' (%s)", ass->aname.name, image->name);
+
+ /* We need to check for ReferenceAssmeblyAttribute before we
+ * mark the assembly as loaded and before we fire the load
+ * hook. Otherwise mono_domain_fire_assembly_load () in
+ * appdomain.c will cache a mapping from the assembly name to
+ * this image and we won't be able to look for a different
+ * candidate. */
+
+ if (!refonly && strcmp (ass->aname.name, "mscorlib") != 0) {
+ /* Don't check for reference assmebly attribute for
+ * corlib here because if corlib isn't loaded yet,
+ * it's too early to set up the
+ * ReferenceAssemblyAttribute class. We check that
+ * we're not running with a reference corlib in
+ * mono_init_internal().
+ */
+ MonoError refasm_error;
+ if (mono_assembly_has_reference_assembly_attribute (ass, &refasm_error)) {
+ mono_assemblies_unlock ();
+ mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_ASSEMBLY, "Image for assembly '%s' (%s) has ReferenceAssemblyAttribute, skipping", ass->aname.name, image->name);
+ g_free (ass);
+ g_free (base_dir);
+ mono_image_close (image);
+ *status = MONO_IMAGE_IMAGE_INVALID;
+ return NULL;
+ }
+ mono_error_cleanup (&refasm_error);
+ }
+
image->assembly = ass;
loaded_assemblies = g_list_prepend (loaded_assemblies, ass);
return corlib;
}
+static MonoAssembly*
+prevent_reference_assembly_from_running (MonoAssembly* candidate, gboolean refonly)
+{
+ MonoError refasm_error;
+ mono_error_init (&refasm_error);
+ if (candidate && !refonly && mono_assembly_has_reference_assembly_attribute (candidate, &refasm_error)) {
+ candidate = NULL;
+ }
+ mono_error_cleanup (&refasm_error);
+ return candidate;
+}
+
+
MonoAssembly*
mono_assembly_load_full_nosearch (MonoAssemblyName *aname,
const char *basedir,
{
MonoAssembly *result = mono_assembly_load_full_nosearch (aname, basedir, status, refonly);
- if (!result)
+ if (!result) {
/* Try a postload search hook */
result = mono_assembly_invoke_search_hook_internal (aname, requesting, refonly, TRUE);
+ result = prevent_reference_assembly_from_running (result, refonly);
+ }
return result;
}
/* set the parent to something useful and safe, but mark the type as broken */
parent = mono_defaults.object_class;
mono_class_set_type_load_failure (klass, "");
+ g_assert (parent);
}
klass->parent = parent;
if (centry->ctor == NULL)
continue;
MonoClass *klass = centry->ctor->klass;
- if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
+ if (klass == attr_klass || mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
return TRUE;
}
return FALSE;
if (centry->ctor == NULL)
continue;
MonoClass *klass = centry->ctor->klass;
- if (mono_class_is_assignable_from (attr_klass, klass))
+ if (attr_klass == klass || mono_class_is_assignable_from (attr_klass, klass))
break;
}
if (centry == NULL)
mono_context_init_checked (MonoDomain *domain, MonoError *error);
gboolean
-mono_assembly_get_reference_assembly_attribute (MonoAssembly *assembly, MonoError *error);
+mono_assembly_has_reference_assembly_attribute (MonoAssembly *assembly, MonoError *error);
#endif /* __MONO_METADATA_DOMAIN_INTERNALS_H__ */
mono_profiler_appdomain_name (domain, domain->friendly_name);
+ /* Have to do this quite late so that we at least have System.Object */
+ MonoError custom_attr_error;
+ if (mono_assembly_has_reference_assembly_attribute (ass, &custom_attr_error)) {
+ char *corlib_file = g_build_filename (mono_assembly_getrootdir (), "mono", current_runtime->framework_version, "mscorlib.dll", NULL);
+ g_print ("Could not load file or assembly %s. Reference assemblies should not be loaded for execution. They can only be loaded in the Reflection-only loader context.", corlib_file);
+ g_free (corlib_file);
+ exit (1);
+ }
+ mono_error_assert_ok (&custom_attr_error);
+
return domain;
}