structs with VariableLengthInlineArray and SizeOf(0)
Nobody has claimed this yet.
- Dominant language
- C#
- Stars
- 2.5k
- Forks
- 124
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 9
Description
C structures with a flexible array member at the end (array of [0] elements) get translated to a VariableLengthInLineArray. As an example, I take USB_DESCRIPTOR_REQUEST, which in C is:
typedef struct _USB_DESCRIPTOR_REQUEST {
ULONG ConnectionIndex;
struct {
UCHAR bmRequest;
UCHAR bRequest;
USHORT wValue;
USHORT wIndex;
USHORT wLength;
} SetupPacket;
UCHAR Data[0];
} USB_DESCRIPTOR_REQUEST, *PUSB_DESCRIPTOR_REQUEST;
I know about the discussion that in C# (using CsWin32) the VariableLengthInLineArray always has 1 member (as if UCHAR Data[1] instead of UCHAR Data[0]), and therefore the sizeof(C# struct) does not match the sizeof(C struct). And that's OK, since we now have a convenience member function SizeOf for such structures that takes a count parameter for the real number of elements in the array.
However, the function is defined as:
/// <summary>Computes the amount of memory that must be allocated to store this struct, including the specified number of elements in the variable length inline array at the end.</summary>
internal static unsafe int SizeOf(int count)
{
int v = sizeof(USB_DESCRIPTOR_REQUEST);
if (count > 1)
v +=checked((count - 1) * sizeof(byte));
else
if (count < 0)
throw new ArgumentOutOfRangeException();
return v;
}
This does not return the correct size for 0; SizeOf(0) is still off by 1 array element. In fact SizeOf(0) == SizeOf(1) in the current implementation. Note that for the example USB_DESCRIPTOR_REQUEST, 0 is actually a valid size for the array (as in: the data is optional).
I don't know if this is deliberate, or actually a bug.
Could SizeOf(0) be changed so it returns sizeof(C# struct) - sizeof(the 1 element in VariableLengthInLineArray) == sizeof(C struct)? Something like:
/// <summary>Computes the amount of memory that must be allocated to store this struct, including the specified number of elements in the variable length inline array at the end.</summary>
internal static unsafe int SizeOf(int count)
{
int v = sizeof(USB_DESCRIPTOR_REQUEST);
if (count >= 0)
// NOTE: the -1 for count == 0 is intentional, to compensate for the omnipresent 1 element in VariableLengthInLineArray
v +=checked((count - 1) * sizeof(byte));
else
throw new ArgumentOutOfRangeException();
return v;
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by locating the generated USB_DESCRIPTOR_REQUEST SizeOf(int) implementation and the handling of VariableLengthInLineArray. Verify the current results for counts 0, 1, and greater values, then add or update coverage so SizeOf(0) matches the C flexible-array layout while negative counts remain invalid.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100