Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set a fixed buffer field element using reflection?

Here's a typical unsafe struct declaration that includes a fixed buffer field:

[StructLayout(LayoutKind.Explicit, Pack = 1)]
public unsafe struct MyStruct
{
    ...

    [FieldOffset(6)]
    public fixed ushort MyFixedBuffer[28];

    ...
}

How do I set an element of MyFixeBuffer using reflection?

like image 653
mainvoid Avatar asked Jul 30 '26 14:07

mainvoid


1 Answers

You do not need reflection. What you need is the address of the struct which you want to set. Then you can use

byte* pStruct = xxxx
byte* pMyFixedBuffer = pStruct+6;  // FieldOffset 6 tells me this

*(pMyFixedBuffer+i) = yourBytevalue;  // set i-th element in MyFixedBuffer

I guess you are having problems to get the address of the struct at all because it is most likely passed by value to some methods where you want to patch in different values. As long as the struct is not assigned to a class member variable which instance you can somehow access from the outside you will not be able to patch anything at runtime.

Since your class is public and the field is public as well there is no reason to use reflection or unsafe code at all. But I guess this class is not the actual one you are struggling with.

You can use reflection to find out about the class layout but at some point you need to hard code which field you actually want to patch. For this you can use the layout information gained from reflection and then determine the address at runtime. You need to get the FieldOffset attribute value of the field and then use this as pointer offset to get it.

Please note that the array MyFixedBuffer is not a real array in the struct since it is embedded in the struct. The usual object pointer GetType things will not work since the array is not managed but a fixed size buffer which has no MT (Method Table pointer) at all. At this point you need to deal with the raw offsets and patch in the bytes you are after.

Below is an example which uses reflection if you want to know how to deal with any value type if you want to build something dynamic which uses value types or e.g. a serializer.

[StructLayout(LayoutKind.Explicit, Pack = 1)]
public unsafe struct MyStruct
{

    [FieldOffset(6)]
    public fixed ushort MyFixedBuffer[28];

    [FieldOffset(62)]
    public byte Next;
}

class Program
{
    unsafe static void Main(string[] args)
    {
        var field = typeof(MyStruct).GetField("MyFixedBuffer");
        int offset = field.CustomAttributes.Where(x => x.AttributeType.Equals(typeof(FieldOffsetAttribute)))
                                                .SelectMany(x => x.ConstructorArguments)
                                                .Select(x => x.Value)
                                                .Cast<int>()
                                                .First();

        KeyValuePair<Type,int> fixedBufferDescription = field.CustomAttributes.Where(x => x.AttributeType.Equals(typeof(FixedBufferAttribute)))
                                                   .Select(x => x.ConstructorArguments)
                                                   .Select(x => new KeyValuePair<Type, int>((Type)x[0].Value, (int)x[1].Value))
                                                   .First();

        int fixedBuferLen = Marshal.SizeOf(fixedBufferDescription.Key) * fixedBufferDescription.Value;


        MyStruct tmp = new MyStruct();
        byte* raw = (byte*) &tmp;
        short* pmyArray = (short *) (raw + offset);

        for (int i = 0; i < fixedBuferLen/Marshal.SizeOf(fixedBufferDescription.Key); i++)
        {
            *(pmyArray + i) = (short) i;
        }

    }
}

That should do the trick.

like image 62
Alois Kraus Avatar answered Aug 02 '26 02:08

Alois Kraus



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!