Compare commits

...
Author SHA1 Message Date
Kaoru0822andClaude Opus 5.5 106f260d18 fix(swift): keep nested types with undecoded identifiers unclassified
classifySwiftSymbol stopped at the first identifier it could not decode and
kept the enclosing nominal's category. A nested type named by a punycode or
word-substituted identifier (`0...`) inside a struct was therefore filed as a
struct, so analyze_swift_types reported nested enums and classes under
structs and dropped them from a classes filter and from unclassified. Such
an identifier may name a type of any kind, so the category is now unknown.

Fixes #5553

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 15:04:37 +00:00
morluto 7b2087e449 test(kuna): separate composed doctor startup from cancellation timing
Allow the preceding Ghidra ownership preparation before waiting for the gated Kuna child. Keep the two-second cancellation join, exact reasons, reaping and cleanup assertions unchanged.

Refs #5568. A controlled startup delay reproduces the old failure; disabling cancellation forwarding still fails the retained join assertion. All 86 focused setup, doctor, helper and CLI checks passed on pinned Node 24.18.0/macOS arm64.
2026-10-20 22:57:21 +08:00
3 changed files with 27 additions and 2 deletions

No files matched your search

+6 -1
View File
@@ -38,7 +38,12 @@ export const classifySwiftSymbol = (
let category: SwiftTypeCategory | null = null;
for (;;) {
const end = identifierEnd(mangling, offset);
if (end === undefined) break;
if (end === undefined) {
// A word-substituted or punycode identifier (`0…`) may name a nested
// type of any kind, so the enclosing nominal no longer decides it.
if (mangling.charAt(offset) === "0") category = null;
break;
}
const kind = mangling.charAt(end);
const nominal = NOMINAL_CATEGORIES.get(kind);
if (nominal === undefined) {
+14
View File
@@ -28,6 +28,10 @@ describe("modern Swift category evidence", () => {
"$sSi4mainE7doubledSiyF",
"$s9999999999999999999999BadVMa",
"$s4main04PairVMa",
// Nested types named by punycode identifiers inside struct Envelope.
"_$s6Nested8EnvelopeV007IhuqBAbO8describeSSyF",
"_$s6Nested8EnvelopeV007jvrtDBlCAEycfC",
"_$s6Nested8EnvelopeV007jvrtDBlCMa",
];
const result = categorizeSwiftTypes(
names.map((name, index) => ({ address: String(index), name })),
@@ -52,6 +56,16 @@ describe("modern Swift category evidence", () => {
).toMatchObject({ total: 0, unclassified: [] });
});
it("keeps a nested punycode class unresolved under a class filter", () => {
const name = "_$s6Nested8EnvelopeV007jvrtDBlCMa";
expect(
categorizeSwiftTypes([{ address: "0x1", name }], { category: "classes" }),
).toMatchObject({
total: 0,
unclassified: [{ name, reason: "category_not_decoded" }],
});
});
it("deduplicates display names after selecting a category", () => {
expect(
categorizeSwiftTypes(
@@ -176,7 +176,13 @@ it.each(["caller", "host"] as const)(
);
let closing: ReturnType<NonNullable<typeof host.close>> | undefined;
try {
await expect.poll(async () => (await fakeKunaCalls(kuna)).length).toBe(1);
// The preceding Ghidra probe may prepare Darwin process ownership before
// Kuna starts; keep startup separate from the bounded post-abort join.
await expect
.poll(async () => (await fakeKunaCalls(kuna)).length, {
timeout: 10_000,
})
.toBe(1);
const probe = (await fakeKunaCalls(kuna))[0];
if (probe === undefined) throw new Error("Missing Kuna version probe");
expect(probe.argv).toEqual(["--version"]);