-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Description
When adding nullable annotations for System.Net.Sockets (#32675), it was discovered that there is a scenario when using NamedPipeClientStream can use a null string:
When calling NamedPipeClientStream.Connect on Unix, it will try using the _normalizedPipePath string:
runtime/src/libraries/System.IO.Pipes/src/System/IO/Pipes/NamedPipeClientStream.Unix.cs
Lines 21 to 31 in 032e8db
| private bool TryConnect(int timeout, CancellationToken cancellationToken) | |
| { | |
| // timeout and cancellationToken aren't used as Connect will be very fast, | |
| // either succeeding immediately if the server is listening or failing | |
| // immediately if it isn't. The only delay will be between the time the server | |
| // has called Bind and Listen, with the latter immediately following the former. | |
| var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified); | |
| SafePipeHandle? clientHandle = null; | |
| try | |
| { | |
| socket.Connect(new UnixDomainSocketEndPoint(_normalizedPipePath)); |
However, if the NamedPipeClientStream object was created with the constructor that takes an existing SafePipeHandle and isConnected: false, then _normalizedPipePath will be null.
runtime/src/libraries/System.IO.Pipes/src/System/IO/Pipes/NamedPipeClientStream.cs
Lines 101 to 103 in 032e8db
| public NamedPipeClientStream(PipeDirection direction, bool isAsync, bool isConnected, SafePipeHandle safePipeHandle) | |
| : base(direction, 0) | |
| { |
Doing some searching, I'm honestly not certain how this scenario (existing SafePipeHandle and isConnected: false) can ever work successfully. It will need a path to be able to connect to, which it wasn't given. So at best we may be able to throw a better exception than the ArgumentNullException we get:
Unhandled exception. System.ArgumentNullException: Value cannot be null. (Parameter 'path')
at System.Net.Sockets.UnixDomainSocketEndPoint..ctor(String path)
at System.IO.Pipes.NamedPipeClientStream.TryConnect(Int32 timeout, CancellationToken cancellationToken)
at System.IO.Pipes.NamedPipeClientStream.ConnectInternal(Int32 timeout, CancellationToken cancellationToken, Int32 startTime)
at System.IO.Pipes.NamedPipeClientStream.Connect(Int32 timeout)
at System.IO.Pipes.NamedPipeClientStream.Connect()
/cc @stephentoub