From 5c90846c1b25e7f6bcce70980f630f90a98ccca0 Mon Sep 17 00:00:00 2001 From: Cory Benfield Date: Wed, 27 Jan 2021 14:37:00 +0000 Subject: [PATCH] Tolerate out-of-band ports. (#112) Motivation: We shouldn't crash if the user gives us a bad port. Modifications: - Check the ports are in-band before we move on. Result: We won't crash. --- .../NIOTSConnectionBootstrap.swift | 5 ++++ .../NIOTSListenerBootstrap.swift | 5 ++++ .../NIOTSBootstrapTests.swift | 27 +++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/Sources/NIOTransportServices/NIOTSConnectionBootstrap.swift b/Sources/NIOTransportServices/NIOTSConnectionBootstrap.swift index 9e5cea8..e580291 100644 --- a/Sources/NIOTransportServices/NIOTSConnectionBootstrap.swift +++ b/Sources/NIOTransportServices/NIOTSConnectionBootstrap.swift @@ -156,6 +156,11 @@ public final class NIOTSConnectionBootstrap { /// - port: The port to connect to. /// - returns: An `EventLoopFuture` to deliver the `Channel` when connected. public func connect(host: String, port: Int) -> EventLoopFuture { + let validPortRange = Int(UInt16.min)...Int(UInt16.max) + guard validPortRange.contains(port) else { + return self.group.next().makeFailedFuture(NIOTSErrors.InvalidPort(port: port)) + } + guard let actualPort = NWEndpoint.Port(rawValue: UInt16(port)) else { return self.group.next().makeFailedFuture(NIOTSErrors.InvalidPort(port: port)) } diff --git a/Sources/NIOTransportServices/NIOTSListenerBootstrap.swift b/Sources/NIOTransportServices/NIOTSListenerBootstrap.swift index 8dbe41b..fa0e312 100644 --- a/Sources/NIOTransportServices/NIOTSListenerBootstrap.swift +++ b/Sources/NIOTransportServices/NIOTSListenerBootstrap.swift @@ -249,6 +249,11 @@ public final class NIOTSListenerBootstrap { /// - host: The host to bind on. /// - port: The port to bind on. public func bind(host: String, port: Int) -> EventLoopFuture { + let validPortRange = Int(UInt16.min)...Int(UInt16.max) + guard validPortRange.contains(port) else { + return self.group.next().makeFailedFuture(NIOTSErrors.InvalidPort(port: port)) + } + return self.bind0 { (channel, promise) in do { // NWListener does not actually resolve hostname-based NWEndpoints diff --git a/Tests/NIOTransportServicesTests/NIOTSBootstrapTests.swift b/Tests/NIOTransportServicesTests/NIOTSBootstrapTests.swift index 7405ce9..94ec461 100644 --- a/Tests/NIOTransportServicesTests/NIOTSBootstrapTests.swift +++ b/Tests/NIOTransportServicesTests/NIOTSBootstrapTests.swift @@ -306,6 +306,33 @@ final class NIOTSBootstrapTests: XCTestCase { setValue: false, shortOption: .disableAutoRead) } + + func testBootstrapsErrorGracefullyOnOutOfBandPorts() throws { + let invalidPortNumbers = [-1, 65536] + + let group = NIOTSEventLoopGroup() + defer { + try! group.syncShutdownGracefully() + } + + let listenerBootstrap = NIOTSListenerBootstrap(group: group) + let connectionBootstrap = NIOTSConnectionBootstrap(group: group) + + for invalidPort in invalidPortNumbers { + var listenerChannel: Channel? + var connectionChannel: Channel? + + XCTAssertThrowsError(listenerChannel = try listenerBootstrap.bind(host: "localhost", port: invalidPort).wait()) { error in + XCTAssertNotNil(error as? NIOTSErrors.InvalidPort) + } + XCTAssertThrowsError(connectionChannel = try connectionBootstrap.connect(host: "localhost", port: invalidPort).wait()) { error in + XCTAssertNotNil(error as? NIOTSErrors.InvalidPort) + } + + try? listenerChannel?.close().wait() + try? connectionChannel?.close().wait() + } + } } extension Channel {