mirror of
https://github.com/morluto/rea
synced 2026-10-25 22:08:11 -04:00
fix(pe): retain resource directory branch identities
This commit is contained in:
@@ -203,6 +203,10 @@ reported. Directory headers, entries, data entries and payloads retain original
|
||||
file offsets and lengths. Each opaque payload has its own SHA-256; code page and
|
||||
reserved data-entry fields are preserved.
|
||||
|
||||
Each `directories[]` row retains its incoming identity `path` and corresponding
|
||||
`entry_locations`, including branches with no payload leaves. The root has empty
|
||||
arrays; a type branch has one identity and a name branch has two.
|
||||
|
||||
RT_GROUP_ICON records expose original image descriptors and RT_ICON candidates.
|
||||
A reference resolves only when an icon with the same numeric ID and language
|
||||
exists. Missing references, other-language candidates and declared-size mismatch
|
||||
|
||||
@@ -65,6 +65,8 @@ export const peResourcesSchema = z.strictObject({
|
||||
.nullable(),
|
||||
directories: z.array(
|
||||
z.strictObject({
|
||||
path: z.array(identity).max(2),
|
||||
entry_locations: z.array(range).max(2),
|
||||
location: range,
|
||||
characteristics: uint,
|
||||
timestamp: uint,
|
||||
|
||||
@@ -143,6 +143,39 @@ describe("portable PE resource parsing", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it.each([10, 11, "named type"])(
|
||||
"retains identity and incoming entry ranges for empty branch %s",
|
||||
async (type) => {
|
||||
const fixture = peResourceFixture(false, [
|
||||
{ type, name: 7, language: 1033, payload: Buffer.from("control") },
|
||||
]);
|
||||
const populated = peResourcesSchema.parse(await parse(fixture.bytes));
|
||||
expect(populated.resources[0]?.type).toMatchObject(
|
||||
typeof type === "number"
|
||||
? { kind: "id", id: type }
|
||||
: { kind: "name", name: type },
|
||||
);
|
||||
// Empty the type directory while retaining its incoming root entry.
|
||||
const typeDirectory = fixture.directoryOffsets[1]!;
|
||||
fixture.bytes.writeUInt16LE(0, typeDirectory + 12);
|
||||
fixture.bytes.writeUInt16LE(0, typeDirectory + 14);
|
||||
const report = peResourcesSchema.parse(await parse(fixture.bytes));
|
||||
expect(report.resources).toEqual([]);
|
||||
expect(report.directories.map(({ path }) => path)).toEqual([
|
||||
[],
|
||||
[populated.resources[0]!.type],
|
||||
]);
|
||||
expect(report.directories[1]?.entry_locations).toEqual([
|
||||
populated.resources[0]!.entry_locations[0],
|
||||
]);
|
||||
expect(report.coverage).toEqual({
|
||||
status: "complete",
|
||||
examined_entries: 1,
|
||||
resources: 0,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
it.each([
|
||||
[
|
||||
"truncated directory",
|
||||
|
||||
@@ -132,6 +132,8 @@ export const parsePeResources = async (
|
||||
examined += count;
|
||||
relative(at, 16 + 8 * count);
|
||||
const directory = {
|
||||
path,
|
||||
entry_locations: entryLocations,
|
||||
location: recordRange(header, 16 + 8 * count, "directory"),
|
||||
characteristics: bytes.readUInt32LE(header),
|
||||
timestamp: bytes.readUInt32LE(header + 4),
|
||||
|
||||
Reference in New Issue
Block a user