Skip to content

cDAC: Loader_1.GetModuleHandles throws on an empty assembly-list slot after a collectible assembly is unloaded #135518

Closed

Description

@pcshrosbree

When a collectible assembly is unloaded, AppDomain::RemoveAssembly (src/coreclr/vm/appdomain.cpp, called from the loader allocator cleanup in loaderallocator.cpp) sets the assembly's slot in the AppDomain's assembly list to NULL. The list's count does not change, and AppDomain::AddAssembly reuses such slots. The native iterator, AppDomain::AssemblyIterator::Next_Unlocked, skips them:

Assembly * pAssembly = dac_cast<PTR_Assembly>(m_Iterator.GetElement());
if (pAssembly == NULL)
{
    continue;
}

Loader_1.GetModuleHandles (src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Loader_1.cs) has no such check and reads a Data.Assembly at every element. When the enumeration reaches an empty slot, it throws a VirtualReadException (reading a field of an Assembly at a null address) instead of returning the remaining modules. GetModuleHandles is the only cDAC reader of this list; it backs ISOSDacInterface.GetAppDomainData and GetAssemblyList, IXCLRDataProcess.StartEnumModules, GetModuleByAddress, StartEnumMethodDefinitionsByAddress and the StartEnumMethodInstancesByAddress / EnumMethodInstanceByAddress enumeration, and DacDbiImpl.EnumerateAssembliesInAppDomain.

The pseudocode in docs/design/datacontracts/Loader.md omits the same check. Separately, it inverts the tenure test for collectible assemblies: it skips the assembly when its module is Tenured, where the native iterator and Loader_1 both skip it when it is not.

Found by reading the code while working on #135516, and reproduced with a cDAC unit test (a mock AppDomain whose assembly list has empty slots); not reproduced against a real process or dump.

Activity

  1. dotnet-policy-service commented on Oct 9, 2026

    @dotnet-policy-service
    Contributor

    Tagging subscribers to this area: @agocke, @elinor-fung
    See info in area-owners.md if you want to be subscribed.

  2. dotnet-policy-service commented on Oct 9, 2026

    @dotnet-policy-service
    Contributor

    Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag
    See info in area-owners.md if you want to be subscribed.

  3. removed
    untriagedNew issue has not been triaged by the area owner
    on Oct 10, 2026
  4. added this to the 11.0.0 milestone on Oct 10, 2026
  5. added a commit that references this issue on Oct 12, 2026
    c5a4e90
  6. added a commit that references this issue on Oct 16, 2026
    70bc56c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions