microsoft / microsoft/VSExtensibility

Static constructor mistakenly selected at Extension instantiation

Open Beginner friendly
#522 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C#
Stars
440
Forks
63
Avg merge
2d 12h
Merged PRs (30d)
1

Description

Description

Extension invocation fails when the target extension class contains a static constructor.

Problem

When retrieving constructors via TypeInfo and using them to instantiate a class, the method FindServiceFactoryConstructor currently uses LINQ's FirstOrDefault without filtering out static constructors.
As a result, if the target class contains a static constructor, it may be selected—even when instance constructors are present—leading to incorrect behavior during instantiation.

// Extract Source code by Visual Studio
private ConstructorInfo FindServiceFactoryConstructor(TypeInfo typeInfo, string typeName)
{
  IsolatedUtilities.RequiresNotNull(typeInfo, "typeInfo");
  IsolatedUtilities.RequiresNotNullOrEmpty(typeName, "typeName");
  if (typeInfo.GetInterface(typeName) == null)
  {
    return null;
  }
  return (from ctor in typeInfo.DeclaredConstructors
			let parameters = ctor.GetParameters()
			where parameters.Length == 0
			select ctor).FirstOrDefault();
}

This causes the method to potentially return a static constructor, which cannot be used to create an instance.

In TryGetServiceFactoryDetailsAsync, this method incorrectly selects the static constructor, and when attempting to instantiate the class a System.MemberAccessException is thrown.

Therefore, extension classes that contains a static constructor call will fail.

Call stack
System.Private.CoreLib.dll!System.Reflection.RuntimeConstructorInfo.ThrowNoInvokeException()	Unknown
Microsoft.ServiceHub.HostStub.dll!Microsoft.ServiceHub.HostStub.ServiceManager.TryGetServiceFactoryDetailsAsync(Microsoft.ServiceHub.Utility.ServiceModuleInfo smi, System.Type serviceModuleType)	Unknown
Microsoft.ServiceHub.HostStub.dll!Microsoft.ServiceHub.HostStub.ServiceManager.CreateAndConfigureServiceAsync(Microsoft.ServiceHub.Utility.ServiceModuleInfo smi, System.Type serviceModuleType, System.IO.Stream stream, string serializedServiceActivationOptions, System.Threading.CancellationTokenSource cts)	Unknown
Microsoft.ServiceHub.HostStub.dll!Microsoft.ServiceHub.HostStub.ServiceManager.StartServiceAsync.AnonymousMethod__0(System.IO.Stream stream, System.Threading.CancellationTokenSource cts)	Unknown
Microsoft.ServiceHub.HostStub.dll!Microsoft.ServiceHub.HostStub.ServiceManager.StartServiceAsync.AnonymousMethod__0(System.IO.Stream stream)	Unknown
Microsoft.ServiceHub.HostStub.dll!Microsoft.ServiceHub.Utility.Server.ClientConnected(Microsoft.ServiceHub.Utility.WrappedStream stream)	Unknown
Microsoft.ServiceHub.HostStub.dll!Microsoft.ServiceHub.Utility.NamedPipeServer..ctor.AnonymousMethod__0()	Unknown
[Resuming Async Method]	
System.Private.CoreLib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.Threading.Tasks.VoidTaskResult>.AsyncStateMachineBox<Microsoft.ServiceHub.Utility.NamedPipeServer.ExecutionContextCallback(object s)	Unknown
System.Private.CoreLib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state)	Unknown
System.Private.CoreLib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.Threading.Tasks.VoidTaskResult>.AsyncStateMachineBox<Microsoft.ServiceHub.Utility.NamedPipeServer.MoveNext(System.Threading.Thread threadPoolThread)	Unknown
System.Private.CoreLib.dll!System.Runtime.CompilerServices.AsyncTaskMethodBuilder<System.Threading.Tasks.VoidTaskResult>.AsyncStateMachineBox<Microsoft.ServiceHub.Utility.NamedPipeServer.MoveNext()	Unknown
System.Private.CoreLib.dll!System.Runtime.CompilerServices.TaskAwaiter.OutputWaitEtwEvents.AnonymousMethod__12_0(System.Action innerContinuation, System.Threading.Tasks.Task innerTask)	Unknown
System.Private.CoreLib.dll!System.Threading.Tasks.AwaitTaskContinuation.RunOrScheduleAction(System.Action action, bool allowInlining)	Unknown
System.Private.CoreLib.dll!System.Threading.Tasks.Task.RunContinuations(object continuationObject)	Unknown
System.Private.CoreLib.dll!System.Threading.Tasks.Task.TrySetResult()	Unknown
System.Private.CoreLib.dll!System.Threading.Tasks.ValueTask.ValueTaskSourceAsTask..cctor.AnonymousMethod__4_0(object state)	Unknown
System.Private.CoreLib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch()	Unknown
System.Private.CoreLib.dll!System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()	Unknown
[Async Call Stack]	
[Async] System.Private.CoreLib.dll!System.Threading.Tasks.Task.Run	Unknown
[Async] System.Private.CoreLib.dll!System.Threading.Tasks.Task.WhenAny	Unknown
[Async] Microsoft.ServiceHub.HostStub.dll!Microsoft.ServiceHub.Utility.NamedPipeServer.DisposeAsyncCore()	Unknown
Image
Suggest for fix

Update the LINQ query to explicitly filter out static constructors by checking:

return (from ctor in typeInfo.DeclaredConstructors 
        where ctor.GetParameters().Length == 0 && !ctor.IsStatic
        select ctor).FirstOrDefault();

return typeInfo.DeclaredConstructors
    .Where(ctor => ctor.GetParameters().Length == 0 && !ctor.IsStatic)
    .FirstOrDefault();

This ensures that only instance constructors are considered when selecting the appropriate constructor for instantiation.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating FindServiceFactoryConstructor and reviewing its use from TryGetServiceFactoryDetailsAsync. Reproduce the case with an extension class containing a static constructor and an instance constructor, then verify that constructor selection excludes static constructors and instantiation no longer throws System.MemberAccessException.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
devtools
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
65/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.