Skip to content

Commit fa93369

Browse files
BrennanConroyJohn Luo
authored andcommitted
Fix null reference exception for Streaming null object (#14004) (#14515)
1 parent 00ebfb4 commit fa93369

File tree

3 files changed

+90
-1
lines changed

3 files changed

+90
-1
lines changed

src/SignalR/server/Core/src/Internal/DefaultHubDispatcher.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,8 @@ await SendInvocationError(hubMethodInvocationMessage.InvocationId, connection,
265265
for (var parameterPointer = 0; parameterPointer < arguments.Length; parameterPointer++)
266266
{
267267
if (hubMethodInvocationMessage.Arguments.Length > hubInvocationArgumentPointer &&
268-
descriptor.OriginalParameterTypes[parameterPointer].IsAssignableFrom(hubMethodInvocationMessage.Arguments[hubInvocationArgumentPointer].GetType()))
268+
(hubMethodInvocationMessage.Arguments[hubInvocationArgumentPointer] == null ||
269+
descriptor.OriginalParameterTypes[parameterPointer].IsAssignableFrom(hubMethodInvocationMessage.Arguments[hubInvocationArgumentPointer].GetType())))
269270
{
270271
// The types match so it isn't a synthetic argument, just copy it into the arguments array
271272
arguments[parameterPointer] = hubMethodInvocationMessage.Arguments[hubInvocationArgumentPointer];

src/SignalR/server/SignalR/test/HubConnectionHandlerTestUtils/Hubs.cs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,36 @@ public ChannelReader<int> CancelableStreamMultiParameter(int ignore, int ignore2
933933
return channel.Reader;
934934
}
935935

936+
public ChannelReader<int> CancelableStreamNullableParameter(int x, string y, CancellationToken token)
937+
{
938+
var channel = Channel.CreateBounded<int>(10);
939+
940+
Task.Run(async () =>
941+
{
942+
_tcsService.StartedMethod.SetResult(x);
943+
await token.WaitForCancellationAsync();
944+
channel.Writer.TryComplete();
945+
_tcsService.EndMethod.SetResult(y);
946+
});
947+
948+
return channel.Reader;
949+
}
950+
951+
public ChannelReader<int> StreamNullableParameter(int x, int? input)
952+
{
953+
var channel = Channel.CreateBounded<int>(10);
954+
955+
Task.Run(() =>
956+
{
957+
_tcsService.StartedMethod.SetResult(x);
958+
channel.Writer.TryComplete();
959+
_tcsService.EndMethod.SetResult(input);
960+
return Task.CompletedTask;
961+
});
962+
963+
return channel.Reader;
964+
}
965+
936966
public ChannelReader<int> CancelableStreamMiddleParameter(int ignore, CancellationToken token, int ignore2)
937967
{
938968
var channel = Channel.CreateBounded<int>(10);

src/SignalR/server/SignalR/test/HubConnectionHandlerTests.cs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3591,6 +3591,64 @@ public async Task StreamHubMethodCanAcceptCancellationTokenAsArgumentAndBeTrigge
35913591
}
35923592
}
35933593

3594+
[Fact]
3595+
public async Task StreamHubMethodCanAcceptNullableParameter()
3596+
{
3597+
using (StartVerifiableLog())
3598+
{
3599+
var tcsService = new TcsService();
3600+
var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(builder =>
3601+
{
3602+
builder.AddSingleton(tcsService);
3603+
}, LoggerFactory);
3604+
var connectionHandler = serviceProvider.GetService<HubConnectionHandler<LongRunningHub>>();
3605+
3606+
using (var client = new TestClient())
3607+
{
3608+
var connectionHandlerTask = await client.ConnectAsync(connectionHandler).OrTimeout();
3609+
3610+
var streamInvocationId = await client.SendStreamInvocationAsync(nameof(LongRunningHub.StreamNullableParameter), 5, null).OrTimeout();
3611+
// Wait for the stream method to start
3612+
var firstArgument = await tcsService.StartedMethod.Task.OrTimeout();
3613+
Assert.Equal(5, firstArgument);
3614+
3615+
var secondArgument = await tcsService.EndMethod.Task.OrTimeout();
3616+
Assert.Null(secondArgument);
3617+
}
3618+
}
3619+
}
3620+
3621+
3622+
[Fact]
3623+
public async Task StreamHubMethodCanAcceptNullableParameterWithCancellationToken()
3624+
{
3625+
using (StartVerifiableLog())
3626+
{
3627+
var tcsService = new TcsService();
3628+
var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(builder =>
3629+
{
3630+
builder.AddSingleton(tcsService);
3631+
}, LoggerFactory);
3632+
var connectionHandler = serviceProvider.GetService<HubConnectionHandler<LongRunningHub>>();
3633+
3634+
using (var client = new TestClient())
3635+
{
3636+
var connectionHandlerTask = await client.ConnectAsync(connectionHandler).OrTimeout();
3637+
3638+
var streamInvocationId = await client.SendStreamInvocationAsync(nameof(LongRunningHub.CancelableStreamNullableParameter), 5, null).OrTimeout();
3639+
// Wait for the stream method to start
3640+
var firstArgument = await tcsService.StartedMethod.Task.OrTimeout();
3641+
Assert.Equal(5, firstArgument);
3642+
3643+
// Cancel the stream which should trigger the CancellationToken in the hub method
3644+
await client.SendHubMessageAsync(new CancelInvocationMessage(streamInvocationId)).OrTimeout();
3645+
3646+
var secondArgument = await tcsService.EndMethod.Task.OrTimeout();
3647+
Assert.Null(secondArgument);
3648+
}
3649+
}
3650+
}
3651+
35943652
[Fact]
35953653
public async Task InvokeHubMethodCannotAcceptCancellationTokenAsArgument()
35963654
{

0 commit comments

Comments
 (0)