Files
rea/tests/fixtures/processRunTokenParserProbe.swift
morluto 23de10bb28 fix: streamline tests and preserve Darwin process ownership (#8275)
* test: strengthen suite guards and regression oracles

* test: share JSON client registration contract

* test: reuse fixtures and reduce repeated setup

* fix(process): preserve ambiguous Darwin token ownership

* test(process): bound child readiness waits
2026-10-31 16:43:04 +08:00

335 lines
14 KiB
Swift

import Foundation
func fixture(
arguments: [String],
environment: [String],
pointerSize: Int = 8,
executablePath: String = "/fixture/executable",
appleRecords: [String] = ["pfz=synthetic"],
zeroedPfz: Bool = false
) -> [UInt8] {
var bytes = withUnsafeBytes(of: Int32(arguments.count).littleEndian, Array.init)
let pathBytes = Array(executablePath.utf8)
bytes.append(contentsOf: pathBytes + [0])
let prefixLength = Array("executable_path=".utf8).count
let padding = (pointerSize - ((prefixLength + pathBytes.count + 1) % pointerSize)) % pointerSize
bytes.append(contentsOf: repeatElement(UInt8(0), count: padding))
for argument in arguments { bytes.append(contentsOf: Array(argument.utf8) + [0]) }
for entry in environment { bytes.append(contentsOf: Array(entry.utf8) + [0]) }
if zeroedPfz {
bytes.append(contentsOf: repeatElement(UInt8(0), count: Array("pfz=synthetic".utf8).count + 1))
}
for record in appleRecords { bytes.append(contentsOf: Array(record.utf8) + [0]) }
return bytes
}
@main
struct ProcessRunTokenParserProbe {
static func main() throws {
let argvDecoyFailsClosed: Bool
do {
_ = try parseProcessEnvironment(in: fixture(
arguments: ["/fixture/executable", "REA_PROCESS_RUN_ID=argv-decoy", "trailing"],
environment: ["DECOY=words REA_PROCESS_RUN_ID=synthetic-decoy"]
))
argvDecoyFailsClosed = false
} catch RunTokenReadError.ambiguousEnvironmentBoundary {
argvDecoyFailsClosed = true
}
// This layout matches the observed long-title overwrite: a former
// environment entry is consumed as an argv slot before the cleared pfz.
let titleOverwriteFailsClosed: Bool
do {
_ = try parseProcessEnvironment(in: fixture(
arguments: [String(repeating: "n", count: 248), "REA_PROCESS_RUN_ID=owned-token", "a", "b", "c", "d"],
environment: ["PATH=/usr/bin"],
zeroedPfz: true
))
titleOverwriteFailsClosed = false
} catch RunTokenReadError.ambiguousEnvironmentBoundary {
titleOverwriteFailsClosed = true
}
let realToken = try parseProcessEnvironment(in: fixture(
arguments: ["/fixture/executable"],
environment: ["DECOY=words REA_PROCESS_RUN_ID=synthetic-decoy", "REA_PROCESS_RUN_ID=owned-token"]
))
let readableNoToken = try parseProcessEnvironment(in: fixture(
arguments: ["/fixture/executable"],
environment: ["PATH=/usr/bin"]
))
let emptyLaterArgument = try parseProcessEnvironment(in: fixture(
arguments: ["/fixture/executable", "", "after-empty"],
environment: ["REA_PROCESS_RUN_ID=empty-argument-token"],
pointerSize: 8
))
let alternatePadding = try parseProcessEnvironment(in: fixture(
arguments: ["/fixture/executable", "argument"],
environment: ["REA_PROCESS_RUN_ID=alternate-padding-token"],
pointerSize: 4
), pointerSize: 4)
let emptyArgv0Read = try parseProcessEnvironment(in: fixture(
arguments: ["", "", "after-empty"],
environment: ["REA_PROCESS_RUN_ID=empty-argv0-token"],
pointerSize: 8
))
let finalAssignmentArgumentRead = try parseProcessEnvironment(in: fixture(
arguments: ["/fixture/executable", "FOO=bar"],
environment: ["REA_PROCESS_RUN_ID=final-assignment-token"]
))
let reservedArgumentWithRealTokenFailsClosed: Bool
do {
_ = try parseProcessEnvironment(in: fixture(
arguments: ["/fixture/executable", "REA_PROCESS_RUN_ID=argv-decoy"],
environment: ["REA_PROCESS_RUN_ID=actual-token"]
))
reservedArgumentWithRealTokenFailsClosed = false
} catch RunTokenReadError.ambiguousEnvironmentBoundary {
reservedArgumentWithRealTokenFailsClosed = true
}
let nonAsciiPathRead = try parseProcessEnvironment(in: fixture(
arguments: ["/fixture/é", "FOO=bar"],
environment: ["REA_PROCESS_RUN_ID=utf8-path-token"],
pointerSize: 8,
executablePath: "/fixture/é"
))
let appleVectorTokenFailsClosed: Bool
do {
_ = try parseProcessEnvironment(in: fixture(
arguments: ["/fixture/executable"],
environment: ["pfz=user-value", "PATH=/usr/bin"],
appleRecords: ["pfz=synthetic", "REA_PROCESS_RUN_ID=apple-decoy"]
))
appleVectorTokenFailsClosed = false
} catch RunTokenReadError.ambiguousEnvironmentBoundary {
appleVectorTokenFailsClosed = true
}
let clearedAppleVectorTokenFailsClosed: Bool
do {
_ = try parseProcessEnvironment(in: fixture(
arguments: ["/fixture/executable"],
environment: ["REA_PROCESS_RUN_ID=cleared-pfz-owned-token"],
appleRecords: ["REA_PROCESS_RUN_ID=apple-decoy"],
zeroedPfz: true
))
clearedAppleVectorTokenFailsClosed = false
} catch RunTokenReadError.ambiguousEnvironmentBoundary {
clearedAppleVectorTokenFailsClosed = true
}
let callerPfzBeforeTokenRead = try parseProcessEnvironment(in: fixture(
arguments: ["/fixture/executable"],
environment: ["pfz=caller-value", "REA_PROCESS_RUN_ID=cleared-pfz-owned-token"],
zeroedPfz: true
))
let emptyEnvironmentRecordsBeforeTokenFailClosed: Bool
do {
_ = try parseProcessEnvironment(in: fixture(
arguments: ["/fixture/executable"],
environment: ["DECOY=value", "", "", "REA_PROCESS_RUN_ID=synthetic-decoy"],
appleRecords: [],
zeroedPfz: true
))
emptyEnvironmentRecordsBeforeTokenFailClosed = false
} catch RunTokenReadError.ambiguousEnvironmentBoundary {
emptyEnvironmentRecordsBeforeTokenFailClosed = true
}
let zeroArgumentsRead = try parseProcessEnvironment(in: fixture(
arguments: [],
environment: ["REA_PROCESS_RUN_ID=zero-argc-token"],
pointerSize: 4
), pointerSize: 4)
var truncatedArgv = withUnsafeBytes(of: Int32(2).littleEndian, Array.init)
let truncatedPath = Array("/fixture/executable".utf8)
truncatedArgv.append(contentsOf: truncatedPath + [0])
let truncatedPadding = (8 - ((Array("executable_path=".utf8).count + truncatedPath.count + 1) % 8)) % 8
truncatedArgv.append(contentsOf: repeatElement(UInt8(0), count: truncatedPadding))
truncatedArgv.append(contentsOf: Array("/fixture/executable".utf8) + [0])
truncatedArgv.append(contentsOf: Array("REA_PROCESS_RUN_ID=synthetic-decoy".utf8))
let truncatedArgvFailsClosed: Bool
do {
_ = try parseProcessEnvironment(in: truncatedArgv)
truncatedArgvFailsClosed = false
} catch RunTokenReadError.invalidBufferAt(.arguments) {
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: ["REA_PROCESS_RUN_ID=argv-decoy"], environment: [], executablePath: "x")
unterminated.removeLast()
let malformedBuffers: [([UInt8], ProcargsMalformedStage)] = [
([0, 0, 0], .header),
([255, 255, 255, 255], .argumentCount),
([0, 0, 0, 0, 120], .executablePath),
(invalidPadding, .pathPadding),
(unterminated, .terminator),
(truncatedArgv, .arguments),
]
let malformedBuffersRejected = malformedBuffers.allSatisfy { bytes, expectedStage in
do {
_ = try parseProcessEnvironment(in: bytes)
return false
} catch RunTokenReadError.invalidBufferAt(let stage) {
return stage == expectedStage
} catch {
return false
}
}
let invalidPointerSizeFailsClosed: Bool
do {
_ = try parseProcessEnvironment(in: fixture(arguments: [], environment: []), pointerSize: 3)
invalidPointerSizeFailsClosed = false
} catch RunTokenReadError.invalidBufferAt(.pointerSize) {
invalidPointerSizeFailsClosed = true
}
let malformedStages = ProcargsMalformedStage.allCases.map { stage in
let observation = processRunTokenObservation(
pid: 1,
parse: .failure(.invalidBufferAt(stage)),
codeSigningFlags: { 0 }
)
return ["state": observation.state, "reason": observation.reason ?? ""]
}
let malformedObservation = processRunTokenObservation(
pid: 1,
parse: .failure(.invalidBuffer),
codeSigningFlags: { 0 }
)
let duplicateTokenFailsClosed: Bool
do {
_ = try parseProcessEnvironment(in: fixture(
arguments: ["/fixture/executable", "REA_PROCESS_RUN_ID=argv-decoy"],
environment: ["REA_PROCESS_RUN_ID=first", "REA_PROCESS_RUN_ID=second"]
))
duplicateTokenFailsClosed = false
} catch RunTokenReadError.duplicateToken {
duplicateTokenFailsClosed = true
}
var invalidTokenEncoding = fixture(
arguments: ["/fixture/executable", "REA_PROCESS_RUN_ID=argv-decoy"],
environment: ["REA_PROCESS_RUN_ID=é"]
)
invalidTokenEncoding[invalidTokenEncoding.firstIndex(of: 0xc3)!] = 0xff
let invalidTokenEncodingFailsClosed: Bool
do {
_ = try parseProcessEnvironment(in: invalidTokenEncoding)
invalidTokenEncodingFailsClosed = false
} catch RunTokenReadError.invalidTokenEncoding {
invalidTokenEncodingFailsClosed = true
}
let missingAppleBoundaryFailsClosed: Bool
do {
_ = try parseProcessEnvironment(in: fixture(
arguments: ["/fixture/executable"],
environment: ["REA_PROCESS_RUN_ID=synthetic-decoy"],
appleRecords: []
))
missingAppleBoundaryFailsClosed = false
} catch RunTokenReadError.appleVectorUnavailable {
missingAppleBoundaryFailsClosed = true
}
let restrictedReadableNoToken = processRunTokenObservation(
pid: 1,
parse: .success(readableNoToken),
codeSigningFlags: { 0x0000_0800 }
)
let restrictedEmptyEnvironment = processRunTokenObservation(
pid: 1,
parse: .success(try parseProcessEnvironment(in: fixture(
arguments: ["/fixture/executable"],
environment: []
))),
codeSigningFlags: { 0x0000_0800 }
)
let platformEmptyEnvironment = processRunTokenObservation(
pid: 1,
parse: .success(try parseProcessEnvironment(in: fixture(
arguments: ["/fixture/executable"],
environment: []
))),
codeSigningFlags: { 0x0400_0000 }
)
let restrictedUnavailableEnvironment = processRunTokenObservation(
pid: 1,
parse: .failure(.environmentUnavailable),
codeSigningFlags: { 0x0000_0800 }
)
let restrictedAmbiguousEnvironment = processRunTokenObservation(
pid: 1,
parse: .failure(.ambiguousEnvironmentBoundary),
codeSigningFlags: { 0x0000_0800 }
)
let ordinaryAmbiguousEnvironment = processRunTokenObservation(
pid: 1,
parse: .failure(.ambiguousEnvironmentBoundary),
codeSigningFlags: { 0 }
)
let ordinaryUnavailableEnvironment = processRunTokenObservation(
pid: 1,
parse: .failure(.environmentUnavailable),
codeSigningFlags: { 0 }
)
let result: [String: Any] = [
"argvDecoyFailsClosed": argvDecoyFailsClosed,
"titleOverwriteFailsClosed": titleOverwriteFailsClosed,
"realTokenRead": realToken.runId == "owned-token",
"readableEnvironmentWithoutToken": [
"runId": readableNoToken.runId as Any? ?? NSNull(),
"environmentEntryCount": readableNoToken.environmentEntryCount,
],
"restrictedReadableEnvironmentWithoutToken": [
"state": restrictedReadableNoToken.state,
"reason": restrictedReadableNoToken.reason as Any? ?? NSNull(),
],
"restrictedEmptyEnvironment": [
"state": restrictedEmptyEnvironment.state,
"reason": restrictedEmptyEnvironment.reason as Any? ?? NSNull(),
],
"platformEmptyEnvironment": [
"state": platformEmptyEnvironment.state,
"reason": platformEmptyEnvironment.reason as Any? ?? NSNull(),
],
"restrictedUnavailableEnvironment": [
"state": restrictedUnavailableEnvironment.state,
"reason": restrictedUnavailableEnvironment.reason as Any? ?? NSNull(),
],
"restrictedAmbiguousEnvironment": [
"state": restrictedAmbiguousEnvironment.state,
"reason": restrictedAmbiguousEnvironment.reason as Any? ?? NSNull(),
],
"ordinaryAmbiguousEnvironment": [
"state": ordinaryAmbiguousEnvironment.state,
"reason": ordinaryAmbiguousEnvironment.reason as Any? ?? NSNull(),
],
"ordinaryUnavailableEnvironment": [
"state": ordinaryUnavailableEnvironment.state,
"reason": ordinaryUnavailableEnvironment.reason as Any? ?? NSNull(),
],
"emptyLaterArgumentRead": emptyLaterArgument.runId == "empty-argument-token",
"alternatePaddingRead": alternatePadding.runId == "alternate-padding-token",
"truncatedArgvFailsClosed": truncatedArgvFailsClosed,
"malformedBuffersRejected": malformedBuffersRejected,
"invalidPointerSizeFailsClosed": invalidPointerSizeFailsClosed,
"malformedStages": malformedStages,
"malformedObservation": [
"state": malformedObservation.state,
"reason": malformedObservation.reason as Any? ?? NSNull(),
],
"duplicateTokenFailsClosed": duplicateTokenFailsClosed,
"invalidTokenEncodingFailsClosed": invalidTokenEncodingFailsClosed,
"missingAppleBoundaryFailsClosed": missingAppleBoundaryFailsClosed,
"emptyArgv0Read": emptyArgv0Read.runId == "empty-argv0-token",
"finalAssignmentArgumentRead": finalAssignmentArgumentRead.runId == "final-assignment-token",
"reservedArgumentWithRealTokenFailsClosed": reservedArgumentWithRealTokenFailsClosed,
"nonAsciiPathRead": nonAsciiPathRead.runId == "utf8-path-token",
"appleVectorTokenFailsClosed": appleVectorTokenFailsClosed,
"clearedAppleVectorTokenFailsClosed": clearedAppleVectorTokenFailsClosed,
"callerPfzBeforeTokenRead": callerPfzBeforeTokenRead.runId == "cleared-pfz-owned-token",
"emptyEnvironmentRecordsBeforeTokenFailClosed": emptyEnvironmentRecordsBeforeTokenFailClosed,
"zeroArgumentsRead": zeroArgumentsRead.runId == "zero-argc-token",
]
let output = try JSONSerialization.data(withJSONObject: result, options: [.sortedKeys])
FileHandle.standardOutput.write(output)
}
}