Skip to content

Commit 5b70af8

Browse files
authored
[mono] Support copying arrays of compatible pointers (#104611)
Fixes #104197
1 parent d40ac7c commit 5b70af8

File tree

4 files changed

+16
-22
lines changed

4 files changed

+16
-22
lines changed

src/libraries/System.Runtime/tests/System.Runtime.Tests/System/ArrayTests.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1599,7 +1599,6 @@ public static void Copy_SourceAndDestinationNeverConvertible_ThrowsArrayTypeMism
15991599
}
16001600

16011601
[Fact]
1602-
[SkipOnMono("https://github.com/dotnet/runtime/issues/104197")]
16031602
public static unsafe void Copy_CompatiblePointers()
16041603
{
16051604
// Can copy between compatible pointers

src/mono/mono/metadata/class.c

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3582,6 +3582,7 @@ mono_class_is_subclass_of_internal (MonoClass *klass, MonoClass *klassc,
35823582
gboolean check_interfaces)
35833583
{
35843584
MONO_REQ_GC_UNSAFE_MODE;
3585+
35853586
/* FIXME test for interfaces with variant generic arguments */
35863587
if (check_interfaces) {
35873588
mono_class_init_internal (klass);
@@ -4284,13 +4285,9 @@ mono_class_is_assignable_from_general (MonoClass *klass, MonoClass *oklass, gboo
42844285

42854286
MonoClass *eclass;
42864287
MonoClass *eoclass;
4287-
if (signature_assignment) {
4288-
eclass = composite_type_to_reduced_element_type (klass);
4289-
eoclass = composite_type_to_reduced_element_type (oklass);
4290-
} else {
4291-
eclass = m_class_get_cast_class (klass);
4292-
eoclass = m_class_get_cast_class (oklass);
4293-
}
4288+
4289+
eclass = composite_type_to_reduced_element_type (klass);
4290+
eoclass = composite_type_to_reduced_element_type (oklass);
42944291

42954292
*result = (eclass == eoclass);
42964293
return;

src/mono/mono/metadata/icall.c

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -199,12 +199,7 @@ ves_icall_System_Array_GetValueImpl (MonoObjectHandleOnStack array_handle, MonoO
199199
MonoClass * const array_class = mono_object_class (array);
200200
MonoClass * const element_class = m_class_get_element_class (array_class);
201201

202-
if (m_class_is_native_pointer (element_class)) {
203-
mono_error_set_not_supported (error, NULL);
204-
return;
205-
}
206-
207-
if (m_class_is_valuetype (element_class)) {
202+
if (m_class_is_valuetype (element_class) || mono_class_is_pointer (element_class)) {
208203
gsize element_size = mono_array_element_size (array_class);
209204
gpointer element_address = mono_array_addr_with_size_fast (array, element_size, (gsize)pos);
210205
MonoObject *res = mono_value_box_checked (element_class, element_address, error);
@@ -872,13 +867,16 @@ ves_icall_System_Array_FastCopy (MonoObjectHandleOnStack source_handle, int sour
872867
if (m_class_is_valuetype (dest_class) || m_class_is_enumtype (dest_class) ||
873868
m_class_is_valuetype (src_class) || m_class_is_valuetype (src_class))
874869
return FALSE;
875-
876-
/* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
877-
if (!mono_class_is_subclass_of_internal (src_class, dest_class, FALSE))
878-
return FALSE;
879-
880-
if (m_class_is_native_pointer (src_class) || m_class_is_native_pointer (dest_class))
881-
return FALSE;
870+
871+
if (mono_class_is_pointer (dest_class) || mono_class_is_pointer (src_class)) {
872+
/* if we're copying between at least one array of pointers, only allow it if both dest_class is assignable from src_class (checked above, and src_class is assignable from dest_class). This should only be true if both src_class and dest_class have a common cast_class. (for example: int*[] and uint*[] are ok, but void*[] and int*[] are not)). */
873+
if (!mono_class_is_assignable_from_internal (dest_class, src_class))
874+
return FALSE;
875+
} else {
876+
/* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
877+
if (!mono_class_is_subclass_of_internal (src_class, dest_class, FALSE))
878+
return FALSE;
879+
}
882880
}
883881

884882
if (m_class_is_valuetype (dest_class)) {

src/mono/mono/metadata/object.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6529,7 +6529,7 @@ mono_value_box_handle (MonoClass *klass, gpointer value, MonoError *error)
65296529

65306530
error_init (error);
65316531

6532-
g_assert (m_class_is_valuetype (klass));
6532+
g_assert (m_class_is_valuetype (klass) || mono_class_is_pointer (klass));
65336533
g_assert (value != NULL);
65346534
if (G_UNLIKELY (m_class_is_byreflike (klass))) {
65356535
char *full_name = mono_type_get_full_name (klass);

0 commit comments

Comments
 (0)