Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CSharpDecompiler: EnumValueDisplayMode does not expect Class, sets to null and throws (ProtoContract issue?) #3108

Closed
StalkR opened this issue Oct 24, 2023 · 2 comments
Labels

Comments

@StalkR
Copy link

StalkR commented Oct 24, 2023

I noticed since version 8.0.0.7106-preview2 up to current master, ilspycmd fails to decompile, complaining about ArgumentOutOfRangeException in CSharpDecompiler.cs:1432 (full stacktrace at the end). It works fine up to version 8.0.0.7007-preview1 then starts crashing.

Just 10 commits between these tags for this file:

$ git log v8.0-preview1..v8.0-preview2 ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs | grep ^commit | wc -l
10

I can share the dll privately if necessary, but the code is basically:

namespace SomeNamespace
{
        public class SomeClass
	{
		[ProtoContract]
		public enum SomeEnum
		{
			Zero,
			One
		}
	}
}

I can reproduce with ILSpy as well, it just fails to decompile this specific enum.

Debugging a bit, it's not expecting decompileRun.EnumValueDisplayMode to be null, coming from this:

				decompileRun.EnumValueDisplayMode = typeDef.Kind == TypeKind.Enum
					? DetectBestEnumValueDisplayMode(typeDef, module.PEFile)
					: null;

In this situation, typeDef.Kind is actually Class.

If I replace null with EnumValueDisplayMode.None for instance, it's able to decompile.

Did you set it on purpose to null to catch this sort of situations and investigate closer? otherwise I can send you this pull request always setting it to EnumValueDisplayMode.None as safe fallback value.

With that exception out of the way, decompilation gives:

[ProtoContract]
public enum SomeEnum
{
	private class SomeNamespace_SomeClass<>SomeEnum<>Actor : IActivator, IActivator<SomeEnum>
	{
		private virtual sealed object CreateInstance()
		{
			return default(SomeEnum);
		}

		object IActivator.CreateInstance()
		{
			//ILSpy generated this explicit interface implementation from .override directive in CreateInstance
			return this.CreateInstance();
		}

		private virtual sealed SomeEnumCreateInstance()
		{
			//IL_000f: Expected I4, but got O
			return (MyLayerMode)(object)default(SomeEnum);
		}

		SomeEnumIActivator<SomeEnum>.CreateInstance()
		{
			//ILSpy generated this explicit interface implementation from .override directive in CreateInstance
			return this.CreateInstance();
		}
	}
	,
	Zero,
	One
}

But I think it shouldn't show this class at all, just the fields.

Maybe this extra class comes from the [ProtoContract] annotation? (protobuf-net most likely)

Thanks for the project and maintaining it ❤️

Error message

System.AggregateException: One or more errors occurred. (Error decompiling @[redacted] [redacted])
 ---> Error decompiling @[redacted] [redacted] in assembly "[redacted]"
 ---> System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
   at ICSharpCode.Decompiler.CSharp.CSharpDecompiler.DoDecompile(ITypeDefinition typeDef, DecompileRun decompileRun, ITypeResolveContext decompilationContext) in CSharpDecompiler.cs:line 1432
-- continuing with outer exception (ICSharpCode.Decompiler.DecompilerException) --
   at ICSharpCode.Decompiler.CSharp.CSharpDecompiler.DoDecompile(ITypeDefinition typeDef, DecompileRun decompileRun, ITypeResolveContext decompilationContext) in CSharpDecompiler.cs:line 1440
   at ICSharpCode.Decompiler.CSharp.CSharpDecompiler.<>c__DisplayClass74_0.<DoDecompile>g__DoDecompileMember|0(IEntity entity, RecordDecompiler recordDecompiler, PartialTypeInfo partialType) in CSharpDecompiler.cs:line 1491
   at ICSharpCode.Decompiler.CSharp.CSharpDecompiler.DoDecompile(ITypeDefinition typeDef, DecompileRun decompileRun, ITypeResolveContext decompilationContext) in CSharpDecompiler.cs:line 1368
   at ICSharpCode.Decompiler.CSharp.CSharpDecompiler.DoDecompileTypes(IEnumerable`1 types, DecompileRun decompileRun, ITypeResolveContext decompilationContext, SyntaxTree syntaxTree) in CSharpDecompiler.cs:line 651
   at ICSharpCode.Decompiler.CSharp.CSharpDecompiler.DecompileTypes(IEnumerable`1 types) in CSharpDecompiler.cs:line 950
   at ICSharpCode.Decompiler.CSharp.ProjectDecompiler.WholeProjectDecompiler.<>c__DisplayClass46_0.<WriteCodeFilesInProject>b__5(IGrouping`2 file) in WholeProjectDecompiler.cs:line 274
   at System.Threading.Tasks.Parallel.<>c__DisplayClass44_0`2.<PartitionerForEachWorker>b__1(IEnumerator& partitionState, Int32 timeout, Boolean& replicationDelegateYieldedBeforeCompletion) in offset 259
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() in offset 17
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw(Exception source) in offset 0
   at System.Threading.Tasks.Parallel.<>c__DisplayClass44_0`2.<PartitionerForEachWorker>b__1(IEnumerator& partitionState, Int32 timeout, Boolean& replicationDelegateYieldedBeforeCompletion) in offset 609
   at System.Threading.Tasks.TaskReplicator.Replica`1.ExecuteAction(Boolean& yieldedBeforeCompletion) in offset 0
   at System.Threading.Tasks.TaskReplicator.Replica.Execute() in offset 0
   --- End of inner exception stack trace ---
   at System.Threading.Tasks.TaskReplicator.Run[TState](ReplicatableUserAction`1 action, ParallelOptions options, Boolean stopOnFirstFailure)
   at System.Threading.Tasks.Parallel.PartitionerForEachWorker[TSource,TLocal](Partitioner`1 source, ParallelOptions parallelOptions, Action`1 simpleBody, Action`2 bodyWithState, Action`3 bodyWithStateAndIndex, Func`4 bodyWithStateAndLocal, Func`5 bodyWithEverything, Func`1 localInit, Action`1 localFinally)
--- End of stack trace from previous location ---
   at System.Threading.Tasks.Parallel.ThrowSingleCancellationExceptionOrOtherException(ICollection exceptions, CancellationToken cancelToken, Exception otherException)
   at System.Threading.Tasks.Parallel.PartitionerForEachWorker[TSource,TLocal](Partitioner`1 source, ParallelOptions parallelOptions, Action`1 simpleBody, Action`2 bodyWithState, Action`3 bodyWithStateAndIndex, Func`4 bodyWithStateAndLocal, Func`5 bodyWithEverything, Func`1 localInit, Action`1 localFinally)
   at System.Threading.Tasks.Parallel.ForEach[TSource](Partitioner`1 source, ParallelOptions parallelOptions, Action`1 body)
   at ICSharpCode.Decompiler.CSharp.ProjectDecompiler.WholeProjectDecompiler.<>c__DisplayClass46_0.<WriteCodeFilesInProject>g__ProcessFiles|3(List`1 files) in /_/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs:line 255
   at ICSharpCode.Decompiler.CSharp.ProjectDecompiler.WholeProjectDecompiler.WriteCodeFilesInProject(PEFile module, IList`1 partialTypes, CancellationToken cancellationToken) in /_/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs:line 221
   at ICSharpCode.Decompiler.CSharp.ProjectDecompiler.WholeProjectDecompiler.DecompileProject(PEFile moduleDefinition, String targetDirectory, TextWriter projectFileWriter, CancellationToken cancellationToken) in /_/ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs:line 154
   at ICSharpCode.ILSpyCmd.ILSpyCmdProgram.DecompileAsProject(String assemblyFileName, String projectFileName) in D:\a\ILSpy\ILSpy\ICSharpCode.ILSpyCmd\IlspyCmdProgram.cs:line 318
   at ICSharpCode.ILSpyCmd.ILSpyCmdProgram.OnExecuteAsync(CommandLineApplication app) in D:\a\ILSpy\ILSpy\ICSharpCode.ILSpyCmd\IlspyCmdProgram.cs:line 147
@StalkR StalkR added the Bug label Oct 24, 2023
@siegfriedpammer
Copy link
Member

I have a hard time reproducing the exact issue. Would you be able to provide the assembly in question? Thanks!

@StalkR
Copy link
Author

StalkR commented Nov 3, 2023

Thanks much!

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 2, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants