Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4ff226e98e | ||
|
|
9f30b01387 | ||
|
|
707797d80f |
No files matched your search
@@ -103,3 +103,39 @@ describe("read-only NativeAOT PE parser", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("NativeAOT PE section virtual extent", () => {
|
||||||
|
const TEXT_VIRTUAL_SIZE = 0x188 + 8;
|
||||||
|
const RDATA_VIRTUAL_SIZE = 0x188 + 40 + 8;
|
||||||
|
const parseWithVirtualSize = (at: number, virtualSize: number) => {
|
||||||
|
const bytes = nativeAotPeFixture();
|
||||||
|
bytes.writeUInt32LE(virtualSize, at);
|
||||||
|
return parseNativeAotPe(
|
||||||
|
bytes,
|
||||||
|
nativeAotPeDigest(bytes),
|
||||||
|
SUMMARY_BUDGET,
|
||||||
|
"0x140000000",
|
||||||
|
).summary;
|
||||||
|
};
|
||||||
|
|
||||||
|
it("does not treat raw padding past VirtualSize as executable code", () => {
|
||||||
|
// The 0x2280 MethodTable's only slot targets 0x1040, past .text's 0x40 bytes.
|
||||||
|
expect(parseWithVirtualSize(TEXT_VIRTUAL_SIZE, 0x40)).toMatchObject({
|
||||||
|
method_tables: 2,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not read a frozen string from raw padding past VirtualSize", () => {
|
||||||
|
expect(parseWithVirtualSize(RDATA_VIRTUAL_SIZE, 0x300)).toMatchObject({
|
||||||
|
status: "partial",
|
||||||
|
frozen_strings: [],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("maps raw bytes when VirtualSize is zero, as the image loader does", () => {
|
||||||
|
expect(parseWithVirtualSize(TEXT_VIRTUAL_SIZE, 0)).toMatchObject({
|
||||||
|
status: "complete",
|
||||||
|
method_tables: 3,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -366,6 +366,13 @@ const parsedSummary = (
|
|||||||
readTypeDetail: () => undefined,
|
readTypeDetail: () => undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// The image loader maps VirtualSize bytes, using SizeOfRawData only when
|
||||||
|
// VirtualSize is zero. Raw bytes past that extent are file-alignment padding.
|
||||||
|
const virtualExtent = (section: Section): number =>
|
||||||
|
section.virtualSize === 0 ? section.rawSize : section.virtualSize;
|
||||||
|
const fileBackedExtent = (section: Section): number =>
|
||||||
|
Math.min(section.rawSize, virtualExtent(section));
|
||||||
|
|
||||||
class PeImage {
|
class PeImage {
|
||||||
readonly imageBase: bigint;
|
readonly imageBase: bigint;
|
||||||
readonly sizeOfImage: number;
|
readonly sizeOfImage: number;
|
||||||
@@ -417,10 +424,7 @@ class PeImage {
|
|||||||
});
|
});
|
||||||
for (const section of this.sections) {
|
for (const section of this.sections) {
|
||||||
this.#range(section.rawOffset, section.rawSize);
|
this.#range(section.rawOffset, section.rawSize);
|
||||||
if (
|
if (section.rva + virtualExtent(section) > this.sizeOfImage)
|
||||||
section.rva + Math.max(section.virtualSize, section.rawSize) >
|
|
||||||
this.sizeOfImage
|
|
||||||
)
|
|
||||||
throw new Error("PE section exceeds the declared image extent");
|
throw new Error("PE section exceeds the declared image extent");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -456,11 +460,11 @@ class PeImage {
|
|||||||
for (const section of this.sections) {
|
for (const section of this.sections) {
|
||||||
if (this.#budget !== undefined && !this.#budget.consumeWork(1))
|
if (this.#budget !== undefined && !this.#budget.consumeWork(1))
|
||||||
return null;
|
return null;
|
||||||
const extent = Math.max(section.virtualSize, section.rawSize);
|
const extent = virtualExtent(section);
|
||||||
if (relative < section.rva || relative - section.rva > extent - size)
|
if (relative < section.rva || relative - section.rva > extent - size)
|
||||||
continue;
|
continue;
|
||||||
const delta = relative - section.rva;
|
const delta = relative - section.rva;
|
||||||
if (delta > section.rawSize - size) return null;
|
if (delta > fileBackedExtent(section) - size) return null;
|
||||||
const offset = section.rawOffset + delta;
|
const offset = section.rawOffset + delta;
|
||||||
return this.#bytes.subarray(offset, offset + size);
|
return this.#bytes.subarray(offset, offset + size);
|
||||||
}
|
}
|
||||||
@@ -475,7 +479,7 @@ class PeImage {
|
|||||||
if (
|
if (
|
||||||
(section.characteristics & 0x20000000) !== 0 &&
|
(section.characteristics & 0x20000000) !== 0 &&
|
||||||
rva >= BigInt(section.rva) &&
|
rva >= BigInt(section.rva) &&
|
||||||
rva < BigInt(section.rva + section.rawSize)
|
rva < BigInt(section.rva + virtualExtent(section))
|
||||||
)
|
)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -492,10 +496,7 @@ class PeImage {
|
|||||||
if (this.#budget !== undefined && !this.#budget.consumeWork(1)) return 0;
|
if (this.#budget !== undefined && !this.#budget.consumeWork(1)) return 0;
|
||||||
if (
|
if (
|
||||||
rva >= BigInt(candidate.rva) &&
|
rva >= BigInt(candidate.rva) &&
|
||||||
rva <
|
rva < BigInt(candidate.rva + virtualExtent(candidate))
|
||||||
BigInt(
|
|
||||||
candidate.rva + Math.max(candidate.virtualSize, candidate.rawSize),
|
|
||||||
)
|
|
||||||
) {
|
) {
|
||||||
section = candidate;
|
section = candidate;
|
||||||
break;
|
break;
|
||||||
@@ -503,9 +504,7 @@ class PeImage {
|
|||||||
}
|
}
|
||||||
return section === undefined
|
return section === undefined
|
||||||
? 0
|
? 0
|
||||||
: section.rva +
|
: section.rva + virtualExtent(section) - Number(rva);
|
||||||
Math.max(section.virtualSize, section.rawSize) -
|
|
||||||
Number(rva);
|
|
||||||
}
|
}
|
||||||
#range(offset: number, size: number): void {
|
#range(offset: number, size: number): void {
|
||||||
if (
|
if (
|
||||||
@@ -602,7 +601,7 @@ const findDirectory = (
|
|||||||
)
|
)
|
||||||
continue;
|
continue;
|
||||||
const begin = section.rawOffset;
|
const begin = section.rawOffset;
|
||||||
const end = begin + section.rawSize;
|
const end = begin + fileBackedExtent(section);
|
||||||
const first = (begin + 7) & ~7;
|
const first = (begin + 7) & ~7;
|
||||||
const candidateBytes =
|
const candidateBytes =
|
||||||
first <= end - 16 ? (Math.floor((end - 16 - first) / 8) + 1) * 8 : 0;
|
first <= end - 16 ? (Math.floor((end - 16 - first) / 8) + 1) * 8 : 0;
|
||||||
@@ -970,10 +969,10 @@ const discoverTables = (
|
|||||||
(section.characteristics & 0x20000000) !== 0
|
(section.characteristics & 0x20000000) !== 0
|
||||||
)
|
)
|
||||||
continue;
|
continue;
|
||||||
if (section.rawSize > 0) {
|
if (fileBackedExtent(section) > 0) {
|
||||||
ranges.push({
|
ranges.push({
|
||||||
start: image.addressForRva(section.rva),
|
start: image.addressForRva(section.rva),
|
||||||
end: image.addressForRva(section.rva + section.rawSize),
|
end: image.addressForRva(section.rva + fileBackedExtent(section)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -984,9 +983,7 @@ const discoverTables = (
|
|||||||
(candidate.characteristics & 0x20000000) === 0 &&
|
(candidate.characteristics & 0x20000000) === 0 &&
|
||||||
hydrated.base >= image.addressForRva(candidate.rva) &&
|
hydrated.base >= image.addressForRva(candidate.rva) &&
|
||||||
hydrated.base + BigInt(hydrated.sizeBytes) <=
|
hydrated.base + BigInt(hydrated.sizeBytes) <=
|
||||||
image.addressForRva(
|
image.addressForRva(candidate.rva + virtualExtent(candidate)),
|
||||||
candidate.rva + Math.max(candidate.virtualSize, candidate.rawSize),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
if (section !== undefined)
|
if (section !== undefined)
|
||||||
ranges.push({
|
ranges.push({
|
||||||
@@ -1592,11 +1589,10 @@ export const parseNativeAotPe = (
|
|||||||
? "raw-image-pointer-scan"
|
? "raw-image-pointer-scan"
|
||||||
: "raw-image-and-rehydrated-pointer-scan",
|
: "raw-image-and-rehydrated-pointer-scan",
|
||||||
},
|
},
|
||||||
diagnostics: [
|
diagnostics:
|
||||||
...(hydrationError === null
|
hydrationError === null
|
||||||
? []
|
? []
|
||||||
: [`Read-only hydration stopped: ${hydrationError}`]),
|
: [`Read-only hydration stopped: ${hydrationError}`],
|
||||||
],
|
|
||||||
limitations: reportLimitations,
|
limitations: reportLimitations,
|
||||||
};
|
};
|
||||||
if (Buffer.byteLength(JSON.stringify(summary)) > maximumSummaryBytes)
|
if (Buffer.byteLength(JSON.stringify(summary)) > maximumSummaryBytes)
|
||||||
|
|||||||
Reference in new issue
Block a user