dotnet / wcf

This repo contains the client-oriented WCF libraries that enable applications built on .NET Core to communicate with WCF services.
MIT License
1.7k stars 559 forks source link

EtwDiagnosticTrace throw exception if fault message contains certain Unicode characters #5583

Open stefanegli opened 2 months ago

stefanegli commented 2 months ago

Describe the bug A returned fault containing a record separator () causes an exception in EtwDiagnosticTrace.ExceptionToTraceString(), which hides the fault from the client.

To Reproduce Call a wcf service that returns a fault with a message containing a record separator. Instead of the fault an InvalidOperationException is thrown:

   System.InvalidOperationException: The Writer is closed or in error state.
   at System.Xml.XmlWellFormedWriter.AdvanceState(Token token)
   at System.Xml.XmlWellFormedWriter.WriteEndElement()
   at System.Runtime.Diagnostics.EtwDiagnosticTrace.WriteExceptionToTraceString(XmlWriter xml, Exception exception, Int32 remainingLength, Int32 remainingAllowedRecursionDepth)
   at System.Runtime.Diagnostics.EtwDiagnosticTrace.ExceptionToTraceString(Exception exception, Int32 maxTraceStringLength)
   at System.Runtime.ExceptionTrace.TraceEtwException(Exception exception, EventLevel eventLevel)
   at System.ServiceModel.Diagnostics.ExceptionUtility.ThrowHelper(Exception exception, EventLevel eventLevel)
   at System.ServiceModel.Diagnostics.ExceptionUtility.ThrowHelperWarning(Exception exception)
   at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
   at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
   at System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.<>c__DisplayClass1_0.<CreateGenericTask>b__0(IAsyncResult asyncResult)

Expected behavior A FaultException based on the returned fault is thrown.

Additional context The same faults can be processed without any problem in .NET48

mconnew commented 2 months ago

We can fix this with the sledgehammer approach and simply catch any exception that gets thrown while trying to log this, but for me that leaves a bad taste. Can you confirm that the fault looks like a regular fault other than having the record separator character in the fault message? Something like that should get XML encoded so I'd like to work out why the XML writer is getting into a bad state instead of doing something sensible.
The difference between .NET and .NET Framework is the type of XmlWriter being used is different. The one used in .NET is supposed to be stricter conforming to the XML spec and do the right thing more. The one used in .NET Framework has a history of letting characters through and written into the XML so creating an invalid XML document.

stefanegli commented 2 months ago

The fault looks like all the other faults but as soon as a record separator is in the message, it causes the Exception during logging.

I tried to create a reproduction of the problem (with some reflection code, because the tracing classes are internal) but so far I was unable to create a fault exception that would demonstrate my problem...

One thing I did wonder though: Why is this kind of tracing enabled by default and why does there not seem to be a way to disable it?

stefanegli commented 2 months ago

I managed to create a reproduction of the problem. The solution has wcfCore Service and a simple client and if you run both projects at the same time the client receives a "writer is in closed state" exception.

The server creates a rather harmless looking fault: throw new FaultException("TypeNotActive,\u001e2,Z" + value);

Wcf.zip