fix(native): classify every Swift mangling prefix as invalid when undecodable
demangle_swift reported "invalid" only for $s and _$s inputs that swift-demangle left unchanged. Undecodable symbols carrying the other prefixes the Swift demangler accepts (_T0, $S, _$S, @__swiftmacro_, $e, _$e) were reported as "unchanged", i.e. as non-Swift names. Legacy _T stays "unchanged" because it is also an ordinary C symbol spelling. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
70771523c5
commit
a3cea599fb
|
|
@ -40,21 +40,23 @@ describe("parseDemangledSymbols", () => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("identifies invalid Swift symbols that fail demangling", () => {
|
it("identifies invalid Swift symbols for every demangler mangling prefix", () => {
|
||||||
const inputs = ["$sInvalidMangle", "_$sAlsoInvalid"];
|
const inputs = [
|
||||||
const output = "$sInvalidMangle\n_$sAlsoInvalid\n";
|
"_T0Bogus",
|
||||||
expect(parseDemangledSymbols(inputs, output)).toEqual([
|
"$SBogus",
|
||||||
{
|
"_$SBogus",
|
||||||
input: "$sInvalidMangle",
|
"$sBogus",
|
||||||
output: "$sInvalidMangle",
|
"_$sBogus",
|
||||||
status: "invalid",
|
"@__swiftmacro_Bogus",
|
||||||
},
|
"$eBogus",
|
||||||
{
|
"_$eBogus",
|
||||||
input: "_$sAlsoInvalid",
|
"_Tprintf",
|
||||||
output: "_$sAlsoInvalid",
|
];
|
||||||
status: "invalid",
|
expect(
|
||||||
},
|
parseDemangledSymbols(inputs, `${inputs.join("\n")}\n`).map(
|
||||||
]);
|
({ status }) => status,
|
||||||
|
),
|
||||||
|
).toEqual([...Array<string>(8).fill("invalid"), "unchanged"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("parses mixed batches preserving ordering", () => {
|
it("parses mixed batches preserving ordering", () => {
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,22 @@ const resultSchema = z.object({
|
||||||
|
|
||||||
export type DemangledSymbol = z.infer<typeof resultSchema>;
|
export type DemangledSymbol = z.infer<typeof resultSchema>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prefixes the Swift demangler accepts as mangled names (Swift 4, 4.x, 5+,
|
||||||
|
* macro file names and Embedded Swift). Legacy `_T` is omitted because it is
|
||||||
|
* also an ordinary C symbol spelling such as `_Tprintf`.
|
||||||
|
*/
|
||||||
|
const SWIFT_MANGLING_PREFIXES = [
|
||||||
|
"_T0",
|
||||||
|
"$S",
|
||||||
|
"_$S",
|
||||||
|
"$s",
|
||||||
|
"_$s",
|
||||||
|
"@__swiftmacro_",
|
||||||
|
"$e",
|
||||||
|
"_$e",
|
||||||
|
] as const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preserve input ordering while parsing `swift-demangle --compact` lines.
|
* Preserve input ordering while parsing `swift-demangle --compact` lines.
|
||||||
* The demangler ends each record with LF, so a carriage return belongs to the
|
* The demangler ends each record with LF, so a carriage return belongs to the
|
||||||
|
|
@ -33,7 +49,7 @@ export const parseDemangledSymbols = (
|
||||||
output: value,
|
output: value,
|
||||||
status:
|
status:
|
||||||
value === input
|
value === input
|
||||||
? input.startsWith("$s") || input.startsWith("_$s")
|
? SWIFT_MANGLING_PREFIXES.some((prefix) => input.startsWith(prefix))
|
||||||
? "invalid"
|
? "invalid"
|
||||||
: "unchanged"
|
: "unchanged"
|
||||||
: "demangled",
|
: "demangled",
|
||||||
|
|
|
||||||
|
|
@ -68,5 +68,39 @@ describe.skipIf(process.platform !== "darwin")(
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
mcpTest(
|
||||||
|
"reports undecodable symbols with any Swift mangling prefix as invalid",
|
||||||
|
async ({ mcp, onTestFinished }) => {
|
||||||
|
const target = join(
|
||||||
|
await createTestTempDirectory("rea-demangle-mcp-"),
|
||||||
|
"tool",
|
||||||
|
);
|
||||||
|
await copyFile("/usr/bin/true", target);
|
||||||
|
const client = await openProductionTarget(mcp, onTestFinished, target);
|
||||||
|
const prefixes = ["_T0", "$S", "_$S", "$e", "_$e"];
|
||||||
|
|
||||||
|
const called = await client.callTool({
|
||||||
|
name: "demangle_swift",
|
||||||
|
arguments: {
|
||||||
|
symbols: [
|
||||||
|
...prefixes.map((prefix) => `${prefix}4main3FooV`),
|
||||||
|
...prefixes.map((prefix) => `${prefix}Bogus`),
|
||||||
|
"_Tprintf",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
expect(called.isError, JSON.stringify(called.content)).not.toBe(true);
|
||||||
|
expect(
|
||||||
|
demangledSchema
|
||||||
|
.parse(called.structuredContent)
|
||||||
|
.normalized_result.symbols.map(({ status }) => status),
|
||||||
|
).toEqual([
|
||||||
|
...prefixes.map(() => "demangled"),
|
||||||
|
...prefixes.map(() => "invalid"),
|
||||||
|
"unchanged",
|
||||||
|
]);
|
||||||
|
},
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue