Files
reverse-engineering-anything/tests/boundary/filesystem/keyedArchiveXmlNesting.test.ts
T
ae09e3fe70 fix(native): recover macOS command deadlines (#6059)
* fix(native): recover macOS command deadlines

Promote native_command_timeout_ms (default 60000), native_ui_deadline_ms
(default 180000), and pwntools_timeout_ms (default 30000) as validated
per-call settings. Keep cpuSeconds, byte allowances, LLDB grace, and plist
probes fixed, and say those caps have no runtime override.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(native): report the deadline that actually expired

Pass the selected native command timeout through xcrun resolution, thread
the pwntools deadline into pwndbg failures, and state the selected UI
deadline apart from the fixed wait-step cap. SIGXFSZ and EFBIG recovery
names the file-size allowance.

Co-authored-by: morluto <morluto@users.noreply.github.com>

* fix(native): honor the selected deadline on helper stages

The UI helper compile and capture subprocesses used fixed 60s and 30s
exec timeouts, so a longer native_ui_deadline_ms still failed as a generic
provider error. Preparation timeouts reported the 60000 ms default instead
of the selected native_command_timeout_ms.

Memory resource-constraint recovery names memory again, and the Darwin
plist CLI expectation matches the byte-counted input allowance.

Co-authored-by: morluto <morluto@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: morluto <morluto@users.noreply.github.com>
2026-10-22 02:59:27 +08:00

102 lines
3.7 KiB
TypeScript

import { writeFile } from "node:fs/promises";
import { join } from "node:path";
import { expect, it } from "vitest";
import { parse } from "plist";
import { inspectBundleKeyedArchive } from "../../../src/artifacts/apple/KeyedArchiveReader.js";
import { plistNestingLimitMessage } from "../../../src/domain/apple/plistValue.js";
import { createTestTempDirectory } from "../../fixtures/temporaryDirectory.js";
import { deeplyNestedXmlPlist } from "../../fixtures/keyedArchiveXmlNesting.js";
it.each([129, 3000])(
"reports XML nesting of %i levels as the keyed archive decode limit",
async (depth) => {
const root = await createTestTempDirectory("rea-keyed-depth-");
await writeFile(join(root, "Deep.plist"), deeplyNestedXmlPlist(depth));
const rejected = await inspectBundleKeyedArchive({
bundlePath: root,
targetSha256: "a".repeat(64),
parameters: { path: "Deep.plist" },
platform: "linux",
}).catch((cause: unknown) => cause);
// Recursive decoding exhausts the call stack before the projection limit
// can report it, so the limit diagnostic must come from the preflight.
expect(rejected).toMatchObject({
reason: "limit",
message: `Cannot decode selected Foundation keyed archive: ${plistNestingLimitMessage()}`,
});
},
);
it.each(["(}", "{)", "(@", "{key @", "(x @", "(x ", "{key ", "{key = x,"])(
"preserves the pinned OpenStep syntax diagnosis before a deep suffix after %s",
async (prefix) => {
const text = prefix + "(".repeat(130);
let pinned: unknown;
try {
parse(text);
} catch (cause) {
pinned = cause;
}
if (!(pinned instanceof Error) || pinned instanceof RangeError)
throw new Error(
"Malformed control must fail in the pinned syntax decoder",
);
const root = await createTestTempDirectory("rea-keyed-openstep-malformed-");
await writeFile(join(root, "Malformed.plist"), text);
const rejected = await inspectBundleKeyedArchive({
bundlePath: root,
targetSha256: "a".repeat(64),
parameters: { path: "Malformed.plist" },
platform: "linux",
}).catch((cause: unknown) => cause);
expect(rejected).toMatchObject({
reason: "format",
message: `Cannot decode selected Foundation keyed archive: ${pinned.message}`,
});
},
);
it("retains the limit classification for syntactically valid deep OpenStep values", async () => {
const root = await createTestTempDirectory("rea-keyed-openstep-limit-");
await writeFile(
join(root, "Deep.plist"),
"(".repeat(129) + "x" + ")".repeat(129),
);
const rejected = await inspectBundleKeyedArchive({
bundlePath: root,
targetSha256: "a".repeat(64),
parameters: { path: "Deep.plist" },
platform: "linux",
}).catch((cause: unknown) => cause);
expect(rejected).toMatchObject({
reason: "limit",
message: `Cannot decode selected Foundation keyed archive: ${plistNestingLimitMessage()}`,
});
});
it.each([
["array sibling", (deep: string) => `((x),${deep})`],
["compound dictionary key", (deep: string) => `{(key)=${deep};}`],
] as const)(
"retains the named OpenStep depth limit after a completed %s",
async (_name, document) => {
const root = await createTestTempDirectory(
"rea-keyed-openstep-sibling-depth-",
);
const deep = "(".repeat(30000) + "x" + ")".repeat(30000);
await writeFile(join(root, "Deep.plist"), document(deep));
const rejected = await inspectBundleKeyedArchive({
bundlePath: root,
targetSha256: "a".repeat(64),
parameters: { path: "Deep.plist" },
platform: "linux",
}).catch((cause: unknown) => cause);
expect(rejected).toMatchObject({
reason: "limit",
message: `Cannot decode selected Foundation keyed archive: ${plistNestingLimitMessage()}`,
});
},
);