Bug with unsafe (fixed buffer) structs
ApocDev
Posts: 14
For performance reasons, we have a few structures that use fixed-buffer arrays to align padding, and provide quicker array access (via pointer usage) instead of the typical [MarshalAs] approach.
Example struct:
The above class is simply a cache for Marshal.SizeOf (its fairly slow on complex types, so we just pseudo-cache it with the static-generic trick)
In a console application:
However, if you run SA over the same console application, with literally zero options enabled, it will print "19". This is causing a ton of bugs in our application where we've done optimizations to reduce CPU usage.
Example struct:
[StructLayout(LayoutKind.Sequential, Pack=1)] unsafe struct Example { public IntPtr InternalEntries; public uint MaxEntries; private fixed byte padding8[8]; public uint NumEntries; private fixed byte padding14[4]; public IntPtr InternalEntriesSecond; private fixed byte padding1c [4]; }
public static class MarshalCache<T> { public static int Size; static MarshalCache() { if (typeof(T).IsEnum) { var underlying = typeof(T).GetEnumUnderlyingType(); Size = Marshal.SizeOf(underlying); } else Size = Marshal.SizeOf(typeof(T)); } }
The above class is simply a cache for Marshal.SizeOf (its fairly slow on complex types, so we just pseudo-cache it with the static-generic trick)
In a console application:
Console.WriteLine(MarshalCache<Example>.Size)The above will print "32" when built from VS. (Assuming x86 mode due to IntPtr changing between 4/8 bytes)
However, if you run SA over the same console application, with literally zero options enabled, it will print "19". This is causing a ton of bugs in our application where we've done optimizations to reduce CPU usage.
Comments
It would probably be important to let us know which protection options you are using so we can try to isolate which one may be interfering with this.
Not quite. The issue is with structure sizes. (The enum sanity check is due to Marshal.SizeOf not being able to determine the size of an enum, so we grab the underlying type (enum Foo: uint, will cause the underlying type to be uint, [4 bytes]))
The bug is with structs with fixed buffers. (public fixed byte Padding[50];)
This happens with zero protection options turned on. (Not even strong-name signing, or error reporting. No obfuscation, no pruning, no string encryption, etc)