Repository navigation
ILVerify: allow family access through implemented interfaces - #136176
Merged
jkotas merged 1 commit intoOct 21, 2026
Merged
Conversation
The ECMA-335 augments for default interface methods let a type that implements an interface access the interface's protected members. The runtime enforces this in ClassLoader::CanAccessFamily: when the target is an interface, access is granted if the caller, or a type that encloses it, has an interface with the same type definition in its interface map. Any instantiation of a generic interface counts. ILVerify's CanAccessFamily only walked base classes, so it reported MethodAccess for these calls. One example is Int32.CreateChecked<TOther>, which calls the protected static abstract method INumberBase<TOther>.TryConvertToChecked. When the target is an interface, look for its type definition among the runtime interfaces of the current type. The rule that a protected instance member is accessed through an instance of the current type is unchanged.
|
Azure Pipelines: Successfully started running 3 pipeline(s). 13 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
Contributor
|
Tagging subscribers to this area: @agocke |
Contributor
|
Tagging subscribers to this area: @JulieLeeMSFT, @dotnet/jit-contrib |
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
The focused implementation preserves existing restrictions, has targeted regression coverage, and has no unresolved findings.
No open issues 🎉
What changed in this PR
Fixes ILVerify’s rejection of protected interface-member calls from implementing types, aligning interface eligibility with the runtime.
Changes:
- Checks implemented interfaces by type definition, including different generic instantiations.
- Preserves existing protected-instance receiver restrictions.
- Adds seven positive and negative IL regression tests.
Builds and tests were not rerun during this review.
| File | Description |
|---|---|
| src/coreclr/tools/ILVerification/AccessVerificationHelpers.cs | Adds interface-aware family-access checks. |
| src/coreclr/tools/ILVerification.Tests/ILTests/AccessTests.il | Covers generic, inherited, nested, and rejected access scenarios. |
Review effort: Balanced
jkotas
approved these changes
Oct 21, 2026
Member
|
/ba-g opened #136205 on the test failure |
This was referenced Oct 21, 2026
Contributor
Author
|
Thank you for the review and merge! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #136175
Change
CanAccessFamilyinAccessVerificationHelpers.cslooked for the target's type definition only among the current type's base types. When the target is an interface, it now looks among the current type'sRuntimeInterfacesinstead, and compares type definitions. This matches the runtime:ClassLoader::CanAccessFamilysearches the caller's interface map by type definition, so any instantiation of a generic interface counts.RuntimeInterfacesincludes interfaces inherited from base classes and from other interfaces. The existing loop over enclosing types covers nested types.The check that a protected instance member is accessed through an instance of the current type runs first, as before. The runtime does not make that check, but ILVerify already applies it to classes, and this change keeps it for interfaces too.
Tests
Seven methods in
ILTests/AccessTests.il, each for one rule:Call.FamilyStaticOfOtherInstantiationIFamilyMembers<Self>callsIFamilyMembers<T>'s protected static method throughconstrained.(theInt32.CreateCheckedshape)Call.FamilyStaticOfInterfaceOfBaseClassCall.FamilyStaticFromNestedTypeCall.FamilyInstanceOfBaseInterfacethisCall.FamilyStaticFromUnrelatedTypeMethodAccessCall.FamilyStaticFromOtherInterfaceMethodAccessCall.FamilyInstanceThroughOtherImplementerMethodAccessMethodAccess. The three invalid tests pass on main and with this change.MethodAccessException. The other-implementer shape passes the runtime's access check, which does not check the instance, and then throwsNullReferenceExceptionfor its null receiver.Measured impact
I scanned with ILVerify built from main and from this branch. The inputs were the shared framework (Microsoft.NETCore.App 10.0.12, 130,146 method bodies) and 388,490 method bodies from four sets of NuGet packages.
MethodAccesserrors, in 41 methods, and 38 of those methods now verify. The remaining error is anldvirtftnofObject.Finalize, which is not an interface member. One method,InlineBufferWriter<T>.GetBuffer, now reportsReturnPtrToStackat itsret. TheMethodAccesserror had stopped ILVerify in the method's first block, before it reached the block containing thatret. The framework results do not change, because the 57 framework calls are in methods that fail earlier withInitLocals.MethodAccesserrors go away, inCreateChecked,CreateSaturatingandCreateTruncatingof 19 numeric types (51 in System.Private.CoreLib, 6 in System.Runtime.Numerics). Those 57 methods now pass. DotNext loses the same 51 errors, and 41 of its methods now pass.Note
This PR was prepared with AI assistance (Anthropic Claude and OpenAI Codex), under my direction. I reviewed it before posting.