fix(managed): classify ReadyToRun images without ILONLY as modern .NET (#2075)
* fix(managed): classify ReadyToRun images without ILONLY as modern .NET crossgen2 clears COMIMAGE_FLAGS_ILONLY and sets IL_LIBRARY on ReadyToRun output. inspect_managed_artifact checked the clear ILONLY flag before the ReadyToRun signature, so real ReadyToRun assemblies were reported as runtime_family mixed-clr-native and implementation cpp-cli-mixed, and cil-and-ready-to-run was unreachable for crossgen2 output. Check the ReadyToRun signature first; a clear ILONLY flag without it still reports mixed CLR/native code. * test(managed): exhaust capacity through inspected assembly references --------- Co-authored-by: morluto <76467478+morluto@users.noreply.github.com>
This commit is contained in:
parent
9c14999efd
commit
cdc41fc86c
|
|
@ -547,6 +547,63 @@ describe("managed fixture data layout", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("managed implementation classification", () => {
|
||||
it("classifies crossgen2 ReadyToRun output without ILONLY as modern .NET", () => {
|
||||
// crossgen2 writes IL_LIBRARY | STRONGNAMESIGNED and clears ILONLY.
|
||||
const bytes = buildManagedPeFixture({ readyToRun: true, cliFlags: 0xc });
|
||||
const result = inspectManagedArtifactBytes(
|
||||
bytes,
|
||||
managedPeFixtureTarget(bytes),
|
||||
);
|
||||
|
||||
expect(result.classification).toMatchObject({
|
||||
runtime_family: "modern-dotnet",
|
||||
implementation: "cil-and-ready-to-run",
|
||||
});
|
||||
expect(result.classification.evidence).toContainEqual(
|
||||
expect.objectContaining({ code: "ready-to-run-signature-observed" }),
|
||||
);
|
||||
expect(result.classification.evidence).not.toContainEqual(
|
||||
expect.objectContaining({ code: "cli-il-only-clear" }),
|
||||
);
|
||||
});
|
||||
|
||||
it("preserves ReadyToRun runtime identity after metadata capacity is exhausted", () => {
|
||||
const bytes = buildManagedPeFixture({
|
||||
readyToRun: true,
|
||||
cliFlags: 0xc,
|
||||
references: ["x".repeat(12 * 1024 * 1024)],
|
||||
});
|
||||
const result = inspectManagedArtifactBytes(
|
||||
bytes,
|
||||
managedPeFixtureTarget(bytes),
|
||||
);
|
||||
expect(result.classification).toMatchObject({
|
||||
status: "managed",
|
||||
runtime_family: "modern-dotnet",
|
||||
});
|
||||
expect(result.coverage.issues).toContainEqual(
|
||||
expect.objectContaining({ code: "resource-limit" }),
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps a clear ILONLY flag without ReadyToRun as mixed CLR/native", () => {
|
||||
const bytes = buildManagedPeFixture({ cliFlags: 0 });
|
||||
const result = inspectManagedArtifactBytes(
|
||||
bytes,
|
||||
managedPeFixtureTarget(bytes),
|
||||
);
|
||||
|
||||
expect(result.classification).toMatchObject({
|
||||
runtime_family: "mixed-clr-native",
|
||||
implementation: "cpp-cli-mixed",
|
||||
});
|
||||
expect(result.classification.evidence).toContainEqual(
|
||||
expect.objectContaining({ code: "cli-il-only-clear" }),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("managed artifact metadata identity", () => {
|
||||
it("accepts CLI metadata GUIDs without RFC UUID version or variant bits", () => {
|
||||
const bytes = buildManagedPeFixture({
|
||||
|
|
|
|||
|
|
@ -158,6 +158,15 @@ interface RuntimeClassificationInput {
|
|||
readonly inventory: ManagedMetadataInventory;
|
||||
}
|
||||
|
||||
const runtimeFamilyFromCliHeader = (
|
||||
cli: ManagedCliHeader | null,
|
||||
): ManagedArtifactInspection["classification"]["runtime_family"] =>
|
||||
cli?.readyToRunSignature === true
|
||||
? "modern-dotnet"
|
||||
: cli !== null && (cli.flags & 1) === 0
|
||||
? "mixed-clr-native"
|
||||
: "unknown";
|
||||
|
||||
const runtimeFamilyFor = (
|
||||
cli: ManagedCliHeader,
|
||||
inventory: ManagedMetadataInventory,
|
||||
|
|
@ -180,7 +189,9 @@ const runtimeFamilyFor = (
|
|||
);
|
||||
let runtimeFamily: ManagedArtifactInspection["classification"]["runtime_family"] =
|
||||
"unknown";
|
||||
if ((cli.flags & 1) === 0) {
|
||||
// crossgen2 clears ILONLY on ReadyToRun output, so only a clear flag
|
||||
// without the ReadyToRun signature indicates mixed CLR/native code.
|
||||
if (runtimeFamilyFromCliHeader(cli) === "mixed-clr-native") {
|
||||
runtimeFamily = "mixed-clr-native";
|
||||
evidence.push({
|
||||
code: "cli-il-only-clear",
|
||||
|
|
@ -239,8 +250,8 @@ const implementationFor = (
|
|||
cli: ManagedCliHeader,
|
||||
metadata: ManagedMetadataLayout,
|
||||
): ManagedArtifactInspection["classification"]["implementation"] => {
|
||||
if ((cli.flags & 1) === 0) return "cpp-cli-mixed";
|
||||
if (cli.readyToRunSignature) return "cil-and-ready-to-run";
|
||||
if ((cli.flags & 1) === 0) return "cpp-cli-mixed";
|
||||
return (metadata.rowCounts[6] ?? 0) === 0 ? "metadata-only" : "cil";
|
||||
};
|
||||
|
||||
|
|
@ -303,8 +314,7 @@ const partialMetadataResult = ({
|
|||
classification: {
|
||||
status: issue.code === "resource-limit" ? "managed" : "malformed",
|
||||
container: "pe",
|
||||
runtime_family:
|
||||
(layout.cli?.flags ?? 1) & 1 ? "unknown" : "mixed-clr-native",
|
||||
runtime_family: runtimeFamilyFromCliHeader(layout.cli),
|
||||
implementation: "unknown",
|
||||
managed_architecture: "unknown",
|
||||
evidence: [
|
||||
|
|
|
|||
Loading…
Reference in New Issue