microsoft / microsoft/VSExtensibility
Static constructor mistakenly selected at Extension instantiation
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
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
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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