Fix exception when writing null/empty array to EventSource
authorstephentoub <stoub@microsoft.com>
Sat, 7 Nov 2015 06:46:02 +0000 (22:46 -0800)
committerstephentoub <stoub@microsoft.com>
Sat, 7 Nov 2015 06:56:00 +0000 (22:56 -0800)
EventSource has two WriteEvent overloads that take a byte[].  If the
byte[] provided is null, it uses an empty array.  It then tries to get the
address of the 0th element of the array, resulting in an
IndexOutOfRangeException.  We could instead just use ```byte* blob =
arg1``` instead of ```byte* blob = &arg1[0]```, but doing so with an empty
array has undefined behavior in C#.  Instead, we just special-case null
and empty arrays.

src/mscorlib/src/System/Diagnostics/Eventing/EventSource.cs

index 1fc9a52..80a7a47 100644 (file)
@@ -1055,17 +1055,28 @@ namespace System.Diagnostics.Tracing
         {
             if (m_eventSourceEnabled)
             {
-                if (arg1 == null) arg1 = Array.Empty<byte>();
-                int blobSize = arg1.Length;
-                fixed (byte* blob = &arg1[0])
+                EventSource.EventData* descrs = stackalloc EventSource.EventData[2];
+                if (arg1 == null || arg1.Length == 0)
                 {
-                    EventSource.EventData* descrs = stackalloc EventSource.EventData[2];
+                    int blobSize = 0;
                     descrs[0].DataPointer = (IntPtr)(&blobSize);
                     descrs[0].Size = 4;
-                    descrs[1].DataPointer = (IntPtr)blob;
-                    descrs[1].Size = blobSize;
+                    descrs[1].DataPointer = (IntPtr)(&blobSize); // valid address instead of empty content
+                    descrs[1].Size = 0;
                     WriteEventCore(eventId, 2, descrs);
                 }
+                else
+                {
+                    int blobSize = arg1.Length;
+                    fixed (byte* blob = &arg1[0])
+                    {
+                        descrs[0].DataPointer = (IntPtr)(&blobSize);
+                        descrs[0].Size = 4;
+                        descrs[1].DataPointer = (IntPtr)blob;
+                        descrs[1].Size = blobSize;
+                        WriteEventCore(eventId, 2, descrs);
+                    }
+                }
             }
         }
 
@@ -1075,19 +1086,30 @@ namespace System.Diagnostics.Tracing
         {
             if (m_eventSourceEnabled)
             {
-                if (arg2 == null) arg2 = Array.Empty<byte>();
-                int blobSize = arg2.Length;
-                fixed (byte* blob = &arg2[0])
+                EventSource.EventData* descrs = stackalloc EventSource.EventData[3];
+                descrs[0].DataPointer = (IntPtr)(&arg1);
+                descrs[0].Size = 8;
+                if (arg2 == null || arg2.Length == 0)
                 {
-                    EventSource.EventData* descrs = stackalloc EventSource.EventData[3];
-                    descrs[0].DataPointer = (IntPtr)(&arg1);
-                    descrs[0].Size = 8;
+                    int blobSize = 0;
                     descrs[1].DataPointer = (IntPtr)(&blobSize);
                     descrs[1].Size = 4;
-                    descrs[2].DataPointer = (IntPtr)blob;
-                    descrs[2].Size = blobSize;
+                    descrs[2].DataPointer = (IntPtr)(&blobSize); // valid address instead of empty contents
+                    descrs[2].Size = 0;
                     WriteEventCore(eventId, 3, descrs);
                 }
+                else
+                {
+                    int blobSize = arg2.Length;
+                    fixed (byte* blob = &arg2[0])
+                    {
+                        descrs[1].DataPointer = (IntPtr)(&blobSize);
+                        descrs[1].Size = 4;
+                        descrs[2].DataPointer = (IntPtr)blob;
+                        descrs[2].Size = blobSize;
+                        WriteEventCore(eventId, 3, descrs);
+                    }
+                }
             }
         }