Skip to content

Strings with embedded nulls cause issues with event payload decoding #52025

@josalem

Description

@josalem

Manifest driven EventSources mark all strings as win:UnicodeString in the manifest. This is interpreted by TraceEvent and other pieces of tracing infrastructure as "a null-terminated string". There is a separate type for "counted strings" that isn't used by EventSource.

C#, however, allows for embedded nulls in strings, and String.Length will give the full length of string including the embedded nulls.

EventSource uses String.Length when it is encoding strings, e.g.,

descrs[1].DataPointer = (IntPtr)string2Bytes;
descrs[1].Size = ((arg2.Length + 1) * 2);
descrs[1].Reserved = 0;

This can lead to problems for the parser if there are things in the payload after the string. For example:

public class MySource : EventSource
{
    public static MySource Instance = new MySource();

    public void MyEvent(int foo, string bar, int baz) => WriteEvent(1, foo, bar, baz);
}

// ...

var myString = "aaa$bbb";
myString = myString.Replace('$', '\0');
MySource.Instance.MyEvent(10, myString, -10);

will result in the following at the reader end:
image

The event contains the full data:

<Event MSec=  "4096.7191" PID="24292" PName="EventSourceNullContent" TID="31320" EventName="MyEvent"
  TimeStamp="04/26/21 17:14:07.575276" ID="1" Version="0" Keywords="0x0000F00000000000" TimeStampQPC="9,698,287,562,667" QPCTime="0.100us"
  Level="Informational" ProviderName="MySource" ProviderGuid="a61ea624-4944-55fc-c2a8-37838829438d" ClassicProvider="False" ProcessorNumber="7"
  Opcode="0" Task="65533" Channel="0" PointerSize="8"
  CPU="7" EventIndex="70874" TemplateType="DynamicTraceEventData">
  <PrettyPrint>
    <Event MSec=  "4096.7191" PID="24292" PName="EventSourceNullContent" TID="31320" EventName="MyEvent" ProviderName="MySource" foo="10" bar="aaa" baz="6,422,626"/>
  </PrettyPrint>
  <Payload Length="24">
       0:   a  0  0  0 61  0 61  0 | 61  0  0  0 62  0 62  0   ....a.a. a...b.b.
      10:  62  0  0  0 f6 ff ff ff |                           b....... 
  </Payload>
</Event>

TraceEvent attempts to read a null terminated string, and then interprets the next 4 bytes as the baz parameter which is incorrect.

A potential solution would be to truncate input strings to the first null encountered. I imagine this is a very rare occurrence and the overhead of running String.IndexOf((char)0) should be minimal for the common use case. We could also push and out of band message that an event payload string was truncated.

CC @sywhang @noahfalk

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions