mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -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 {
|
const {
|
||||||
Error,
|
Error,
|
||||||
Number,
|
Number,
|
||||||
|
NumberIsNaN,
|
||||||
|
NumberIsInteger,
|
||||||
ObjectPrototypeIsPrototypeOf,
|
ObjectPrototypeIsPrototypeOf,
|
||||||
ObjectDefineProperty,
|
ObjectDefineProperty,
|
||||||
PromiseResolve,
|
PromiseResolve,
|
||||||
|
RangeError,
|
||||||
SafeSet,
|
SafeSet,
|
||||||
SetPrototypeAdd,
|
SetPrototypeAdd,
|
||||||
SetPrototypeDelete,
|
SetPrototypeDelete,
|
||||||
|
@ -531,10 +534,11 @@ const listenOptionApiName = Symbol("listenOptionApiName");
|
||||||
function listen(args) {
|
function listen(args) {
|
||||||
switch (args.transport ?? "tcp") {
|
switch (args.transport ?? "tcp") {
|
||||||
case "tcp": {
|
case "tcp": {
|
||||||
|
const port = validatePort(args.port);
|
||||||
const { 0: rid, 1: addr } = op_net_listen_tcp(
|
const { 0: rid, 1: addr } = op_net_listen_tcp(
|
||||||
{
|
{
|
||||||
hostname: args.hostname ?? "0.0.0.0",
|
hostname: args.hostname ?? "0.0.0.0",
|
||||||
port: Number(args.port),
|
port,
|
||||||
},
|
},
|
||||||
args.reusePort,
|
args.reusePort,
|
||||||
args.loadBalanced ?? false,
|
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) {
|
function createListenDatagram(udpOpFn, unixOpFn) {
|
||||||
return function listenDatagram(args) {
|
return function listenDatagram(args) {
|
||||||
switch (args.transport) {
|
switch (args.transport) {
|
||||||
case "udp": {
|
case "udp": {
|
||||||
|
const port = validatePort(args.port);
|
||||||
const { 0: rid, 1: addr } = udpOpFn(
|
const { 0: rid, 1: addr } = udpOpFn(
|
||||||
{
|
{
|
||||||
hostname: args.hostname ?? "127.0.0.1",
|
hostname: args.hostname ?? "127.0.0.1",
|
||||||
port: args.port,
|
port,
|
||||||
},
|
},
|
||||||
args.reuseAddress ?? false,
|
args.reuseAddress ?? false,
|
||||||
args.loopback ?? false,
|
args.loopback ?? false,
|
||||||
|
@ -590,10 +613,11 @@ function createListenDatagram(udpOpFn, unixOpFn) {
|
||||||
async function connect(args) {
|
async function connect(args) {
|
||||||
switch (args.transport ?? "tcp") {
|
switch (args.transport ?? "tcp") {
|
||||||
case "tcp": {
|
case "tcp": {
|
||||||
|
const port = validatePort(args.port);
|
||||||
const { 0: rid, 1: localAddr, 2: remoteAddr } = await op_net_connect_tcp(
|
const { 0: rid, 1: localAddr, 2: remoteAddr } = await op_net_connect_tcp(
|
||||||
{
|
{
|
||||||
hostname: args.hostname ?? "127.0.0.1",
|
hostname: args.hostname ?? "127.0.0.1",
|
||||||
port: args.port,
|
port,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
localAddr.transport = "tcp";
|
localAddr.transport = "tcp";
|
||||||
|
@ -626,4 +650,5 @@ export {
|
||||||
shutdown,
|
shutdown,
|
||||||
TcpConn,
|
TcpConn,
|
||||||
UnixConn,
|
UnixConn,
|
||||||
|
validatePort,
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,13 +17,12 @@ import {
|
||||||
op_tls_start,
|
op_tls_start,
|
||||||
} from "ext:core/ops";
|
} from "ext:core/ops";
|
||||||
const {
|
const {
|
||||||
Number,
|
|
||||||
ObjectDefineProperty,
|
ObjectDefineProperty,
|
||||||
TypeError,
|
TypeError,
|
||||||
SymbolFor,
|
SymbolFor,
|
||||||
} = primordials;
|
} = 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 {
|
class TlsConn extends Conn {
|
||||||
#rid = 0;
|
#rid = 0;
|
||||||
|
@ -259,6 +258,7 @@ function listenTls({
|
||||||
if (transport !== "tcp") {
|
if (transport !== "tcp") {
|
||||||
throw new TypeError(`Unsupported transport: '${transport}'`);
|
throw new TypeError(`Unsupported transport: '${transport}'`);
|
||||||
}
|
}
|
||||||
|
port = validatePort(port);
|
||||||
|
|
||||||
if (!hasTlsKeyPairOptions(arguments[0])) {
|
if (!hasTlsKeyPairOptions(arguments[0])) {
|
||||||
throw new TypeError(
|
throw new TypeError(
|
||||||
|
@ -267,7 +267,7 @@ function listenTls({
|
||||||
}
|
}
|
||||||
const keyPair = loadTlsKeyPair("Deno.listenTls", arguments[0]);
|
const keyPair = loadTlsKeyPair("Deno.listenTls", arguments[0]);
|
||||||
const { 0: rid, 1: localAddr } = op_net_listen_tls(
|
const { 0: rid, 1: localAddr } = op_net_listen_tls(
|
||||||
{ hostname, port: Number(port) },
|
{ hostname, port },
|
||||||
{ alpnProtocols, reusePort },
|
{ alpnProtocols, reusePort },
|
||||||
keyPair,
|
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(
|
function createUrlTest(
|
||||||
name: string,
|
name: string,
|
||||||
methodAndPath: string,
|
methodAndPath: string,
|
||||||
|
|
Loading…
Reference in a new issue