mirror of
https://github.com/morluto/rea.git
synced 2026-10-26 17:35:11 +00:00
fix(apple): keep the documented terminating process, parent pid and metadata members of IPS reports (#7079)
Apple's crash report JSON documents termination.byPid, byProc and flags, the body's parentPid, and the metadata line's build_version and platform. The parser shapes did not list them, so they were reported only by name in unlisted_keys / unlisted_body_keys and their values were dropped: a watchdog kill no longer said which process ended it, and process kept parentProc without its pid. #4297 asks for termination members beyond namespace/code/indicator to be retained as recorded, and docs/apple-ips.md says documented fields are reproduced. They are now kept: termination.by_proc, termination.by_pid and termination.flags, process.parent_pid and metadata.build_version / metadata.platform. The integers are recorded integers, so they count toward max_integer_text_bytes and a type mismatch is recorded like the other fields.
This commit is contained in:
1 parent
cc146042d1
commit
0a2b7af905
7 files changed
+81
-13
No files matched your search
+4
-1
@@ -31,7 +31,10 @@ stackshots, return no crash result.
|
||||
`process`, `exception`, `termination`, `faulting_thread`, `threads`, and
|
||||
`images` reproduce documented body fields when present, including each image's
|
||||
`name` and each frame's `symbolLocation` (as `symbol_location`, the byte offset
|
||||
from the start of `recorded_symbol`). Integers keep their
|
||||
from the start of `recorded_symbol`). `termination` keeps the terminating
|
||||
process as `by_proc` and `by_pid` and its `flags`; `process.parent_pid` keeps
|
||||
`parentPid` next to `parent`; and `metadata` keeps `build_version` and
|
||||
`platform`. Integers keep their
|
||||
decimal literals and a hexadecimal form, including arm64e registers above
|
||||
2^53. Frame roles follow the recorded frame index: row zero of the resolved
|
||||
faulting thread is `faulting_instruction`, row zero of other threads is
|
||||
|
||||
@@ -22,6 +22,8 @@ const report: AppleIps = {
|
||||
bundle_id: null,
|
||||
incident_id: null,
|
||||
name: null,
|
||||
build_version: null,
|
||||
platform: null,
|
||||
unlisted_keys: [],
|
||||
},
|
||||
process: {
|
||||
@@ -29,6 +31,7 @@ const report: AppleIps = {
|
||||
path: null,
|
||||
pid: null,
|
||||
parent: null,
|
||||
parent_pid: null,
|
||||
cpu_type: null,
|
||||
translated: null,
|
||||
os_version: null,
|
||||
@@ -200,19 +203,23 @@ it.each(["threads", "images"] as const)(
|
||||
);
|
||||
|
||||
it.each([
|
||||
[43, false],
|
||||
[44, true],
|
||||
[131, false],
|
||||
[132, true],
|
||||
] as const)(
|
||||
"checks repeated integer text against %s UTF-16 bytes",
|
||||
async (maximum, accepted) => {
|
||||
const value = { decimal: "12345", hex: "0x3039" };
|
||||
const repeated: AppleIps = {
|
||||
...report,
|
||||
process: { ...report.process, pid: value },
|
||||
metadata: { ...report.metadata, platform: value },
|
||||
process: { ...report.process, pid: value, parent_pid: value },
|
||||
termination: {
|
||||
namespace: null,
|
||||
code: value,
|
||||
indicator: null,
|
||||
flags: value,
|
||||
by_pid: value,
|
||||
by_proc: null,
|
||||
reasons: null,
|
||||
unlisted_keys: [],
|
||||
},
|
||||
|
||||
@@ -40,6 +40,8 @@ it("rejects extra caller arguments and admits an empty crash inventory", () => {
|
||||
bundle_id: null,
|
||||
incident_id: null,
|
||||
name: null,
|
||||
build_version: null,
|
||||
platform: null,
|
||||
unlisted_keys: [],
|
||||
},
|
||||
process: {
|
||||
@@ -47,6 +49,7 @@ it("rejects extra caller arguments and admits an empty crash inventory", () => {
|
||||
path: null,
|
||||
pid: null,
|
||||
parent: null,
|
||||
parent_pid: null,
|
||||
cpu_type: null,
|
||||
translated: null,
|
||||
os_version: null,
|
||||
|
||||
@@ -122,6 +122,8 @@ const metadataSchema = z.strictObject({
|
||||
bundle_id: z.string().nullable(),
|
||||
incident_id: z.string().nullable(),
|
||||
name: z.string().nullable(),
|
||||
build_version: z.string().nullable(),
|
||||
platform: recordedIntegerSchema.nullable(),
|
||||
unlisted_keys: z.array(z.string()),
|
||||
});
|
||||
|
||||
@@ -141,6 +143,9 @@ const terminationSchema = z
|
||||
namespace: z.string().nullable(),
|
||||
code: recordedIntegerSchema.nullable(),
|
||||
indicator: z.string().nullable(),
|
||||
flags: recordedIntegerSchema.nullable(),
|
||||
by_pid: recordedIntegerSchema.nullable(),
|
||||
by_proc: z.string().nullable(),
|
||||
reasons: z.array(z.string()).nullable(),
|
||||
unlisted_keys: z.array(z.string()),
|
||||
})
|
||||
@@ -275,6 +280,7 @@ export const appleIpsSchema = z.strictObject({
|
||||
path: z.string().nullable(),
|
||||
pid: recordedIntegerSchema.nullable(),
|
||||
parent: z.string().nullable(),
|
||||
parent_pid: recordedIntegerSchema.nullable(),
|
||||
cpu_type: z.string().nullable(),
|
||||
translated: z.boolean().nullable(),
|
||||
os_version: osVersionSchema,
|
||||
@@ -314,8 +320,12 @@ export const appleIpsIntegerTextBytes = (
|
||||
/** The named report fields own which observed and derived integers are retained. */
|
||||
export const appleIpsReportIntegerTextBytes = (report: AppleIps): number => {
|
||||
let bytes =
|
||||
appleIpsIntegerTextBytes(report.metadata.platform) +
|
||||
appleIpsIntegerTextBytes(report.process.pid) +
|
||||
appleIpsIntegerTextBytes(report.termination?.code ?? null);
|
||||
appleIpsIntegerTextBytes(report.process.parent_pid) +
|
||||
appleIpsIntegerTextBytes(report.termination?.code ?? null) +
|
||||
appleIpsIntegerTextBytes(report.termination?.flags ?? null) +
|
||||
appleIpsIntegerTextBytes(report.termination?.by_pid ?? null);
|
||||
for (const image of report.images)
|
||||
bytes +=
|
||||
appleIpsIntegerTextBytes(image.base) +
|
||||
|
||||
@@ -122,7 +122,14 @@ const terminationShape = (): JsonShape => {
|
||||
return {
|
||||
kind: "object",
|
||||
members: {
|
||||
...scalarMembers("namespace", "code", "indicator"),
|
||||
...scalarMembers(
|
||||
"namespace",
|
||||
"code",
|
||||
"indicator",
|
||||
"flags",
|
||||
"byPid",
|
||||
"byProc",
|
||||
),
|
||||
reasons: {
|
||||
kind: "array",
|
||||
items: SCALAR,
|
||||
@@ -150,6 +157,7 @@ export const ipsBodyShape = (input: InspectAppleIpsInput): JsonShape => {
|
||||
"procName",
|
||||
"procPath",
|
||||
"pid",
|
||||
"parentPid",
|
||||
"parentProc",
|
||||
"cpuType",
|
||||
"translated",
|
||||
@@ -202,6 +210,8 @@ export const IPS_METADATA_SHAPE: JsonShape = {
|
||||
"bundleID",
|
||||
"incident_id",
|
||||
"name",
|
||||
"build_version",
|
||||
"platform",
|
||||
),
|
||||
beforeUnlisted: unlistedKeys,
|
||||
};
|
||||
|
||||
@@ -383,11 +383,7 @@ it("keeps ReportCrash-shaped producer facts and reports complete coverage", () =
|
||||
description: "(Data Abort) byte read Translation fault",
|
||||
});
|
||||
expect(parsed.exception?.unlisted_keys).toEqual(["rawCodes"]);
|
||||
expect(parsed.termination?.unlisted_keys).toEqual([
|
||||
"flags",
|
||||
"byProc",
|
||||
"byPid",
|
||||
]);
|
||||
expect(parsed.termination?.unlisted_keys).toEqual([]);
|
||||
expect(parsed.unlisted_body_keys).toContain("sharedCache");
|
||||
expect(parsed.unlisted_body_keys).not.toContain("osVersion");
|
||||
expect(parsed.metadata.unlisted_keys).toContain("slice_uuid");
|
||||
@@ -402,6 +398,37 @@ it("keeps ReportCrash-shaped producer facts and reports complete coverage", () =
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps the documented terminating process, parent pid and metadata members", () => {
|
||||
const parsed = report({});
|
||||
expect(parsed.termination).toMatchObject({
|
||||
flags: { decimal: "0", hex: "0x0" },
|
||||
by_pid: { decimal: "4242", hex: "0x1092" },
|
||||
by_proc: "exc handler",
|
||||
});
|
||||
expect(parsed.process.parent_pid).toEqual({ decimal: "100", hex: "0x64" });
|
||||
expect(parsed.metadata).toMatchObject({
|
||||
build_version: "",
|
||||
platform: { decimal: "1", hex: "0x1" },
|
||||
});
|
||||
expect(parsed.metadata.unlisted_keys).not.toContain("build_version");
|
||||
expect(parsed.metadata.unlisted_keys).not.toContain("platform");
|
||||
expect(parsed.unlisted_body_keys).not.toContain("parentPid");
|
||||
expect(parsed.coverage.status).toBe("complete");
|
||||
const wrong = parse(
|
||||
Buffer.from(
|
||||
appleIpsReport().replace('"byPid": 4242', '"byPid": "4242"'),
|
||||
"utf8",
|
||||
),
|
||||
);
|
||||
expect(wrong.termination?.by_pid).toBeNull();
|
||||
expect(wrong.coverage.type_mismatches).toContainEqual(
|
||||
expect.objectContaining({
|
||||
path: "body.termination.byPid",
|
||||
expected: "integer",
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps the recorded image name and symbol offset", () => {
|
||||
const parsed = report({});
|
||||
expect(parsed.images.map((image) => image.name)).toEqual([
|
||||
@@ -511,8 +538,10 @@ it.each(["-1", "4294967296", `1${"0".repeat(1000)}`])(
|
||||
);
|
||||
|
||||
it("bounds rejected index text before retaining it", () => {
|
||||
const bytes = withBody(
|
||||
'{"faultingThread":4294967296,"threads":[],"usedImages":[]}',
|
||||
// A bare metadata line: its recorded platform integer would also count toward this allowance.
|
||||
const bytes = Buffer.from(
|
||||
'{"bug_type":"309"}\n{"faultingThread":4294967296,"threads":[],"usedImages":[]}',
|
||||
"utf8",
|
||||
);
|
||||
expect(() =>
|
||||
parseAppleIps(bytes, artifact(bytes), {
|
||||
|
||||
@@ -86,6 +86,9 @@ const terminationOf = (
|
||||
namespace: read.text(members.namespace, "body.termination.namespace"),
|
||||
code: read.integer(members.code, "body.termination.code"),
|
||||
indicator: read.text(members.indicator, "body.termination.indicator"),
|
||||
flags: read.integer(members.flags, "body.termination.flags"),
|
||||
by_pid: read.integer(members.byPid, "body.termination.byPid"),
|
||||
by_proc: read.text(members.byProc, "body.termination.byProc"),
|
||||
reasons:
|
||||
reasonItems === null
|
||||
? null
|
||||
@@ -353,6 +356,8 @@ const metadataOf = (text: string, read: FieldReader): AppleIps["metadata"] => {
|
||||
bundle_id: read.text(members.bundleID, "metadata.bundleID"),
|
||||
incident_id: read.text(members.incident_id, "metadata.incident_id"),
|
||||
name: read.text(members.name, "metadata.name"),
|
||||
build_version: read.text(members.build_version, "metadata.build_version"),
|
||||
platform: read.integer(members.platform, "metadata.platform"),
|
||||
unlisted_keys: [...json.unlisted],
|
||||
};
|
||||
};
|
||||
@@ -433,6 +438,7 @@ export const parseAppleIps = (
|
||||
path: read.text(body.procPath, "body.procPath"),
|
||||
pid: read.integer(body.pid, "body.pid"),
|
||||
parent: read.text(body.parentProc, "body.parentProc"),
|
||||
parent_pid: read.integer(body.parentPid, "body.parentPid"),
|
||||
cpu_type: read.text(body.cpuType, "body.cpuType"),
|
||||
translated: read.boolean(body.translated, "body.translated"),
|
||||
os_version: osVersionOf(body.osVersion, read),
|
||||
|
||||
Reference in new issue
Block a user