mirror of
https://github.com/morluto/rea.git
synced 2026-11-06 23:06:18 +00:00
fix(ghidra): preserve valid Unicode language metadata
Validate XML bytes before shared syntax parsing so literal U+FFFD remains valid while malformed bytes and declaration mismatches fail at their producing boundary. Validation: 92 focused checks, 3 selected fake Apktool boundary checks, 6 final encoding controls, check:fast and docs:check. Ghidra coverage uses tiny real files and descriptors, without a real engine or Windows qualification. Refs #4712
This commit is contained in:
1 parent
623339a7ab
commit
3cfa00a29c
3 files changed
+81
-7
No files matched your search
@@ -1,7 +1,8 @@
|
||||
import { open, readdir } from "node:fs/promises";
|
||||
import type { FileHandle } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import { DOMParser, onWarningStopParsing } from "@xmldom/xmldom";
|
||||
import { parseXmlDocument } from "../domain/xmlDocument.js";
|
||||
import { decodeXmlPlistText } from "../domain/propertyListXmlText.js";
|
||||
|
||||
import type { GhidraLanguageOverride } from "../config/ghidraLanguageOverride.js";
|
||||
import { ConfigurationError } from "../domain/configurationErrors.js";
|
||||
@@ -80,9 +81,12 @@ export const parseGhidraLanguageDefinitions = (
|
||||
text: string,
|
||||
): readonly GhidraLanguageDefinition[] => {
|
||||
const definitions: GhidraLanguageDefinition[] = [];
|
||||
const document = new DOMParser({
|
||||
onError: onWarningStopParsing,
|
||||
}).parseFromString(text, "application/xml");
|
||||
const parsed = parseXmlDocument(text, {
|
||||
doctype: "allow",
|
||||
lineEndings: "normalize",
|
||||
});
|
||||
if (!parsed.ok) throw parsed.error;
|
||||
const document = parsed.value;
|
||||
const root = document.documentElement;
|
||||
if (root?.tagName !== "language_definitions")
|
||||
throw new SyntaxError("Expected Ghidra language_definitions XML root");
|
||||
@@ -164,10 +168,10 @@ export const readGhidraLanguageCatalog = async (
|
||||
if (!entry.endsWith(".ldefs")) continue;
|
||||
const bytes = await readLanguageDefinitionFile(join(directory, entry));
|
||||
if (bytes === undefined) continue;
|
||||
// XML 1.0 section 4.3.3: a leading UTF-8 BOM is an encoding signature,
|
||||
// not document content; TextDecoder consumes it, Buffer#toString does not.
|
||||
// The XML byte owner validates encoding and declaration before syntax
|
||||
// parsing; a literal U+FFFD cannot diagnose invalid source bytes.
|
||||
definitions.push(
|
||||
...parseGhidraLanguageDefinitions(new TextDecoder().decode(bytes)),
|
||||
...parseGhidraLanguageDefinitions(decodeXmlPlistText(bytes)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user