Merge pull request #4621 from alexanderkyte/strdup_env
[mono.git] / mono / metadata / image.c
index d09924ff496afc30d6fc625ffedb7ca7ba0d4d53..eb4d686412e586b822e0f064748cc7e7117c2b64 100644 (file)
@@ -1,5 +1,6 @@
-/*
- * image.c: Routines for manipulating an image stored in an
+/**
+ * \file
+ * Routines for manipulating an image stored in an
  * extended PE/COFF file.
  * 
  * Authors:
@@ -199,14 +200,14 @@ mono_cli_rva_image_map (MonoImage *image, guint32 addr)
 }
 
 /**
- * mono_images_rva_map:
- * @image: a MonoImage
- * @addr: relative virtual address (RVA)
+ * mono_image_rva_map:
+ * \param image a \c MonoImage
+ * \param addr relative virtual address (RVA)
  *
  * This is a low-level routine used by the runtime to map relative
  * virtual address (RVA) into their location in memory. 
  *
- * Returns: the address in memory for the given RVA, or NULL if the
+ * \returns the address in memory for the given RVA, or NULL if the
  * RVA is not valid for this image. 
  */
 char *
@@ -290,13 +291,13 @@ mono_images_cleanup (void)
 
 /**
  * mono_image_ensure_section_idx:
- * @image: The image we are operating on
- * @section: section number that we will load/map into memory
+ * \param image The image we are operating on
+ * \param section section number that we will load/map into memory
  *
  * This routine makes sure that we have an in-memory copy of
- * an image section (.text, .rsrc, .data).
+ * an image section (<code>.text</code>, <code>.rsrc</code>, <code>.data</code>).
  *
- * Returns: TRUE on success
+ * \returns TRUE on success
  */
 int
 mono_image_ensure_section_idx (MonoImage *image, int section)
@@ -325,13 +326,13 @@ mono_image_ensure_section_idx (MonoImage *image, int section)
 
 /**
  * mono_image_ensure_section:
- * @image: The image we are operating on
- * @section: section name that we will load/map into memory
+ * \param image The image we are operating on
+ * \param section section name that we will load/map into memory
  *
  * This routine makes sure that we have an in-memory copy of
  * an image section (.text, .rsrc, .data).
  *
- * Returns: TRUE on success
+ * \returns TRUE on success
  */
 int
 mono_image_ensure_section (MonoImage *image, const char *section)
@@ -535,9 +536,9 @@ load_metadata_ptrs (MonoImage *image, MonoCLIImageInfo *iinfo)
        }
 
        i = ((MonoImageLoader*)image->loader)->load_tables (image);
-       g_assert (image->heap_guid.data);
 
        if (!image->metadata_only) {
+               g_assert (image->heap_guid.data);
                g_assert (image->heap_guid.size >= 16);
 
                image->guid = mono_guid_to_string ((guint8*)image->heap_guid.data);
@@ -758,6 +759,9 @@ mono_image_load_module_checked (MonoImage *image, int idx, MonoError *error)
        return image->modules [idx - 1];
 }
 
+/**
+ * mono_image_load_module:
+ */
 MonoImage*
 mono_image_load_module (MonoImage *image, int idx)
 {
@@ -783,6 +787,9 @@ class_next_value (gpointer value)
        return (gpointer*)&klass->next_class_cache;
 }
 
+/**
+ * mono_image_init:
+ */
 void
 mono_image_init (MonoImage *image)
 {
@@ -1102,7 +1109,7 @@ Mono provides its own implementation of those assemblies so it's safe to do so.
 
 The ignored_assemblies list is generated using tools/nuget-hash-extractor and feeding the problematic nugets to it.
 
-Right now the list of nugets are the ones that provide the assemblies in $ignored_assemblies_names.
+Right now the list of nugets are the ones that provide the assemblies in $ignored_assemblies_file_names.
 
 This is to be removed once a proper fix is shipped through nuget.
 
@@ -1124,7 +1131,12 @@ typedef struct {
        const char guid [40];
 } IgnoredAssembly;
 
-const char *ignored_assemblies_names[] = {
+typedef struct {
+       int assembly_name;
+       guint16 major, minor, build, revision;
+} IgnoredAssemblyVersion;
+
+const char *ignored_assemblies_file_names[] = {
        "System.Runtime.InteropServices.RuntimeInformation.dll",
        "System.Globalization.Extensions.dll",
        "System.IO.Compression.dll",
@@ -1155,6 +1167,53 @@ static const IgnoredAssembly ignored_assemblies [] = {
        IGNORED_ASSEMBLY (0x75B4B041, SYS_VALUE_TUPLE, "F81A4140-A898-4E2B-B6E9-55CE78C273EC", "4.3.0 netstandard1.0"),
 };
 
+
+const char *ignored_assemblies_names[] = {
+       "System.Runtime.InteropServices.RuntimeInformation",
+       "System.Globalization.Extensions",
+       "System.IO.Compression",
+       "System.Net.Http",
+       "System.Text.Encoding.CodePages",
+       "System.Reflection.DispatchProxy",
+       "System.ValueTuple"
+};
+
+#define IGNORED_ASM_VER(NAME, MAJOR, MINOR, BUILD, REVISION) { .assembly_name = NAME, .major = MAJOR, .minor = MINOR, .build = BUILD, .revision = REVISION }
+
+static const IgnoredAssemblyVersion ignored_assembly_versions [] = {
+       IGNORED_ASM_VER (SYS_GLOBALIZATION_EXT, 4, 0, 0, 0),
+       IGNORED_ASM_VER (SYS_GLOBALIZATION_EXT, 4, 0, 1, 0),
+       IGNORED_ASM_VER (SYS_GLOBALIZATION_EXT, 4, 0, 2, 0),
+       IGNORED_ASM_VER (SYS_IO_COMPRESSION, 4, 1, 0, 0),
+       IGNORED_ASM_VER (SYS_IO_COMPRESSION, 4, 1, 2, 0),
+       IGNORED_ASM_VER (SYS_NET_HTTP, 4, 1, 0, 0),
+       IGNORED_ASM_VER (SYS_NET_HTTP, 4, 1, 0, 1),
+       IGNORED_ASM_VER (SYS_NET_HTTP, 4, 1, 1, 0),
+       IGNORED_ASM_VER (SYS_REF_DISP_PROXY, 4, 0, 0, 0),
+       IGNORED_ASM_VER (SYS_REF_DISP_PROXY, 4, 0, 1, 0),
+       IGNORED_ASM_VER (SYS_REF_DISP_PROXY, 4, 0, 2, 0),
+       IGNORED_ASM_VER (SYS_RT_INTEROP_RUNTIME_INFO, 4, 0, 0, 0),
+       IGNORED_ASM_VER (SYS_RT_INTEROP_RUNTIME_INFO, 4, 0, 1, 0),
+       IGNORED_ASM_VER (SYS_TEXT_ENC_CODEPAGES, 4, 0, 1, 0),
+       IGNORED_ASM_VER (SYS_TEXT_ENC_CODEPAGES, 4, 0, 2, 0),
+       IGNORED_ASM_VER (SYS_VALUE_TUPLE, 4, 0, 1, 0),
+};
+
+gboolean
+mono_assembly_is_problematic_version (const char *name, guint16 major, guint16 minor, guint16 build, guint16 revision)
+{
+       for (int i = 0; i < G_N_ELEMENTS (ignored_assembly_versions); ++i) {
+               if (ignored_assembly_versions [i].major != major ||
+                       ignored_assembly_versions [i].minor != minor ||
+                       ignored_assembly_versions [i].build != build ||
+                       ignored_assembly_versions [i].revision != revision)
+                               continue;
+               if (!strcmp (ignored_assemblies_names [ignored_assembly_versions [i].assembly_name], name))
+                       return TRUE;
+       }
+       return FALSE;
+}
+
 /*
 Equivalent C# code:
        static void Main  () {
@@ -1187,7 +1246,7 @@ is_problematic_image (MonoImage *image)
        // Either sort by hash and bseach or use SoA and make the linear search more cache efficient.
        for (int i = 0; i < G_N_ELEMENTS (ignored_assemblies); ++i) {
                if (ignored_assemblies [i].hash == h && !strcmp (image->guid, ignored_assemblies [i].guid)) {
-                       const char *needle = ignored_assemblies_names [ignored_assemblies [i].assembly_name];
+                       const char *needle = ignored_assemblies_file_names [ignored_assemblies [i].assembly_name];
                        size_t needle_len = strlen (needle);
                        size_t asm_len = strlen (image->name);
                        if (asm_len > needle_len && !g_ascii_strcasecmp (image->name + (asm_len - needle_len), needle))
@@ -1343,14 +1402,14 @@ do_mono_image_open (const char *fname, MonoImageOpenStatus *status,
 }
 
 /**
- * mono_image_loaded:
- * @name: path or assembly name of the image to load
- * @refonly: Check with respect to reflection-only loads?
+ * mono_image_loaded_full:
+ * \param name path or assembly name of the image to load
+ * \param refonly Check with respect to reflection-only loads?
  *
  * This routine verifies that the given image is loaded.
  * It checks either reflection-only loads only, or normal loads only, as specified by parameter.
  *
- * Returns: the loaded MonoImage, or NULL on failure.
+ * \returns the loaded \c MonoImage, or NULL on failure.
  */
 MonoImage *
 mono_image_loaded_full (const char *name, gboolean refonly)
@@ -1368,11 +1427,9 @@ mono_image_loaded_full (const char *name, gboolean refonly)
 
 /**
  * mono_image_loaded:
- * @name: path or assembly name of the image to load
- *
+ * \param name path or assembly name of the image to load
  * This routine verifies that the given image is loaded. Reflection-only loads do not count.
- *
- * Returns: the loaded MonoImage, or NULL on failure.
+ * \returns the loaded \c MonoImage, or NULL on failure.
  */
 MonoImage *
 mono_image_loaded (const char *name)
@@ -1398,6 +1455,9 @@ find_by_guid (gpointer key, gpointer val, gpointer user_data)
                data->res = image;
 }
 
+/**
+ * mono_image_loaded_by_guid_full:
+ */
 MonoImage *
 mono_image_loaded_by_guid_full (const char *guid, gboolean refonly)
 {
@@ -1412,6 +1472,9 @@ mono_image_loaded_by_guid_full (const char *guid, gboolean refonly)
        return data.res;
 }
 
+/**
+ * mono_image_loaded_by_guid:
+ */
 MonoImage *
 mono_image_loaded_by_guid (const char *guid)
 {
@@ -1485,18 +1548,27 @@ mono_image_open_from_data_internal (char *data, guint32 data_len, gboolean need_
        return register_image (image);
 }
 
+/**
+ * mono_image_open_from_data_with_name:
+ */
 MonoImage *
 mono_image_open_from_data_with_name (char *data, guint32 data_len, gboolean need_copy, MonoImageOpenStatus *status, gboolean refonly, const char *name)
 {
        return mono_image_open_from_data_internal (data, data_len, need_copy, status, refonly, FALSE, name);
 }
 
+/**
+ * mono_image_open_from_data_full:
+ */
 MonoImage *
 mono_image_open_from_data_full (char *data, guint32 data_len, gboolean need_copy, MonoImageOpenStatus *status, gboolean refonly)
 {
   return mono_image_open_from_data_with_name (data, data_len, need_copy, status, refonly, NULL);
 }
 
+/**
+ * mono_image_open_from_data:
+ */
 MonoImage *
 mono_image_open_from_data (char *data, guint32 data_len, gboolean need_copy, MonoImageOpenStatus *status)
 {
@@ -1528,6 +1600,9 @@ mono_image_open_from_module_handle (HMODULE module_handle, char* fname, gboolean
 }
 #endif
 
+/**
+ * mono_image_open_full:
+ */
 MonoImage *
 mono_image_open_full (const char *fname, MonoImageOpenStatus *status, gboolean refonly)
 {
@@ -1644,13 +1719,12 @@ mono_image_open_a_lot (const char *fname, MonoImageOpenStatus *status, gboolean
 
 /**
  * mono_image_open:
- * @fname: filename that points to the module we want to open
- * @status: An error condition is returned in this field
- *
- * Returns: An open image of type %MonoImage or NULL on error. 
+ * \param fname filename that points to the module we want to open
+ * \param status An error condition is returned in this field
+ * \returns An open image of type \c MonoImage or NULL on error. 
  * The caller holds a temporary reference to the returned image which should be cleared 
- * when no longer needed by calling mono_image_close ().
- * if NULL, then check the value of @status for details on the error
+ * when no longer needed by calling \c mono_image_close.
+ * if NULL, then check the value of \p status for details on the error
  */
 MonoImage *
 mono_image_open (const char *fname, MonoImageOpenStatus *status)
@@ -1660,13 +1734,12 @@ mono_image_open (const char *fname, MonoImageOpenStatus *status)
 
 /**
  * mono_pe_file_open:
- * @fname: filename that points to the module we want to open
- * @status: An error condition is returned in this field
- *
- * Returns: An open image of type %MonoImage or NULL on error.  if
- * NULL, then check the value of @status for details on the error.
- * This variant for mono_image_open DOES NOT SET UP CLI METADATA.
- * It's just a PE file loader, used for FileVersionInfo.  It also does
+ * \param fname filename that points to the module we want to open
+ * \param status An error condition is returned in this field
+ * \returns An open image of type \c MonoImage or NULL on error.  if
+ * NULL, then check the value of \p status for details on the error.
+ * This variant for \c mono_image_open DOES NOT SET UP CLI METADATA.
+ * It's just a PE file loader, used for \c FileVersionInfo.  It also does
  * not use the image cache.
  */
 MonoImage *
@@ -1679,11 +1752,9 @@ mono_pe_file_open (const char *fname, MonoImageOpenStatus *status)
 
 /**
  * mono_image_open_raw
- * @fname: filename that points to the module we want to open
- * @status: An error condition is returned in this field
- * 
- * Returns an image without loading neither pe or cli data.
- * 
+ * \param fname filename that points to the module we want to open
+ * \param status An error condition is returned in this field
+ * \returns an image without loading neither pe or cli data.
  * Use mono_image_load_pe_data and mono_image_load_cli_data to load them.  
  */
 MonoImage *
@@ -1705,6 +1776,9 @@ mono_image_open_metadata_only (const char *fname, MonoImageOpenStatus *status)
        return do_mono_image_open (fname, status, TRUE, TRUE, FALSE, TRUE, FALSE);
 }
 
+/**
+ * mono_image_fixup_vtable:
+ */
 void
 mono_image_fixup_vtable (MonoImage *image)
 {
@@ -1778,9 +1852,8 @@ free_array_cache_entry (gpointer key, gpointer val, gpointer user_data)
 
 /**
  * mono_image_addref:
- * @image: The image file we wish to add a reference to
- *
- *  Increases the reference count of an image.
+ * \param image The image file we wish to add a reference to
+ * Increases the reference count of an image.
  */
 void
 mono_image_addref (MonoImage *image)
@@ -2116,8 +2189,7 @@ mono_image_close_finish (MonoImage *image)
 
 /**
  * mono_image_close:
- * @image: The image file we wish to close
- *
+ * \param image The image file we wish to close
  * Closes an image file, deallocates all memory consumed and
  * unmaps all possible sections of the file
  */
@@ -2130,9 +2202,8 @@ mono_image_close (MonoImage *image)
 
 /** 
  * mono_image_strerror:
- * @status: an code indicating the result from a recent operation
- *
- * Returns: a string describing the error
+ * \param status an code indicating the result from a recent operation
+ * \returns a string describing the error
  */
 const char *
 mono_image_strerror (MonoImageOpenStatus status)
@@ -2232,13 +2303,12 @@ mono_image_walk_resource_tree (MonoCLIImageInfo *info, guint32 res_id,
 
 /**
  * mono_image_lookup_resource:
- * @image: the image to look up the resource in
- * @res_id: A MONO_PE_RESOURCE_ID_ that represents the resource ID to lookup.
- * @lang_id: The language id.
- * @name: the resource name to lookup.
- *
- * Returns: NULL if not found, otherwise a pointer to the in-memory representation
- * of the given resource. The caller should free it using g_free () when no longer
+ * \param image the image to look up the resource in
+ * \param res_id A \c MONO_PE_RESOURCE_ID_ that represents the resource ID to lookup.
+ * \param lang_id The language id.
+ * \param name the resource name to lookup.
+ * \returns NULL if not found, otherwise a pointer to the in-memory representation
+ * of the given resource. The caller should free it using \c g_free when no longer
  * needed.
  */
 gpointer
@@ -2303,12 +2373,10 @@ mono_image_lookup_resource (MonoImage *image, guint32 res_id, guint32 lang_id, g
 
 /** 
  * mono_image_get_entry_point:
- * @image: the image where the entry point will be looked up.
- *
+ * \param image the image where the entry point will be looked up.
  * Use this routine to determine the metadata token for method that
  * has been flagged as the entry point.
- *
- * Returns: the token for the entry point method in the image
+ * \returns the token for the entry point method in the image
  */
 guint32
 mono_image_get_entry_point (MonoImage *image)
@@ -2318,15 +2386,15 @@ mono_image_get_entry_point (MonoImage *image)
 
 /**
  * mono_image_get_resource:
- * @image: the image where the resource will be looked up.
- * @offset: The offset to add to the resource
- * @size: a pointer to an int where the size of the resource will be stored
+ * \param image the image where the resource will be looked up.
+ * \param offset The offset to add to the resource
+ * \param size a pointer to an int where the size of the resource will be stored
  *
  * This is a low-level routine that fetches a resource from the
- * metadata that starts at a given @offset.  The @size parameter is
+ * metadata that starts at a given \p offset.  The \p size parameter is
  * filled with the data field as encoded in the metadata.
  *
- * Returns: the pointer to the resource whose offset is @offset.
+ * \returns the pointer to the resource whose offset is \p offset.
  */
 const char*
 mono_image_get_resource (MonoImage *image, guint32 offset, guint32 *size)
@@ -2417,6 +2485,9 @@ done:
        return res;
 }
 
+/**
+ * mono_image_load_file_for_image:
+ */
 MonoImage*
 mono_image_load_file_for_image (MonoImage *image, int fileidx)
 {
@@ -2428,13 +2499,13 @@ mono_image_load_file_for_image (MonoImage *image, int fileidx)
 
 /**
  * mono_image_get_strong_name:
- * @image: a MonoImage
- * @size: a guint32 pointer, or NULL.
+ * \param image a MonoImage
+ * \param size a \c guint32 pointer, or NULL.
  *
- * If the image has a strong name, and @size is not NULL, the value
+ * If the image has a strong name, and \p size is not NULL, the value
  * pointed to by size will have the size of the strong name.
  *
- * Returns: NULL if the image does not have a strong name, or a
+ * \returns NULL if the image does not have a strong name, or a
  * pointer to the public key.
  */
 const char*
@@ -2456,13 +2527,13 @@ mono_image_get_strong_name (MonoImage *image, guint32 *size)
 
 /**
  * mono_image_strong_name_position:
- * @image: a MonoImage
- * @size: a guint32 pointer, or NULL.
+ * \param image a \c MonoImage
+ * \param size a \c guint32 pointer, or NULL.
  *
- * If the image has a strong name, and @size is not NULL, the value
+ * If the image has a strong name, and \p size is not NULL, the value
  * pointed to by size will have the size of the strong name.
  *
- * Returns: the position within the image file where the strong name
+ * \returns the position within the image file where the strong name
  * is stored.
  */
 guint32
@@ -2482,15 +2553,15 @@ mono_image_strong_name_position (MonoImage *image, guint32 *size)
 
 /**
  * mono_image_get_public_key:
- * @image: a MonoImage
- * @size: a guint32 pointer, or NULL.
+ * \param image a \c MonoImage
+ * \param size a \c guint32 pointer, or NULL.
  *
- * This is used to obtain the public key in the @image.
+ * This is used to obtain the public key in the \p image.
  * 
- * If the image has a public key, and @size is not NULL, the value
+ * If the image has a public key, and \p size is not NULL, the value
  * pointed to by size will have the size of the public key.
  * 
- * Returns: NULL if the image does not have a public key, or a pointer
+ * \returns NULL if the image does not have a public key, or a pointer
  * to the public key.
  */
 const char*
@@ -2518,9 +2589,8 @@ mono_image_get_public_key (MonoImage *image, guint32 *size)
 
 /**
  * mono_image_get_name:
- * @name: a MonoImage
- *
- * Returns: the name of the assembly.
+ * \param name a \c MonoImage
+ * \returns the name of the assembly.
  */
 const char*
 mono_image_get_name (MonoImage *image)
@@ -2530,11 +2600,9 @@ mono_image_get_name (MonoImage *image)
 
 /**
  * mono_image_get_filename:
- * @image: a MonoImage
- *
- * Used to get the filename that hold the actual MonoImage
- *
- * Returns: the filename.
+ * \param image a \c MonoImage
+ * Used to get the filename that hold the actual \c MonoImage
+ * \returns the filename.
  */
 const char*
 mono_image_get_filename (MonoImage *image)
@@ -2542,12 +2610,18 @@ mono_image_get_filename (MonoImage *image)
        return image->name;
 }
 
+/**
+ * mono_image_get_guid:
+ */
 const char*
 mono_image_get_guid (MonoImage *image)
 {
        return image->guid;
 }
 
+/**
+ * mono_image_get_table_info:
+ */
 const MonoTableInfo*
 mono_image_get_table_info (MonoImage *image, int table_id)
 {
@@ -2556,6 +2630,9 @@ mono_image_get_table_info (MonoImage *image, int table_id)
        return &image->tables [table_id];
 }
 
+/**
+ * mono_image_get_table_rows:
+ */
 int
 mono_image_get_table_rows (MonoImage *image, int table_id)
 {
@@ -2564,6 +2641,9 @@ mono_image_get_table_rows (MonoImage *image, int table_id)
        return image->tables [table_id].rows;
 }
 
+/**
+ * mono_table_info_get_rows:
+ */
 int
 mono_table_info_get_rows (const MonoTableInfo *table)
 {
@@ -2572,11 +2652,9 @@ mono_table_info_get_rows (const MonoTableInfo *table)
 
 /**
  * mono_image_get_assembly:
- * @image: the MonoImage.
- *
+ * \param image the \c MonoImage .
  * Use this routine to get the assembly that owns this image.
- *
- * Returns: the assembly that holds this image.
+ * \returns the assembly that holds this image.
  */
 MonoAssembly* 
 mono_image_get_assembly (MonoImage *image)
@@ -2586,12 +2664,11 @@ mono_image_get_assembly (MonoImage *image)
 
 /**
  * mono_image_is_dynamic:
- * @image: the MonoImage
+ * \param image the \c MonoImage
  *
  * Determines if the given image was created dynamically through the
- * System.Reflection.Emit API
- *
- * Returns: TRUE if the image was created dynamically, FALSE if not.
+ * \c System.Reflection.Emit API
+ * \returns TRUE if the image was created dynamically, FALSE if not.
  */
 gboolean
 mono_image_is_dynamic (MonoImage *image)
@@ -2601,12 +2678,10 @@ mono_image_is_dynamic (MonoImage *image)
 
 /**
  * mono_image_has_authenticode_entry:
- * @image: the MonoImage
- *
+ * \param image the \c MonoImage
  * Use this routine to determine if the image has a Authenticode
  * Certificate Table.
- *
- * Returns: TRUE if the image contains an authenticode entry in the PE
+ * \returns TRUE if the image contains an authenticode entry in the PE
  * directory.
  */
 gboolean
@@ -2736,8 +2811,7 @@ mono_image_unlock (MonoImage *image)
 
 /**
  * mono_image_property_lookup:
- *
- * Lookup a property on @image. Used to store very rare fields of MonoClass and MonoMethod.
+ * Lookup a property on \p image . Used to store very rare fields of \c MonoClass and \c MonoMethod .
  *
  * LOCKING: Takes the image lock
  */
@@ -2755,8 +2829,8 @@ mono_image_property_lookup (MonoImage *image, gpointer subject, guint32 property
 
 /**
  * mono_image_property_insert:
- *
- * Insert a new property @property with value @value on @subject in @image. Used to store very rare fields of MonoClass and MonoMethod.
+ * Insert a new property \p property with value \p value on \p subject in \p
+ * image. Used to store very rare fields of \c MonoClass and \c MonoMethod.
  *
  * LOCKING: Takes the image lock
  */
@@ -2771,8 +2845,7 @@ mono_image_property_insert (MonoImage *image, gpointer subject, guint32 property
 
 /**
  * mono_image_property_remove:
- *
- * Remove all properties associated with @subject in @image. Used to store very rare fields of MonoClass and MonoMethod.
+ * Remove all properties associated with \p subject in \p image. Used to store very rare fields of \c MonoClass and \c MonoMethod .
  *
  * LOCKING: Takes the image lock
  */