test(process): strengthen macOS token parser boundaries

This commit is contained in:
morluto committed 2026-10-31 01:18:12 +08:00
1 parent ebfef27b46
commit 96606f5114
2 files changed
+44 -4

No files matched your search

@@ -1312,6 +1312,11 @@ it.skipIf(!onDarwin)(
duplicateTokenFailsClosed: true,
finalAssignmentArgumentRead: true,
missingAppleBoundaryFailsClosed: true,
malformedBuffersRejected: true,
malformedObservation: {
state: "unavailable",
reason: "malformed_procargs",
},
nonAsciiPathRead: true,
realTokenRead: true,
reservedArgumentIgnored: true,
@@ -1441,7 +1446,9 @@ it.skipIf(!onDarwin)(
const host = createSystemProcessOwnershipHost("darwin");
const children: Awaited<ReturnType<typeof startNodeChild>>[] = [];
try {
const executables = [join(root, "n"), join(root, "node")];
const executables = Array.from({ length: 8 }, (_, index) =>
join(root, "n".repeat(index + 1)),
);
for (const executable of executables)
await symlink(process.execPath, executable);
for (let index = 0; index < executables.length; index += 1) {
@@ -1467,8 +1474,10 @@ it.skipIf(!onDarwin)(
});
const observations = await host.runTokens?.(entries);
expect(children.map(({ pid }) => observations?.get(pid))).toEqual([
{ state: "readable", runId: "synthetic-padding-0" },
{ state: "readable", runId: "synthetic-padding-1" },
...executables.map((_, index) => ({
state: "readable",
runId: `synthetic-padding-${String(index)}`,
})),
{ state: "readable" },
]);
} finally {
+32 -1
View File
@@ -123,9 +123,35 @@ struct ProcessRunTokenParserProbe {
do {
_ = try parseProcessEnvironment(in: truncatedArgv)
truncatedArgvFailsClosed = false
} catch {
} catch RunTokenReadError.invalidBuffer {
truncatedArgvFailsClosed = true
}
var invalidPadding = fixture(arguments: ["x"], environment: [], executablePath: "x")
invalidPadding[6] = 1 // argc (4 bytes), path and its NUL precede the padding.
var unterminated = fixture(arguments: ["x"], environment: [], executablePath: "x")
unterminated.removeLast()
let malformedBuffers: [[UInt8]] = [
[0, 0, 0], // Short argc.
[255, 255, 255, 255], // Negative argc.
[0, 0, 0, 0, 120], // Unterminated executable path.
invalidPadding,
unterminated,
]
let malformedBuffersRejected = malformedBuffers.allSatisfy { bytes in
do {
_ = try parseProcessEnvironment(in: bytes)
return false
} catch RunTokenReadError.invalidBuffer {
return true
} catch {
return false
}
}
let malformedObservation = processRunTokenObservation(
pid: 1,
parse: .failure(.invalidBuffer),
codeSigningFlags: { 0 }
)
let duplicateTokenFailsClosed: Bool
do {
_ = try parseProcessEnvironment(in: fixture(
@@ -228,6 +254,11 @@ struct ProcessRunTokenParserProbe {
"emptyLaterArgumentRead": emptyLaterArgument.runId == "empty-argument-token",
"alternatePaddingRead": alternatePadding.runId == "alternate-padding-token",
"truncatedArgvFailsClosed": truncatedArgvFailsClosed,
"malformedBuffersRejected": malformedBuffersRejected,
"malformedObservation": [
"state": malformedObservation.state,
"reason": malformedObservation.reason as Any? ?? NSNull(),
],
"duplicateTokenFailsClosed": duplicateTokenFailsClosed,
"missingAppleBoundaryFailsClosed": missingAppleBoundaryFailsClosed,
"emptyArgv0Read": emptyArgv0Read.runId == "empty-argv0-token",