From 34318813458e2bb81508ecc1cd61d2a1016bfe42 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 21 Feb 2021 18:14:23 +0100 Subject: [PATCH] Fix #2307: potential NRE in IntroduceExtensionMethods --- ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs | 13 +++++++------ .../CSharp/Transforms/IntroduceExtensionMethods.cs | 5 +++-- .../Semantics/ByReferenceResolveResult.cs | 5 ++++- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index fdc13ffda..ae4f23486 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -217,10 +217,11 @@ namespace ICSharpCode.Decompiler.CSharp // Ensure that the IdentifierExpression itself also gets a resolve result, as that might // get used after the 'ref' is stripped away: var elementType = ((ByReferenceType)variable.Type).ElementType; - expr.WithRR(new ILVariableResolveResult(variable, elementType)); + var elementRR = new ILVariableResolveResult(variable, elementType); + expr.WithRR(elementRR); expr = new DirectionExpression(FieldDirection.Ref, expr); - return expr.WithRR(new ByReferenceResolveResult(elementType, ReferenceKind.Ref)); + return expr.WithRR(new ByReferenceResolveResult(elementRR, ReferenceKind.Ref)); } else { @@ -1302,7 +1303,7 @@ namespace ICSharpCode.Decompiler.CSharp .WithILInstruction(inst) .WithRR(new ResolveResult(elementType)); return new DirectionExpression(FieldDirection.Ref, expr) - .WithoutILInstruction().WithRR(new ByReferenceResolveResult(expr.Type, ReferenceKind.Ref)); + .WithoutILInstruction().WithRR(new ByReferenceResolveResult(expr.ResolveResult, ReferenceKind.Ref)); } right = Translate(offsetInst); right = ConvertArrayIndex(right, inst.RightInputType, allowIntPtr: true); @@ -2894,7 +2895,7 @@ namespace ICSharpCode.Decompiler.CSharp { var expr = ConvertField(inst.Field).WithILInstruction(inst); return new DirectionExpression(FieldDirection.Ref, expr) - .WithoutILInstruction().WithRR(new ByReferenceResolveResult(expr.Type, ReferenceKind.Ref)); + .WithoutILInstruction().WithRR(new ByReferenceResolveResult(expr.ResolveResult, ReferenceKind.Ref)); } protected internal override TranslatedExpression VisitLdElema(LdElema inst, TranslationContext context) @@ -2922,7 +2923,7 @@ namespace ICSharpCode.Decompiler.CSharp } TranslatedExpression expr = indexerExpr.WithILInstruction(inst).WithRR(new ResolveResult(arrayType.ElementType)); return new DirectionExpression(FieldDirection.Ref, expr) - .WithoutILInstruction().WithRR(new ByReferenceResolveResult(expr.Type, ReferenceKind.Ref)); + .WithoutILInstruction().WithRR(new ByReferenceResolveResult(expr.ResolveResult, ReferenceKind.Ref)); } TranslatedExpression TranslateArrayIndex(ILInstruction i) @@ -3080,7 +3081,7 @@ namespace ICSharpCode.Decompiler.CSharp Arguments = { Translate(inst.Argument).Expression, new TypeReferenceExpression(ConvertType(inst.Type)) } }.WithRR(new ResolveResult(inst.Type)); return new DirectionExpression(FieldDirection.Ref, expr.WithILInstruction(inst)).WithoutILInstruction() - .WithRR(new ByReferenceResolveResult(inst.Type, ReferenceKind.Ref)); + .WithRR(new ByReferenceResolveResult(expr.ResolveResult, ReferenceKind.Ref)); } protected internal override TranslatedExpression VisitBlock(Block block, TranslationContext context) diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs index 3a3071512..754044666 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs @@ -180,10 +180,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { target = new ConversionResolveResult(method.Parameters[0].Type, crr, Conversion.NullLiteralConversion); } - else if (target is ByReferenceResolveResult brrr) + else if (firstArgument is DirectionExpression de) { - target = brrr.ElementResult; + target = de.Expression.GetResolveResult(); } + Debug.Assert(target != null); ResolveResult[] args = new ResolveResult[invocationExpression.Arguments.Count - 1]; string[] argNames = null; int pos = 0; diff --git a/ICSharpCode.Decompiler/Semantics/ByReferenceResolveResult.cs b/ICSharpCode.Decompiler/Semantics/ByReferenceResolveResult.cs index 97918b33a..215aaa369 100644 --- a/ICSharpCode.Decompiler/Semantics/ByReferenceResolveResult.cs +++ b/ICSharpCode.Decompiler/Semantics/ByReferenceResolveResult.cs @@ -42,7 +42,10 @@ namespace ICSharpCode.Decompiler.Semantics this.ElementResult = elementResult; } - public ByReferenceResolveResult(IType elementType, ReferenceKind kind) + /// + /// Should only be used for temporary ResolveResults in TypeInference and CSharpConversions, etc. + /// + internal ByReferenceResolveResult(IType elementType, ReferenceKind kind) : base(new ByReferenceType(elementType)) { this.ReferenceKind = kind;