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

casting interface + null-conditional == uncompilable #2230

Closed
Hefaistos68 opened this issue Nov 27, 2020 · 1 comment
Closed

casting interface + null-conditional == uncompilable #2230

Hefaistos68 opened this issue Nov 27, 2020 · 1 comment
Labels
Bug Decompiler The decompiler engine itself
Milestone

Comments

@Hefaistos68
Copy link

Decompiled PaintDotNet.Core.dll from the Paint.Net app (getpaint.net) which leaves me with two issues: here is the first one, the other one is a call into a base method that doesnt exist, but actually should be a call into a ctor in the base.

This is not valid code:

	((schema as IObjectRef)?)?.Dispose();
	((id as IObjectRef)?)?.Dispose();
	((value as IObjectRef)?)?.Dispose();

Input code

The IL code in question:

	.method family hidebysig virtual 
		instance void Dispose (
			bool disposing
		) cil managed 
	{
		// Method begins at RVA 0x2a300
		// Code size 104 (0x68)
		.maxstack 2
		.locals init (
			[0] class [PaintDotNet.Base]PaintDotNet.ComponentModel.IObjectRef schemaRef,
			[1] class [PaintDotNet.Base]PaintDotNet.ComponentModel.IObjectRef idRef,
			[2] class [PaintDotNet.Base]PaintDotNet.ComponentModel.IObjectRef valueRef
		)

		// sequence point: (line 46, col 13) to (line 46, col 27) in D:\src\pdn\src\Core\Imaging\MetadataItem.cs
		IL_0000: ldarg.1
		IL_0001: brfalse.s IL_004b

		// sequence point: (line 48, col 17) to (line 48, col 57) in D:\src\pdn\src\Core\Imaging\MetadataItem.cs
		IL_0003: ldarg.0
		IL_0004: ldfld object PaintDotNet.Imaging.MetadataItem::schema
		IL_0009: isinst [PaintDotNet.Base]PaintDotNet.ComponentModel.IObjectRef
		IL_000e: stloc.0
		IL_000f: ldloc.0
		IL_0010: brfalse.s IL_001b

		// sequence point: (line 50, col 21) to (line 50, col 42) in D:\src\pdn\src\Core\Imaging\MetadataItem.cs
		IL_0012: ldloc.0
		IL_0013: brfalse.s IL_001b

		IL_0015: ldloc.0
		IL_0016: callvirt instance void [mscorlib]System.IDisposable::Dispose()

		// sequence point: (line 53, col 17) to (line 53, col 49) in D:\src\pdn\src\Core\Imaging\MetadataItem.cs
		IL_001b: ldarg.0
		IL_001c: ldfld object PaintDotNet.Imaging.MetadataItem::id
		IL_0021: isinst [PaintDotNet.Base]PaintDotNet.ComponentModel.IObjectRef
		IL_0026: stloc.1
		IL_0027: ldloc.1
		IL_0028: brfalse.s IL_0033

		// sequence point: (line 55, col 21) to (line 55, col 38) in D:\src\pdn\src\Core\Imaging\MetadataItem.cs
		IL_002a: ldloc.1
		IL_002b: brfalse.s IL_0033

		IL_002d: ldloc.1
		IL_002e: callvirt instance void [mscorlib]System.IDisposable::Dispose()

		// sequence point: (line 58, col 17) to (line 58, col 55) in D:\src\pdn\src\Core\Imaging\MetadataItem.cs
		IL_0033: ldarg.0
		IL_0034: ldfld object PaintDotNet.Imaging.MetadataItem::'value'
		IL_0039: isinst [PaintDotNet.Base]PaintDotNet.ComponentModel.IObjectRef
		IL_003e: stloc.2
		IL_003f: ldloc.2
		IL_0040: brfalse.s IL_004b

		// sequence point: (line 60, col 21) to (line 60, col 41) in D:\src\pdn\src\Core\Imaging\MetadataItem.cs
		IL_0042: ldloc.2
		IL_0043: brfalse.s IL_004b

		IL_0045: ldloc.2
		IL_0046: callvirt instance void [mscorlib]System.IDisposable::Dispose()

		// sequence point: (line 64, col 13) to (line 64, col 32) in D:\src\pdn\src\Core\Imaging\MetadataItem.cs
		IL_004b: ldarg.0
		IL_004c: ldnull
		IL_004d: stfld object PaintDotNet.Imaging.MetadataItem::schema
		// sequence point: (line 65, col 13) to (line 65, col 28) in D:\src\pdn\src\Core\Imaging\MetadataItem.cs
		IL_0052: ldarg.0
		IL_0053: ldnull
		IL_0054: stfld object PaintDotNet.Imaging.MetadataItem::id
		// sequence point: (line 66, col 13) to (line 66, col 31) in D:\src\pdn\src\Core\Imaging\MetadataItem.cs
		IL_0059: ldarg.0
		IL_005a: ldnull
		IL_005b: stfld object PaintDotNet.Imaging.MetadataItem::'value'
		// sequence point: (line 68, col 13) to (line 68, col 37) in D:\src\pdn\src\Core\Imaging\MetadataItem.cs
		IL_0060: ldarg.0
		IL_0061: ldarg.1
		IL_0062: call instance void [PaintDotNet.Base]PaintDotNet.Disposable::Dispose(bool)
		// sequence point: (line 69, col 9) to (line 69, col 10) in D:\src\pdn\src\Core\Imaging\MetadataItem.cs
		IL_0067: ret
	} // end of method MetadataItem::Dispose

Erroneous output

	protected override void Dispose(bool disposing)
	{
		if (disposing)
		{
			((schema as IObjectRef)?)?.Dispose();
			((id as IObjectRef)?)?.Dispose();
			((value as IObjectRef)?)?.Dispose();
		}
		schema = null;
		id = null;
		value = null;
		base.Dispose(disposing);
	}

Details

  • Product in use: ILSpy VS extension
  • Version in use: ILSpy version 6.2.1.6137
    decompilation for C# 8.0,
@Hefaistos68 Hefaistos68 added Bug Decompiler The decompiler engine itself labels Nov 27, 2020
@siegfriedpammer
Copy link
Member

When selecting C# 5.0, the output looks like this:

protected override void Dispose(bool disposing)
{
	if (disposing)
	{
		IObjectRef schemaRef = schema as IObjectRef;
		if (schemaRef != null && schemaRef != null)
		{
			schemaRef.Dispose();
		}
		IObjectRef idRef = id as IObjectRef;
		if (idRef != null && idRef != null)
		{
			idRef.Dispose();
		}
		IObjectRef valueRef = value as IObjectRef;
		if (valueRef != null && valueRef != null)
		{
			valueRef.Dispose();
		}
	}
	schema = null;
	id = null;
	value = null;
	base.Dispose(disposing);
}

The problem seems to be the duplication of br.false instructions such as:

	IL_000f: ldloc.0
	IL_0010: brfalse.s IL_001b

	// sequence point: (line 50, col 21) to (line 50, col 42) in D:\src\pdn\src\Core\Imaging\MetadataItem.cs
	IL_0012: ldloc.0
	IL_0013: brfalse.s IL_001b

No idea, why or how this code was generated. For the null conditional operator, we should probably implement some simplification transform, e. g., expr??.member => expr?.member.

@siegfriedpammer siegfriedpammer added this to the v7.0-p2 milestone Nov 30, 2020
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 29, 2021
ElektroKill added a commit to dnSpyEx/ILSpy that referenced this issue Aug 10, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug Decompiler The decompiler engine itself
Projects
None yet
Development

No branches or pull requests

2 participants