fix(ports): validate lsof PID parsing before assignment (#98371)

* fix(ports): validate lsof PID parsing before assignment

Add Number.isFinite guard on lsof 'p' line PID parsing in
parseLsofOutput, consistent with the netstat branch in the same
function which already validates with Number.isNaN.

While the downstream if (current.pid) truthiness check catches
NaN (falsy), adding validation at the parse site is defense-in-
depth and eliminates an inconsistency within the same function.

* test(ports): add edge case tests for parseLsofOutput

Add test coverage for malformed lsof 'p' lines (empty PID, non-numeric
suffix), zero PID, and empty input to verify the Number.isFinite guard
correctly filters invalid entries.
This commit is contained in:
lizeyu
2026-07-01 16:08:20 +08:00
committed by GitHub
parent 7cf3a56ade
commit 15bb4874bf
2 changed files with 31 additions and 1 deletions
+29
View File
@@ -53,6 +53,35 @@ describe("gateway --force helpers", () => {
]);
});
it("skips malformed lsof 'p' lines (no digits after p)", () => {
const sample = ["p", "cnode", "p456", "cpython", ""].join("\n");
const parsed = parseLsofOutput(sample);
expect(parsed).toEqual<PortProcess[]>([{ pid: 456, command: "python" }]);
});
it("skips malformed lsof 'p' lines (non-numeric suffix)", () => {
const sample = ["pabc", "cnode", "p456", "cpython", ""].join("\n");
const parsed = parseLsofOutput(sample);
expect(parsed).toEqual<PortProcess[]>([{ pid: 456, command: "python" }]);
});
it("returns empty array when all lsof 'p' lines are malformed", () => {
const sample = ["p", "cnode", "pabc", "", ""].join("\n");
const parsed = parseLsofOutput(sample);
expect(parsed).toEqual<PortProcess[]>([]);
});
it("handles empty lsof output", () => {
expect(parseLsofOutput("")).toEqual<PortProcess[]>([]);
});
it("handles 'p' lines with negative-like tokens (zero)", () => {
const sample = ["p0", "cnode", "p456", "cpython", ""].join("\n");
const parsed = parseLsofOutput(sample);
// PID 0 is filtered out (> 0 check), only valid PIDs remain
expect(parsed).toEqual<PortProcess[]>([{ pid: 456, command: "python" }]);
});
it("returns empty list when lsof finds nothing", () => {
(execFileSync as unknown as Mock).mockImplementation(() => {
const err = new Error("no matches") as NodeJS.ErrnoException & { status?: number };