From 2c990414bf51459869090d3b802086bbd19b3f68 Mon Sep 17 00:00:00 2001 From: Marcos Casagrande Date: Mon, 8 Jun 2020 17:58:52 +0200 Subject: [PATCH] fix(std/http): Prevent crash on UnexpectedEof and InvalidData (#6155) --- std/http/server.ts | 8 +++-- std/http/server_test.ts | 70 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 2 deletions(-) diff --git a/std/http/server.ts b/std/http/server.ts index 3cc95a9e49..18bfc4731d 100644 --- a/std/http/server.ts +++ b/std/http/server.ts @@ -211,8 +211,12 @@ export class Server implements AsyncIterable { try { conn = await this.listener.accept(); } catch (error) { - if (error instanceof Deno.errors.BadResource) { - return; + if ( + error instanceof Deno.errors.BadResource || + error instanceof Deno.errors.InvalidData || + error instanceof Deno.errors.UnexpectedEof + ) { + return mux.add(this.acceptConnAndIterateHttpRequests(mux)); } throw error; } diff --git a/std/http/server_test.ts b/std/http/server_test.ts index 52cd8c5393..93b117059b 100644 --- a/std/http/server_test.ts +++ b/std/http/server_test.ts @@ -545,3 +545,73 @@ test({ assert((await entry).done); }, }); + +test({ + name: "serveTLS Invalid Cert", + fn: async (): Promise => { + // Runs a simple server as another process + const p = Deno.run({ + cmd: [ + Deno.execPath(), + "run", + "--allow-net", + "--allow-read", + "http/testdata/simple_https_server.ts", + ], + stdout: "piped", + }); + + let serverIsRunning = true; + const statusPromise = p + .status() + .then((): void => { + serverIsRunning = false; + }) + .catch((_): void => {}); // Ignores the error when closing the process. + + try { + const r = new TextProtoReader(new BufReader(p.stdout!)); + const s = await r.readLine(); + assert( + s !== null && s.includes("server listening"), + "server must be started" + ); + // Invalid certificate, connection should throw + // but should not crash the server + assertThrowsAsync( + () => + Deno.connectTls({ + hostname: "localhost", + port: 4503, + // certFile + }), + Deno.errors.InvalidData + ); + + // Valid request after invalid + const conn = await Deno.connectTls({ + hostname: "localhost", + port: 4503, + certFile: "http/testdata/tls/RootCA.pem", + }); + + await Deno.writeAll( + conn, + new TextEncoder().encode("GET / HTTP/1.0\r\n\r\n") + ); + const res = new Uint8Array(100); + const nread = await conn.read(res); + assert(nread !== null); + conn.close(); + const resStr = new TextDecoder().decode(res.subarray(0, nread)); + assert(resStr.includes("Hello HTTPS")); + assert(serverIsRunning); + } finally { + // Stops the sever and allows `p.status()` promise to resolve + Deno.kill(p.pid, Deno.Signal.SIGKILL); + await statusPromise; + p.stdout!.close(); + p.close(); + } + }, +});