Merge pull request #3686 from lambdageek/dev-format-printf
[mono.git] / mono / metadata / marshal.c
index b27996839e9356dd40c0496abbc451ef3723a6d6..f5cfadbb8faf929ec49a9295ab0f955476660643 100644 (file)
 #include <string.h>
 #include <errno.h>
 
+#if defined(HOST_WIN32)
+#include <objbase.h>
+#endif
+
 /* #define DEBUG_RUNTIME_CODE */
 
 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
@@ -95,7 +99,7 @@ static void
 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object);
 
 static void
-emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object, MonoMarshalNative string_encoding);
+emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object, int offset_of_first_child_field, MonoMarshalNative string_encoding);
 
 static void 
 mono_struct_delete_old (MonoClass *klass, char *ptr);
@@ -778,7 +782,7 @@ mono_free_lparray (MonoArray *array, gpointer* nativeArray)
        if (klass->element_class->byval_arg.type == MONO_TYPE_CLASS) {
                for(i = 0; i < array->max_length; ++i)
                        mono_marshal_free_ccw (mono_array_get (array, MonoObject*, i));
-               free(nativeArray);
+               g_free (nativeArray);
        }
 #endif
 }
@@ -1937,15 +1941,26 @@ emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv
        }
 }
 
+static int offset_of_first_nonstatic_field(MonoClass *klass)
+{
+       int i;
+       for (i = 0; i < klass->field.count; i++) {
+               if (!(klass->fields[i].type->attrs & FIELD_ATTRIBUTE_STATIC) && !mono_field_is_deleted (&klass->fields[i]))
+                       return klass->fields[i].offset - sizeof (MonoObject);
+       }
+
+       return 0;
+}
+
 static void
 emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object,
-                                          MonoMarshalNative string_encoding)
+                                               int offset_of_first_child_field, MonoMarshalNative string_encoding)
 {
        MonoMarshalType *info;
        int i;
 
        if (klass->parent)
-               emit_struct_conv(mb, klass->parent, to_object);
+               emit_struct_conv_full (mb, klass->parent, to_object, offset_of_first_nonstatic_field (klass), string_encoding);
 
        info = mono_marshal_load_type_info (klass);
 
@@ -1953,16 +1968,21 @@ emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_obje
                return;
 
        if (klass->blittable) {
-               int msize = mono_class_value_size (klass, NULL);
-               g_assert (msize == info->native_size);
+               int usize = mono_class_value_size (klass, NULL);
+               g_assert (usize == info->native_size);
                mono_mb_emit_ldloc (mb, 1);
                mono_mb_emit_ldloc (mb, 0);
-               mono_mb_emit_icon (mb, msize);
+               mono_mb_emit_icon (mb, usize);
                mono_mb_emit_byte (mb, CEE_PREFIX1);
                mono_mb_emit_byte (mb, CEE_CPBLK);
 
-               mono_mb_emit_add_to_local (mb, 0, msize);
-               mono_mb_emit_add_to_local (mb, 1, msize);
+               if (to_object) {
+                       mono_mb_emit_add_to_local (mb, 0, usize);
+                       mono_mb_emit_add_to_local (mb, 1, offset_of_first_child_field);
+               } else {
+                       mono_mb_emit_add_to_local (mb, 0, offset_of_first_child_field);
+                       mono_mb_emit_add_to_local (mb, 1, usize);
+               }
                return;
        }
 
@@ -2166,7 +2186,7 @@ emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_obje
 static void
 emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
 {
-       emit_struct_conv_full (mb, klass, to_object, (MonoMarshalNative)-1);
+       emit_struct_conv_full (mb, klass, to_object, 0, (MonoMarshalNative)-1);
 }
 
 static void
@@ -2675,6 +2695,11 @@ mono_marshal_method_from_wrapper (MonoMethod *wrapper)
                        return info->d.runtime_invoke.method;
                else
                        return NULL;
+       case MONO_WRAPPER_DELEGATE_INVOKE:
+               if (info)
+                       return info->d.delegate_invoke.method;
+               else
+                       return NULL;
        default:
                return NULL;
        }
@@ -3255,7 +3280,7 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt
        gboolean closed_over_null = FALSE;
        MonoGenericContext *ctx = NULL;
        MonoGenericContainer *container = NULL;
-       MonoMethod *orig_method = NULL;
+       MonoMethod *orig_method = method;
        WrapperInfo *info;
        WrapperSubtype subtype = WRAPPER_SUBTYPE_NONE;
        gboolean found;
@@ -3299,7 +3324,6 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt
         * For generic delegates, create a generic wrapper, and return an instance to help AOT.
         */
        if (method->is_inflated && subtype == WRAPPER_SUBTYPE_NONE) {
-               orig_method = method;
                ctx = &((MonoMethodInflated*)method)->context;
                method = ((MonoMethodInflated*)method)->declaring;
 
@@ -3548,7 +3572,7 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt
 #endif /* DISABLE_JIT */
 
        info = mono_wrapper_info_create (mb, subtype);
-       info->d.delegate_invoke.method = method;
+       info->d.delegate_invoke.method = orig_method;
 
        if (ctx) {
                MonoMethod *def;
@@ -6343,7 +6367,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
                                mono_mb_emit_stloc (mb, 1);
 
                                /* emit valuetype conversion code */
-                               emit_struct_conv_full (mb, eklass, FALSE, eklass == mono_defaults.char_class ? encoding : (MonoMarshalNative)-1);
+                               emit_struct_conv_full (mb, eklass, FALSE, 0, eklass == mono_defaults.char_class ? encoding : (MonoMarshalNative)-1);
                        }
 
                        mono_mb_emit_add_to_local (mb, index_var, 1);
@@ -6488,7 +6512,7 @@ emit_marshal_array (EmitMarshalContext *m, int argnum, MonoType *t,
                                        mono_mb_emit_stloc (mb, 1);
 
                                        /* emit valuetype conversion code */
-                                       emit_struct_conv_full (mb, eklass, TRUE, eklass == mono_defaults.char_class ? encoding : (MonoMarshalNative)-1);
+                                       emit_struct_conv_full (mb, eklass, TRUE, 0, eklass == mono_defaults.char_class ? encoding : (MonoMarshalNative)-1);
                                }
 
                                if (need_free) {
@@ -10511,7 +10535,7 @@ mono_marshal_alloc (gulong size, MonoError *error)
 #else
        res = g_try_malloc ((gulong)size);
        if (!res)
-               mono_error_set_out_of_memory (error, "Could not allocate %i bytes", size);
+               mono_error_set_out_of_memory (error, "Could not allocate %lu bytes", size);
 #endif
        return res;
 }
@@ -10949,7 +10973,12 @@ ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi (MonoString
        if (!tres)
                return tres;
 
-       len = strlen (tres) + 1;
+       /*
+        * mono_string_to_utf8_checked() returns a memory area at least as large as the size of the
+        * MonoString, even if it contains NULL characters. The copy we allocate here has to be equally
+        * large.
+        */
+       len = MAX (strlen (tres) + 1, string->length);
        ret = ves_icall_System_Runtime_InteropServices_Marshal_AllocHGlobal (len);
        memcpy (ret, tres, len);
        g_free (tres);