Skip to content

Commit 750b1ef

Browse files
committed
Fix Span .ctor from unmaged pointer
1 parent c029754 commit 750b1ef

File tree

2 files changed

+26
-102
lines changed

2 files changed

+26
-102
lines changed

src/CLR/CorLib/corlib_native_System_ReadOnlySpan_1.cpp

Lines changed: 13 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ HRESULT Library_corlib_native_System_ReadOnlySpan_1::_ctor___VOID__VOIDptr__I4(C
1414

1515
int32_t length;
1616
bool isRefContainsRefs = false;
17+
uintptr_t objectRawPointer;
1718

18-
CLR_RT_HeapBlock_Array *sourceArray;
19-
19+
CLR_RT_HeapBlock_Array *destinationArray;
2020
CLR_RT_HeapBlock *thisSpan = stack.This();
2121

2222
// grab caller to get the generic type
@@ -85,62 +85,24 @@ HRESULT Library_corlib_native_System_ReadOnlySpan_1::_ctor___VOID__VOIDptr__I4(C
8585
}
8686

8787
// get the pointer to the array
88-
// assuming the pointer its an array allocated by a previous call to localloc
89-
sourceArray = stack.Arg1().DereferenceArray();
90-
91-
// check the element being UInt8
92-
if (sourceArray->m_typeOfElement != DATATYPE_U1)
88+
// validate data type as being an unmanaged pointer
89+
if (stack.Arg1().DataType() != DATATYPE_PTR)
9390
{
9491
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
9592
}
9693

97-
{
98-
// set reference to the pointer to the array
99-
thisSpan[FIELD___array].SetObjectReference(sourceArray);
100-
101-
// adjust the element type and size to match the generic type T
102-
// The sourceArray was allocated as byte[], but we're going to re-shaping it as T[]
103-
104-
// Get the TypeDef instance for the element type
105-
CLR_RT_TypeDef_Instance inst{};
106-
if (!inst.InitializeFromIndex(element.Class))
107-
{
108-
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
109-
}
94+
objectRawPointer = (uintptr_t)stack.Arg1().Dereference();
11095

111-
// Get the element data type and lookup table
112-
NanoCLRDataType dt = (NanoCLRDataType)inst.target->dataType;
113-
const CLR_RT_DataTypeLookup &dtl = c_CLR_RT_DataTypeLookup[dt];
114-
115-
CLR_UINT32 elementSize = dtl.m_sizeInBytes;
116-
117-
if (elementSize == CLR_RT_DataTypeLookup::c_NA)
118-
{
119-
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
120-
}
121-
122-
CLR_UINT32 newNumElements = sourceArray->m_numOfElements / elementSize;
123-
124-
// Validate that length doesn't exceed available space
125-
if ((CLR_UINT32)length > newNumElements)
126-
{
127-
NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);
128-
}
129-
130-
// Update the reflection data type to the new element type
131-
sourceArray->ReflectionData().data.type = element.Class;
132-
133-
// Now re-shape the array to make it T[]
134-
sourceArray->m_typeOfElement = dt;
135-
sourceArray->m_sizeOfElement = (CLR_UINT8)elementSize;
136-
sourceArray->m_numOfElements = (CLR_UINT32)length;
96+
{
97+
CLR_RT_HeapBlock &refArray = thisSpan[FIELD___array];
98+
CLR_RT_HeapBlock_Array::CreateInstance(refArray, length, element.Class);
13799

138-
// Set fReference flag based on whether element type is numeric
139-
// (same logic as ExtractHeapBlocksForArray)
140-
sourceArray->m_fReference = (dtl.m_flags & CLR_RT_DataTypeLookup::c_Numeric) == 0;
100+
destinationArray = thisSpan[FIELD___array].DereferenceArray();
101+
CLR_UINT32 elementSize = destinationArray->m_sizeOfElement;
102+
CLR_UINT8 *elementPtr = destinationArray->GetFirstElement();
141103

142-
// need to call this in order to have the individual elements cleared
143-
sourceArray->ClearElements(0, length);
104+
// copy data from the raw pointer to the newly created array
105+
memcpy(elementPtr, (void *)objectRawPointer, elementSize * length);
144106
}
145107

146108
// set length

src/CLR/CorLib/corlib_native_System_Span_1.cpp

Lines changed: 13 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ HRESULT Library_corlib_native_System_Span_1::_ctor___VOID__VOIDptr__I4(CLR_RT_St
1414

1515
int32_t length;
1616
bool isRefContainsRefs = false;
17+
uintptr_t objectRawPointer;
1718

18-
CLR_RT_HeapBlock_Array *sourceArray;
19-
19+
CLR_RT_HeapBlock_Array *destinationArray;
2020
CLR_RT_HeapBlock *thisSpan = stack.This();
2121

2222
// grab caller to get the generic type
@@ -85,62 +85,24 @@ HRESULT Library_corlib_native_System_Span_1::_ctor___VOID__VOIDptr__I4(CLR_RT_St
8585
}
8686

8787
// get the pointer to the array
88-
// assuming the pointer its an array allocated by a previous call to localloc
89-
sourceArray = stack.Arg1().DereferenceArray();
90-
91-
// check the element being UInt8
92-
if (sourceArray->m_typeOfElement != DATATYPE_U1)
88+
// validate data type as being an unmanaged pointer
89+
if (stack.Arg1().DataType() != DATATYPE_PTR)
9390
{
9491
NANOCLR_SET_AND_LEAVE(CLR_E_INVALID_PARAMETER);
9592
}
9693

97-
{
98-
// set reference to the pointer to the array
99-
thisSpan[FIELD___array].SetObjectReference(sourceArray);
100-
101-
// adjust the element type and size to match the generic type T
102-
// The sourceArray was allocated as byte[], but we're going to re-shaping it as T[]
103-
104-
// Get the TypeDef instance for the element type
105-
CLR_RT_TypeDef_Instance inst{};
106-
if (!inst.InitializeFromIndex(element.Class))
107-
{
108-
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
109-
}
110-
111-
// Get the element data type and lookup table
112-
NanoCLRDataType dt = (NanoCLRDataType)inst.target->dataType;
113-
const CLR_RT_DataTypeLookup &dtl = c_CLR_RT_DataTypeLookup[dt];
114-
115-
CLR_UINT32 elementSize = dtl.m_sizeInBytes;
94+
objectRawPointer = (uintptr_t)stack.Arg1().Dereference();
11695

117-
if (elementSize == CLR_RT_DataTypeLookup::c_NA)
118-
{
119-
NANOCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE);
120-
}
121-
122-
CLR_UINT32 newNumElements = sourceArray->m_numOfElements / elementSize;
123-
124-
// Validate that length doesn't exceed available space
125-
if ((CLR_UINT32)length > newNumElements)
126-
{
127-
NANOCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE);
128-
}
129-
130-
// Update the reflection data type to the new element type
131-
sourceArray->ReflectionData().data.type = element.Class;
132-
133-
// Now re-shape the array to make it T[]
134-
sourceArray->m_typeOfElement = dt;
135-
sourceArray->m_sizeOfElement = (CLR_UINT8)elementSize;
136-
sourceArray->m_numOfElements = (CLR_UINT32)length;
96+
{
97+
CLR_RT_HeapBlock &refArray = thisSpan[FIELD___array];
98+
CLR_RT_HeapBlock_Array::CreateInstance(refArray, length, element.Class);
13799

138-
// Set fReference flag based on whether element type is numeric
139-
// (same logic as ExtractHeapBlocksForArray)
140-
sourceArray->m_fReference = (dtl.m_flags & CLR_RT_DataTypeLookup::c_Numeric) == 0;
100+
destinationArray = thisSpan[FIELD___array].DereferenceArray();
101+
CLR_UINT32 elementSize = destinationArray->m_sizeOfElement;
102+
CLR_UINT8 *elementPtr = destinationArray->GetFirstElement();
141103

142-
// need to call this in order to have the individual elements cleared
143-
sourceArray->ClearElements(0, length);
104+
// copy data from the raw pointer to the newly created array
105+
memcpy(elementPtr, (void *)objectRawPointer, elementSize * length);
144106
}
145107

146108
// set length

0 commit comments

Comments
 (0)