From 44a89dd6dc7864822ddb48d030af519160de90a2 Mon Sep 17 00:00:00 2001 From: Yusuke Tanaka Date: Tue, 18 Oct 2022 11:28:27 +0900 Subject: fix(ext/net): return an error from `startTls` and `serveHttp` if the original connection is captured elsewhere (#16242) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit removes the calls to `expect()` on `std::rc::Rc`, which caused Deno to panic under certain situations. We now return an error if `Rc` is referenced by other variables. Fixes #9360 Fixes #13345 Fixes #13926 Fixes #16241 Co-authored-by: Bartek IwaƄczuk --- cli/tests/unit/http_test.ts | 80 +++++++++++++++++++++++++++++++++++++++++++++ cli/tests/unit/tls_test.ts | 27 +++++++++++++++ 2 files changed, 107 insertions(+) (limited to 'cli/tests') diff --git a/cli/tests/unit/http_test.ts b/cli/tests/unit/http_test.ts index 63eae3ace..566efce6d 100644 --- a/cli/tests/unit/http_test.ts +++ b/cli/tests/unit/http_test.ts @@ -2373,6 +2373,86 @@ Deno.test( }, ); +Deno.test( + { + permissions: { net: true }, + }, + async function httpServerWithoutExclusiveAccessToTcp() { + const port = 4506; + const listener = Deno.listen({ port }); + + const [clientConn, serverConn] = await Promise.all([ + Deno.connect({ port }), + listener.accept(), + ]); + + const buf = new Uint8Array(128); + const readPromise = serverConn.read(buf); + assertThrows(() => Deno.serveHttp(serverConn), Deno.errors.BadResource); + + clientConn.close(); + listener.close(); + await readPromise; + }, +); + +Deno.test( + { + permissions: { net: true, read: true }, + }, + async function httpServerWithoutExclusiveAccessToTls() { + const hostname = "localhost"; + const port = 4507; + const listener = Deno.listenTls({ + hostname, + port, + certFile: "cli/tests/testdata/tls/localhost.crt", + keyFile: "cli/tests/testdata/tls/localhost.key", + }); + + const caCerts = [ + await Deno.readTextFile("cli/tests/testdata/tls/RootCA.pem"), + ]; + const [clientConn, serverConn] = await Promise.all([ + Deno.connectTls({ hostname, port, caCerts }), + listener.accept(), + ]); + await Promise.all([clientConn.handshake(), serverConn.handshake()]); + + const buf = new Uint8Array(128); + const readPromise = serverConn.read(buf); + assertThrows(() => Deno.serveHttp(serverConn), Deno.errors.BadResource); + + clientConn.close(); + listener.close(); + await readPromise; + }, +); + +Deno.test( + { + ignore: Deno.build.os === "windows", + permissions: { read: true, write: true }, + }, + async function httpServerWithoutExclusiveAccessToUnixSocket() { + const filePath = await Deno.makeTempFile(); + const listener = Deno.listen({ path: filePath, transport: "unix" }); + + const [clientConn, serverConn] = await Promise.all([ + Deno.connect({ path: filePath, transport: "unix" }), + listener.accept(), + ]); + + const buf = new Uint8Array(128); + const readPromise = serverConn.read(buf); + assertThrows(() => Deno.serveHttp(serverConn), Deno.errors.BadResource); + + clientConn.close(); + listener.close(); + await readPromise; + }, +); + function chunkedBodyReader(h: Headers, r: BufReader): Deno.Reader { // Based on https://tools.ietf.org/html/rfc2616#section-19.4.6 const tp = new TextProtoReader(r); diff --git a/cli/tests/unit/tls_test.ts b/cli/tests/unit/tls_test.ts index cf335de49..860965e49 100644 --- a/cli/tests/unit/tls_test.ts +++ b/cli/tests/unit/tls_test.ts @@ -147,6 +147,33 @@ Deno.test( }, ); +Deno.test( + { permissions: { net: true } }, + async function startTlsWithoutExclusiveAccessToTcpConn() { + const hostname = "localhost"; + const port = getPort(); + + const tcpListener = Deno.listen({ hostname, port }); + const [serverConn, clientConn] = await Promise.all([ + tcpListener.accept(), + Deno.connect({ hostname, port }), + ]); + + const buf = new Uint8Array(128); + const readPromise = clientConn.read(buf); + // `clientConn` is being used by a pending promise (`readPromise`) so + // `Deno.startTls` cannot consume the connection. + await assertRejects( + () => Deno.startTls(clientConn, { hostname }), + Deno.errors.BadResource, + ); + + serverConn.close(); + tcpListener.close(); + await readPromise; + }, +); + Deno.test( { permissions: { read: true, net: true } }, async function dialAndListenTLS() { -- cgit v1.2.3