Browse Source

Fix #2305: Cast to integer type where necessary in managed pointer arithmetic.

pull/2308/head
Daniel Grunwald 4 years ago
parent
commit
51b3cf51c6
  1. 5
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs
  2. 39
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  3. 2
      ICSharpCode.Decompiler/TypeSystem/INamedElement.cs

5
ICSharpCode.Decompiler.Tests/TestCases/Pretty/UnsafeCode.cs

@ -537,6 +537,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -537,6 +537,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
}
#endif
private unsafe static int Issue2305(StructWithFixedSizeMembers value, StringComparison s)
{
return value.Integers[(int)s];
}
private unsafe static void* CastToVoidPtr(IntPtr intptr)
{
return (void*)intptr;

39
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -1297,16 +1297,20 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1297,16 +1297,20 @@ namespace ICSharpCode.Decompiler.CSharp
fieldAccess.RemoveAnnotations<ResolveResult>();
var result = fieldAccess.WithRR(new MemberResolveResult(mrr.TargetResult, mrr.Member, new PointerType(elementType)))
.WithILInstruction(inst);
TranslatedExpression expr = new IndexerExpression(result.Expression, Translate(offsetInst).Expression)
right = TranslateArrayIndex(offsetInst);
TranslatedExpression expr = new IndexerExpression(result.Expression, right.Expression)
.WithILInstruction(inst)
.WithRR(new ResolveResult(elementType));
return new DirectionExpression(FieldDirection.Ref, expr)
.WithoutILInstruction().WithRR(new ByReferenceResolveResult(expr.Type, ReferenceKind.Ref));
}
return CallUnsafeIntrinsic(name, new[] { left.Expression, Translate(offsetInst).Expression }, brt, inst);
right = Translate(offsetInst);
right = ConvertArrayIndex(right, inst.RightInputType, allowIntPtr: true);
return CallUnsafeIntrinsic(name, new[] { left.Expression, right.Expression }, brt, inst);
}
else
{
right = ConvertArrayIndex(right, inst.RightInputType, allowIntPtr: true);
return CallUnsafeIntrinsic(name + "ByteOffset", new[] { left.Expression, right.Expression }, brt, inst);
}
}
@ -1324,13 +1328,16 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1324,13 +1328,16 @@ namespace ICSharpCode.Decompiler.CSharp
ILInstruction offsetInst = PointerArithmeticOffset.Detect(inst.Left, brt.ElementType, inst.CheckForOverflow);
if (offsetInst != null)
{
left = Translate(offsetInst);
left = ConvertArrayIndex(left, inst.LeftInputType, allowIntPtr: true);
return CallUnsafeIntrinsic("Add", new[] {
new NamedArgumentExpression("elementOffset", Translate(offsetInst)),
new NamedArgumentExpression("elementOffset", left),
new NamedArgumentExpression("source", right)
}, brt, inst);
}
else
{
left = ConvertArrayIndex(left, inst.LeftInputType, allowIntPtr: true);
return CallUnsafeIntrinsic("AddByteOffset", new[] {
new NamedArgumentExpression("byteOffset", left.Expression),
new NamedArgumentExpression("source", right)
@ -2921,11 +2928,31 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2921,11 +2928,31 @@ namespace ICSharpCode.Decompiler.CSharp
TranslatedExpression TranslateArrayIndex(ILInstruction i)
{
var input = Translate(i);
if (i.ResultType == StackType.I4 && input.Type.IsSmallIntegerType() && input.Type.Kind != TypeKind.Enum)
return ConvertArrayIndex(input, i.ResultType, allowIntPtr: false);
}
TranslatedExpression ConvertArrayIndex(TranslatedExpression input, StackType stackType, bool allowIntPtr)
{
if (input.Type.GetSize() > stackType.GetSize())
{
// truncate oversized result
return input.ConvertTo(FindType(stackType, input.Type.GetSign()), this);
}
if (input.Type.IsCSharpPrimitiveIntegerType() || input.Type.IsCSharpNativeIntegerType())
{
// can be used as array index as-is
return input;
}
if (allowIntPtr && (input.Type.IsKnownType(KnownTypeCode.IntPtr) || input.Type.IsKnownType(KnownTypeCode.UIntPtr)))
{
return input;
}
if (stackType != StackType.I4 && input.Type.GetStackType() == StackType.I4)
{
return input; // we don't need a cast, just let small integers be promoted to int
// prefer casting to int if that's big enough
stackType = StackType.I4;
}
IType targetType = FindArithmeticType(i.ResultType, input.Type.GetSign());
IType targetType = FindArithmeticType(stackType, input.Type.GetSign());
return input.ConvertTo(targetType, this);
}

2
ICSharpCode.Decompiler/TypeSystem/INamedElement.cs

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#nullable enable
namespace ICSharpCode.Decompiler.TypeSystem
{
public interface INamedElement

Loading…
Cancel
Save