diff --git a/docs/managed-code-analysis.md b/docs/managed-code-analysis.md index d9dea7fff9..7bcd5a0175 100644 --- a/docs/managed-code-analysis.md +++ b/docs/managed-code-analysis.md @@ -575,7 +575,8 @@ exception semantics, and does not replace the raw CIL digest. Cross-build comparison requires equal raw CIL digests as well for exact CIL/signature matches and reports ambiguity when structural evidence is insufficient. -For example, a decoded `nop; ret` body serializes exactly as +For example, a present body (including any valid declared locals signature) +whose IL is `nop; ret` serializes exactly as `[["nop","none",null],["ret","none",null]]` and has digest `5e5fad7741cb44bca3a4f045546b7449990da343f612f5f34c0ca30e9eee0636`. This vector specifies the tuple order, `null` handling, absence of whitespace, diff --git a/src/dotnet/ManagedCilDecoding.test.ts b/src/dotnet/ManagedCilDecoding.test.ts index ed49b5f718..91cfe755f4 100644 --- a/src/dotnet/ManagedCilDecoding.test.ts +++ b/src/dotnet/ManagedCilDecoding.test.ts @@ -211,6 +211,7 @@ describe("managed CIL decoding", () => { fatHeader.writeUInt32LE(il.length, 4); fatHeader.writeUInt32LE(0x1100_0001, 8); const fatBytes = buildManagedPeFixture({ + standaloneSignatures: [Buffer.from([0x07, 0x01, 0x08])], ilBody: Buffer.concat([fatHeader, il]), }); const tiny = inspectManagedMembersBytes( diff --git a/src/dotnet/ManagedSignatureResolution.test.ts b/src/dotnet/ManagedSignatureResolution.test.ts index 4154b4fa90..fe9c423e43 100644 --- a/src/dotnet/ManagedSignatureResolution.test.ts +++ b/src/dotnet/ManagedSignatureResolution.test.ts @@ -104,17 +104,12 @@ describe("resolved member signature digests", () => { expect(forged.raw_sha256).toBe(resolved.resolved_sha256); }); - it.each([ - ["a TypeSpec, whose blob member inspection does not decode", (1 << 2) | 2], - ["a TypeRef row outside its table", (9 << 2) | 1], - ])("does not name %s", (_name, codedIndex) => { - const bytes = buildManagedPeFixture({ - fieldSignature: Buffer.from([0x06, 0x12, codedIndex]), + it("decodes a valid but unnamed non-generic TypeSpec operand", () => { + const inspection = fieldOf({ + typeSpecSignatures: [Buffer.from([0x08])], + fieldSignature: Buffer.from([0x06, 0x12, (1 << 2) | 2]), }); - const field = inspectManagedMembersBytes( - bytes, - managedPeFixtureTarget(bytes), - ).fields[0]; + const field = inspection.fields[0]; expect(field?.signature.parse_status).toBe("decoded"); expect(field?.signature.resolved_sha256).toBeNull(); @@ -271,6 +266,10 @@ describe("type operand names", () => { fieldSignature: Buffer.from([0x06, 0x12, (9 << 2) | 1]), }); + expect(inspection.fields[0]?.signature.parse_status).toBe("malformed"); + expect(inspection.fields[0]?.signature.issue).toContain( + "coded index selects row 9 in table 1, which has 1 rows", + ); expect(inspection.fields[0]?.signature.resolved_sha256).toBeNull(); expect(inspection.coverage.state).toBe("partial"); expect(inspection.coverage.issues).toEqual([