mirror of
https://github.com/denoland/deno.git
synced 2024-12-21 23:04:45 -05:00
fix(ext/net): validate port in Deno.{connect,serve,listen} (#24399)
Co-authored-by: Will Leach <4619280+melbourne2991@users.noreply.github.com> Co-authored-by: Luca Casonato <hello@lcas.dev> Co-authored-by: David Sherret <dsherret@gmail.com>
This commit is contained in:
parent
37279e0b0a
commit
a3a54bc747
3 changed files with 113 additions and 6 deletions
|
@ -33,9 +33,12 @@ const UDP_DGRAM_MAXSIZE = 65507;
|
|||
const {
|
||||
Error,
|
||||
Number,
|
||||
NumberIsNaN,
|
||||
NumberIsInteger,
|
||||
ObjectPrototypeIsPrototypeOf,
|
||||
ObjectDefineProperty,
|
||||
PromiseResolve,
|
||||
RangeError,
|
||||
SafeSet,
|
||||
SetPrototypeAdd,
|
||||
SetPrototypeDelete,
|
||||
|
@ -531,10 +534,11 @@ const listenOptionApiName = Symbol("listenOptionApiName");
|
|||
function listen(args) {
|
||||
switch (args.transport ?? "tcp") {
|
||||
case "tcp": {
|
||||
const port = validatePort(args.port);
|
||||
const { 0: rid, 1: addr } = op_net_listen_tcp(
|
||||
{
|
||||
hostname: args.hostname ?? "0.0.0.0",
|
||||
port: Number(args.port),
|
||||
port,
|
||||
},
|
||||
args.reusePort,
|
||||
args.loadBalanced ?? false,
|
||||
|
@ -558,14 +562,33 @@ function listen(args) {
|
|||
}
|
||||
}
|
||||
|
||||
function validatePort(maybePort) {
|
||||
if (typeof maybePort !== "number" && typeof maybePort !== "string") {
|
||||
throw new TypeError(`Invalid port (expected number): ${maybePort}`);
|
||||
}
|
||||
if (maybePort === "") throw new TypeError("Invalid port: ''");
|
||||
const port = Number(maybePort);
|
||||
if (!NumberIsInteger(port)) {
|
||||
if (NumberIsNaN(port) && !NumberIsNaN(maybePort)) {
|
||||
throw new TypeError(`Invalid port: '${maybePort}'`);
|
||||
} else {
|
||||
throw new TypeError(`Invalid port: ${maybePort}`);
|
||||
}
|
||||
} else if (port < 0 || port > 65535) {
|
||||
throw new RangeError(`Invalid port (out of range): ${maybePort}`);
|
||||
}
|
||||
return port;
|
||||
}
|
||||
|
||||
function createListenDatagram(udpOpFn, unixOpFn) {
|
||||
return function listenDatagram(args) {
|
||||
switch (args.transport) {
|
||||
case "udp": {
|
||||
const port = validatePort(args.port);
|
||||
const { 0: rid, 1: addr } = udpOpFn(
|
||||
{
|
||||
hostname: args.hostname ?? "127.0.0.1",
|
||||
port: args.port,
|
||||
port,
|
||||
},
|
||||
args.reuseAddress ?? false,
|
||||
args.loopback ?? false,
|
||||
|
@ -590,10 +613,11 @@ function createListenDatagram(udpOpFn, unixOpFn) {
|
|||
async function connect(args) {
|
||||
switch (args.transport ?? "tcp") {
|
||||
case "tcp": {
|
||||
const port = validatePort(args.port);
|
||||
const { 0: rid, 1: localAddr, 2: remoteAddr } = await op_net_connect_tcp(
|
||||
{
|
||||
hostname: args.hostname ?? "127.0.0.1",
|
||||
port: args.port,
|
||||
port,
|
||||
},
|
||||
);
|
||||
localAddr.transport = "tcp";
|
||||
|
@ -626,4 +650,5 @@ export {
|
|||
shutdown,
|
||||
TcpConn,
|
||||
UnixConn,
|
||||
validatePort,
|
||||
};
|
||||
|
|
|
@ -17,13 +17,12 @@ import {
|
|||
op_tls_start,
|
||||
} from "ext:core/ops";
|
||||
const {
|
||||
Number,
|
||||
ObjectDefineProperty,
|
||||
TypeError,
|
||||
SymbolFor,
|
||||
} = primordials;
|
||||
|
||||
import { Conn, Listener } from "ext:deno_net/01_net.js";
|
||||
import { Conn, Listener, validatePort } from "ext:deno_net/01_net.js";
|
||||
|
||||
class TlsConn extends Conn {
|
||||
#rid = 0;
|
||||
|
@ -259,6 +258,7 @@ function listenTls({
|
|||
if (transport !== "tcp") {
|
||||
throw new TypeError(`Unsupported transport: '${transport}'`);
|
||||
}
|
||||
port = validatePort(port);
|
||||
|
||||
if (!hasTlsKeyPairOptions(arguments[0])) {
|
||||
throw new TypeError(
|
||||
|
@ -267,7 +267,7 @@ function listenTls({
|
|||
}
|
||||
const keyPair = loadTlsKeyPair("Deno.listenTls", arguments[0]);
|
||||
const { 0: rid, 1: localAddr } = op_net_listen_tls(
|
||||
{ hostname, port: Number(port) },
|
||||
{ hostname, port },
|
||||
{ alpnProtocols, reusePort },
|
||||
keyPair,
|
||||
);
|
||||
|
|
|
@ -861,6 +861,88 @@ Deno.test(
|
|||
},
|
||||
);
|
||||
|
||||
Deno.test({ permissions: { net: true } }, async function validPortString() {
|
||||
const server = Deno.serve({
|
||||
handler: (_request) => new Response(),
|
||||
port: "4501" as unknown as number,
|
||||
});
|
||||
assertEquals(server.addr.transport, "tcp");
|
||||
assertEquals(server.addr.port, 4501);
|
||||
await server.shutdown();
|
||||
});
|
||||
|
||||
Deno.test({ permissions: { net: true } }, function invalidPortFloat() {
|
||||
assertThrows(
|
||||
() =>
|
||||
Deno.serve({
|
||||
handler: (_request) => new Response(),
|
||||
port: 45.1,
|
||||
}),
|
||||
TypeError,
|
||||
`Invalid port: 45.1`,
|
||||
);
|
||||
});
|
||||
|
||||
Deno.test({ permissions: { net: true } }, function invalidPortNaN() {
|
||||
assertThrows(
|
||||
() =>
|
||||
Deno.serve({
|
||||
handler: (_request) => new Response(),
|
||||
port: NaN,
|
||||
}),
|
||||
TypeError,
|
||||
`Invalid port: NaN`,
|
||||
);
|
||||
});
|
||||
|
||||
Deno.test({ permissions: { net: true } }, function invalidPortString() {
|
||||
assertThrows(
|
||||
() =>
|
||||
Deno.serve({
|
||||
handler: (_request) => new Response(),
|
||||
port: "some-non-number-string" as unknown as number,
|
||||
}),
|
||||
TypeError,
|
||||
`Invalid port: 'some-non-number-string'`,
|
||||
);
|
||||
});
|
||||
|
||||
Deno.test({ permissions: { net: true } }, function invalidPortTooSmall() {
|
||||
assertThrows(
|
||||
() =>
|
||||
Deno.serve({
|
||||
handler: (_request) => new Response(),
|
||||
port: -111,
|
||||
}),
|
||||
RangeError,
|
||||
`Invalid port (out of range): -111`,
|
||||
);
|
||||
});
|
||||
|
||||
Deno.test({ permissions: { net: true } }, function invalidPortTooLarge() {
|
||||
assertThrows(
|
||||
() =>
|
||||
Deno.serve({
|
||||
handler: (_request) => new Response(),
|
||||
port: 100000,
|
||||
}),
|
||||
RangeError,
|
||||
`Invalid port (out of range): 100000`,
|
||||
);
|
||||
});
|
||||
|
||||
Deno.test({ permissions: { net: true } }, function invalidPortType() {
|
||||
assertThrows(
|
||||
() =>
|
||||
Deno.serve({
|
||||
handler: (_request) => new Response(),
|
||||
port: true as unknown as number,
|
||||
}),
|
||||
TypeError,
|
||||
`Invalid port (expected number): true`,
|
||||
);
|
||||
});
|
||||
|
||||
function createUrlTest(
|
||||
name: string,
|
||||
methodAndPath: string,
|
||||
|
|
Loading…
Reference in a new issue