[mono] Implement AsAny marshalling for simple arrays (#35686)
authorAlexis Christoforides <alexis@thenull.net>
Wed, 20 May 2020 22:59:29 +0000 (18:59 -0400)
committerGitHub <noreply@github.com>
Wed, 20 May 2020 22:59:29 +0000 (18:59 -0400)
* [mono] Implement AsAny marshalling for simple arrays

Simple here means of rank 1, and with a blittable value type as element type.

* Also implement char arrays

* Do not allow in-params to be marshalled this way, as the callee would have write-ability that is not allowed by in-params

src/mono/mono/metadata/marshal.c

index e7264df..6223aca 100644 (file)
@@ -6268,6 +6268,36 @@ mono_marshal_asany_impl (MonoObjectHandle o, MonoMarshalNative string_encoding,
 
                return res;
        }
+       case MONO_TYPE_SZARRAY: {
+               //TODO: Implement structs and in-params for all value types     
+               MonoClass *klass = t->data.klass;
+               MonoClass *eklass = m_class_get_element_class (klass);
+               MonoArray *arr = (MonoArray *) MONO_HANDLE_RAW (o);
+
+               // we only support char[] for in-params; we return a pointer to the managed heap here, and that's not 'in'-safe
+               if ((param_attrs & PARAM_ATTRIBUTE_IN) && eklass != mono_get_char_class ())
+                       break;
+
+               if (m_class_get_rank (klass) > 1)
+                       break;
+
+               if (arr->bounds)
+                       if (arr->bounds->lower_bound != 0)
+                               break;
+
+               if (mono_class_is_auto_layout (eklass))
+                       break;
+
+               if (m_class_is_valuetype (eklass) && (mono_class_is_explicit_layout (eklass) || m_class_is_blittable (eklass) || m_class_is_enumtype (eklass)))
+                       return arr->vector;
+
+               if (eklass == mono_get_char_class ()) {
+                       char *res =  mono_utf16_to_utf8 ((mono_unichar2 *) arr->vector, arr->max_length, error);
+                       return_val_if_nok (error, NULL);
+                       return res;
+               }
+               break;
+       }
        default:
                break;
        }
@@ -6328,6 +6358,20 @@ mono_marshal_free_asany_impl (MonoObjectHandle o, gpointer ptr, MonoMarshalNativ
                mono_marshal_free (ptr);
                break;
        }
+       case MONO_TYPE_SZARRAY: {
+               MonoClass *klass = t->data.klass;
+               MonoClass *eklass = m_class_get_element_class (klass);
+               MonoArray *arr = (MonoArray *) MONO_HANDLE_RAW (o);
+
+               if (eklass != mono_get_char_class ())
+                       break;
+
+               mono_unichar2 *utf16_array = g_utf8_to_utf16 ((const char *)ptr, arr->max_length, NULL, NULL, NULL);
+               g_free (ptr);
+               memcpy (arr->vector, utf16_array, arr->max_length * sizeof (mono_unichar2));
+               g_free (utf16_array);
+               break;
+       }
        default:
                break;
        }