Fix ping bug on certain platforms

This commit is contained in:
Divya Jagadish authored and Zaid Abdulla committed 2022-04-08 13:01:05 -07:00
1 parent 7ccdbace70
commit 7941d929d2
2 files changed
+92 -46

No files matched your search

+56 -46
View File
@@ -40,68 +40,78 @@ function isValidHost(host: string): boolean {
return /^[a-zA-Z0-9\-.:[\]-]+$/.test(domainToASCII(host));
}
export function ping(
host: string,
callback: (err: Error, res?: PingResult, stdout?: string) => void
): void {
let cmd: string, parseRegExp1: RegExp, parseRegExp2: RegExp;
// Validate input to prevent possible remote code execution
// Credit to Alex Hordijk for reporting this vulnerability
if (!isValidHost(host)) return callback(new Error("Invalid host"));
host = host.replace("[", "").replace("]", "");
switch (platform()) {
export function parsePing(osPlatform: string, stdout: string): PingResult {
let parseRegExp1: RegExp, parseRegExp2: RegExp, parsed: PingResult;
switch (osPlatform) {
case "linux":
cmd = `ping -w 1 -i 0.2 -c 3 ${host}`;
parseRegExp1 =
/(\d+) packets transmitted, (\d+) received, ([\d.]+)% packet loss[^]*([\d.]+)\/([\d.]+)\/([\d.]+)\/([\d.]+)/;
/(\d+) packets transmitted, (\d+) .*received, ([\d.]+)% .*loss[^]*= ([\d.]+)\/([\d.]+)\/([\d.]+)\/([\d.]+)/;
parseRegExp2 =
/(\d+) packets transmitted, (\d+) received, ([\d.]+)% packet loss/;
/(\d+) packets transmitted, (\d+) .*received, ([\d.]+)% .*loss/;
break;
case "freebsd":
// Send a single packet because on FreeBSD only superuser can send
// packets that are only 200 ms apart.
cmd = `ping -t 1 -c 3 ${host}`;
parseRegExp1 =
/(\d+) packets transmitted, (\d+) packets received, ([\d.]+)% packet loss\nround-trip min\/avg\/max\/stddev = ([\d.]+)\/([\d.]+)\/([\d.]+)\/([\d.]+) ms/;
parseRegExp2 =
/(\d+) packets transmitted, (\d+) packets received, ([\d.]+)% packet loss/;
break;
}
const m1 = stdout.match(parseRegExp1);
if (m1) {
parsed = {
packetsTransmitted: +m1[1],
packetsReceived: +m1[2],
packetLoss: +m1[3],
min: +m1[4],
avg: +m1[5],
max: +m1[6],
mdev: +m1[7],
};
} else {
const m2 = stdout.match(parseRegExp2);
if (m2) {
parsed = {
packetsTransmitted: +m2[1],
packetsReceived: +m2[2],
packetLoss: +m2[3],
min: null,
avg: null,
max: null,
mdev: null,
};
}
}
return parsed;
}
export function ping(
host: string,
callback: (err: Error, res?: PingResult, stdout?: string) => void
): void {
// Validate input to prevent possible remote code execution
// Credit to Alex Hordijk for reporting this vulnerability
if (!isValidHost(host)) return callback(new Error("Invalid host"));
host = host.replace("[", "").replace("]", "");
let cmd: string;
switch (platform()) {
case "linux":
cmd = `ping -w 1 -i 0.2 -c 3 ${host}`;
break;
case "freebsd":
// Send a single packet because on FreeBSD only superuser can send
// packets that are only 200 ms apart.
cmd = `ping -t 1 -c 3 ${host}`;
break;
default:
return callback(new Error("Platform not supported"));
}
exec(cmd, (err, stdout) => {
let parsed: PingResult;
if (stdout) {
const m1 = stdout.match(parseRegExp1);
if (m1) {
parsed = {
packetsTransmitted: +m1[1],
packetsReceived: +m1[2],
packetLoss: +m1[3],
min: +m1[4],
avg: +m1[5],
max: +m1[6],
mdev: +m1[7],
};
} else {
const m2 = stdout.match(parseRegExp2);
if (m2) {
parsed = {
packetsTransmitted: +m2[1],
packetsReceived: +m2[2],
packetLoss: +m2[3],
min: null,
avg: null,
max: null,
mdev: null,
};
}
}
}
callback(err, parsed, stdout);
if (err) return callback(err);
const parsed: PingResult = parsePing(platform(), stdout);
return callback(err, parsed, stdout);
});
}
+36
View File
@@ -0,0 +1,36 @@
import ava from "ava";
import { parsePing } from "../lib/ping";
ava("linux Case-1", (t) => {
const platform = "linux";
const stdout =
"PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data\n64 bytes from 8.8.8.8: icmp_seq=1 ttl=118 time=6.66 ms\n64 bytes from 8.8.8.8: icmp_seq=2 ttl=118 time=6.50 ms\n64 bytes from 8.8.8.8: icmp_seq=3 ttl=118 time=6.38 ms\n\n--- 8.8.8.8 ping statistics ---\n3 packets transmitted, 3 received, 0% packet loss, time 402ms\nrtt min/avg/max/mdev = 6.381/6.511/6.656/0.112 ms";
const parsedResult = {
packetsTransmitted: 3,
packetsReceived: 3,
packetLoss: 0,
min: 6.381,
avg: 6.511,
max: 6.656,
mdev: 0.112,
};
const parsed = parsePing(platform, stdout);
t.deepEqual(parsedResult, parsed);
});
ava("linux Case-2", (t) => {
const platform = "linux";
const stdout =
"PING 10.251.9.108 (10.251.9.108): 56 data bytes\n64 bytes from 10.251.9.108: icmp_seq=0 ttl=57 time=36.758 ms\n64 bytes from 10.251.9.108: icmp_seq=1 ttl=57 time=69.094 ms\n64 bytes from 10.251.9.108: icmp_seq=2 ttl=57 time=28.868 ms\n--- 10.251.9.108 ping statistics ---3 packets transmitted, 3 packets received, 0% packet loss\nround-trip min/avg/max/stddev = 28.868/44.907/69.094/17.404 ms";
const parsedResult = {
packetsTransmitted: 3,
packetsReceived: 3,
packetLoss: 0,
min: 28.868,
avg: 44.907,
max: 69.094,
mdev: 17.404,
};
const parsed = parsePing(platform, stdout);
t.deepEqual(parsedResult, parsed);
});