wcf icon indicating copy to clipboard operation
wcf copied to clipboard

NRE when response has Content-Type but empty body

Open IGx89 opened this issue 7 years ago • 8 comments

When a SOAP service returns no content but has a Content-Type set, WCF throws a NullReferenceException in HttpResponseMessageHelper. Leaving off Content-Type works fine.

Example HTTP response that reproduces the issue

HTTP/1.1 500
Content-Length: 0
Content-Type: text/xml; charset=UTF-8
Date: Thu, 05 Jul 2018 21:10:34 GMT
Connection: close

Expected Result

System.ServiceModel.CommunicationException : The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error."

Actual Result

System.NullReferenceException : Object reference not set to an instance of an object.

The NRE happens due to inputStream being null in HttpResponseMessageHelper.DecodeBufferedMessageAsync when it attempts to dispose it in the finally block.

The root cause however looks to be in ValidateContentTypeAsync. It doesn't properly handle this situation. It returns true (last line in the method) if the content type has a value and content length is 0, when it should be returning false. Its return value is saved in a hasContent variable in ParseIncomingResponse, so it definitely looks like it should be returning false if there's no content.

IGx89 avatar Jul 05 '18 21:07 IGx89

Thanks for reporting this @IGx89 we'll have someone take a look next week.

StephenBonikowsky avatar Jul 13 '18 21:07 StephenBonikowsky

Would it be possible to fix this bug anytime soon? Since it is a very trivial fix and we'd like to avoid using our own custom build. The patch for the fix is below.

diff --git a/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/HttpResponseMessageHelper.cs b/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/HttpResponseMessageHelper.cs
index 0c580539..f8407996 100644
--- a/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/HttpResponseMessageHelper.cs
+++ b/src/System.Private.ServiceModel/src/System/ServiceModel/Channels/HttpResponseMessageHelper.cs
@@ -42,6 +42,7 @@ namespace System.ServiceModel.Channels
             bool hasContent = await ValidateContentTypeAsync();
             Message message = null;
 
+
             if (!hasContent)
             {
                 if (_encoder.MessageVersion == MessageVersion.None)
@@ -136,6 +137,11 @@ namespace System.ServiceModel.Channels
                 _contentLength = content.Headers.ContentLength.HasValue ? content.Headers.ContentLength.Value : -1;
             }
 
+            if (content == null || _contentLength == 0)
+            {
+                return false;
+            }
+
             if (string.IsNullOrEmpty(_contentType))
             {
                 Stream contentStream = await GetStreamAsync();

skyflyer avatar Mar 05 '19 09:03 skyflyer

@Lxiamail, when is this likely to be addressed? (I've just tested with the 4.7.0 version as I've seen the code has been changed and it seems to be working, so perhaps this one is not even an issue)

skyflyer avatar Feb 05 '20 08:02 skyflyer

@mconnew did this issue get fixed as a side-effect of PR #3709?

StephenBonikowsky avatar Feb 05 '20 18:02 StephenBonikowsky

@StephenBonikowsky, unfortunately no.

mconnew avatar Feb 05 '20 21:02 mconnew

This looks like it would be a simple fix. We should consider it for 5.0.

StephenBonikowsky avatar Feb 05 '20 22:02 StephenBonikowsky

Got a similar issue / identical exception in v4.8.1.

In my case, invoking an async operation, who's operation contract is marked as IsOneWay = true, but the server was returning Content-Type: application/soap+xml; charset=utf-8, with no body, which seems to be throwing things off.

System.NullReferenceException : Object reference not set to an instance of an object.

   at System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result)
   at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result)
   at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
   at System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.<>c__DisplayClass2_0.<CreateTask>b__0(IAsyncResult asyncResult)
--- End of stack trace from previous location ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Acme.Client.<Boom>d__2.MoveNext() in code\Client.cs:line 133

RuaidhriMcDonnell avatar Aug 10 '21 11:08 RuaidhriMcDonnell

Got a similar issue / identical exception in v4.8.1.

In my case, invoking an async operation, who's operation contract is marked as IsOneWay = true, but the server was returning Content-Type: application/soap+xml; charset=utf-8, with no body, which seems to be throwing things off.

System.NullReferenceException : Object reference not set to an instance of an object.

   at System.Runtime.AsyncResult.End[TAsyncResult](IAsyncResult result)
   at System.ServiceModel.Channels.ServiceChannel.SendAsyncResult.End(SendAsyncResult result)
   at System.ServiceModel.Channels.ServiceChannel.EndCall(String action, Object[] outs, IAsyncResult result)
   at System.ServiceModel.Channels.ServiceChannelProxy.TaskCreator.<>c__DisplayClass2_0.<CreateTask>b__0(IAsyncResult asyncResult)
--- End of stack trace from previous location ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at Acme.Client.<Boom>d__2.MoveNext() in code\Client.cs:line 133

Getting the exact same issue here. Found a workaround?

tehZeno avatar Jun 30 '22 09:06 tehZeno