Skip to content

Commit

Permalink
Merge branch 'master' into feature/ReferenceAssemblyOverly
Browse files Browse the repository at this point in the history
  • Loading branch information
workgroupengineering authored Jun 22, 2024
2 parents bf8bc35 + 476e80b commit 757b5d5
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 22 deletions.
98 changes: 79 additions & 19 deletions ICSharpCode.Decompiler/Disassembler/ILParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,24 @@ public static class ILParser
public static ILOpCode DecodeOpCode(this ref BlobReader blob)
{
byte opCodeByte = blob.ReadByte();
return (ILOpCode)(opCodeByte == 0xFE ? 0xFE00 + blob.ReadByte() : opCodeByte);
if (opCodeByte == 0xFE && blob.RemainingBytes >= 1)
{
return (ILOpCode)(0xFE00 + blob.ReadByte());
}
else
{
return (ILOpCode)opCodeByte;
}
}

public static void SkipOperand(this ref BlobReader blob, ILOpCode opCode)
internal static int OperandSize(this OperandType opType)
{
switch (opCode.GetOperandType())
switch (opType)
{
// 64-bit
case OperandType.I8:
case OperandType.R:
blob.Offset += 8;
break;
return 8;
// 32-bit
case OperandType.BrTarget:
case OperandType.Field:
Expand All @@ -52,37 +58,91 @@ public static void SkipOperand(this ref BlobReader blob, ILOpCode opCode)
case OperandType.Tok:
case OperandType.Type:
case OperandType.ShortR:
blob.Offset += 4;
break;
return 4;
// (n + 1) * 32-bit
case OperandType.Switch:
uint n = blob.ReadUInt32();
blob.Offset += (int)(n * 4);
break;
// 16-bit
case OperandType.Variable:
blob.Offset += 2;
break;
return 4; // minimum 4, usually more
case OperandType.Variable: // 16-bit
return 2;
// 8-bit
case OperandType.ShortVariable:
case OperandType.ShortBrTarget:
case OperandType.ShortI:
blob.Offset++;
break;
return 1;
default:
return 0;
}
}

public static void SkipOperand(this ref BlobReader blob, ILOpCode opCode)
{
var opType = opCode.GetOperandType();
int operandSize;
if (opType == OperandType.Switch)
{
uint n = blob.RemainingBytes >= 4 ? blob.ReadUInt32() : uint.MaxValue;
if (n < int.MaxValue / 4)
{
operandSize = (int)(n * 4);
}
else
{
operandSize = int.MaxValue;
}
}
else
{
operandSize = opType.OperandSize();
}
if (operandSize <= blob.RemainingBytes)
{
blob.Offset += operandSize;
}
else
{
// ignore missing/partial operand at end of body
blob.Offset = blob.Length;
}
}

public static int DecodeBranchTarget(this ref BlobReader blob, ILOpCode opCode)
{
return (opCode.GetBranchOperandSize() == 4 ? blob.ReadInt32() : blob.ReadSByte()) + blob.Offset;
int opSize = opCode.GetBranchOperandSize();
if (opSize <= blob.RemainingBytes)
{
int relOffset = opSize == 4 ? blob.ReadInt32() : blob.ReadSByte();
return unchecked(relOffset + blob.Offset);
}
else
{
return int.MinValue;
}
}

public static int[] DecodeSwitchTargets(this ref BlobReader blob)
{
int[] targets = new int[blob.ReadUInt32()];
if (blob.RemainingBytes < 4)
{
blob.Offset += blob.RemainingBytes;
return new int[0];
}
uint numTargets = blob.ReadUInt32();
bool numTargetOverflow = false;
if (numTargets > blob.RemainingBytes / 4)
{
numTargets = (uint)(blob.RemainingBytes / 4);
numTargetOverflow = true;
}
int[] targets = new int[numTargets];
int offset = blob.Offset + 4 * targets.Length;
for (int i = 0; i < targets.Length; i++)
targets[i] = blob.ReadInt32() + offset;
{
targets[i] = unchecked(blob.ReadInt32() + offset);
}
if (numTargetOverflow)
{
blob.Offset += blob.RemainingBytes;
}
return targets;
}

Expand Down
2 changes: 2 additions & 0 deletions ICSharpCode.Decompiler/Disassembler/ILStructure.cs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,8 @@ bool AddNestedStructure(ILStructure newStructure)
// special case: don't consider the loop-like structure of "continue;" statements to be nested loops
if (this.Type == ILStructureType.Loop && newStructure.Type == ILStructureType.Loop && newStructure.StartOffset == this.StartOffset)
return false;
if (newStructure.StartOffset < 0)
return false;

// use <= for end-offset comparisons because both end and EndOffset are exclusive
Debug.Assert(StartOffset <= newStructure.StartOffset && newStructure.EndOffset <= EndOffset);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,8 @@ protected virtual void WriteInstruction(ITextOutput output, MetadataFile metadat
}
}
ILOpCode opCode = ILParser.DecodeOpCode(ref blob);
if (opCode.IsDefined())
OperandType opType = opCode.GetOperandType();
if (opCode.IsDefined() && opType.OperandSize() <= blob.RemainingBytes)
{
WriteRVA(blob, offset + methodRva, opCode);
output.WriteLocalReference(DisassemblerHelpers.OffsetToString(offset), offset, isDefinition: true);
Expand Down
10 changes: 9 additions & 1 deletion ICSharpCode.Decompiler/IL/ILReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1780,7 +1780,15 @@ ILInstruction[] PrepareArguments(bool firstArgumentIsStObjTarget)

DecodedInstruction DecodeCallIndirect()
{
var signatureHandle = (StandaloneSignatureHandle)ReadAndDecodeMetadataToken();
StandaloneSignatureHandle signatureHandle;
try
{
signatureHandle = (StandaloneSignatureHandle)ReadAndDecodeMetadataToken();
}
catch (InvalidCastException ex)
{
throw new BadImageFormatException("Invalid calli metadata token", ex);
}
var (header, fpt) = module.DecodeMethodSignature(signatureHandle, genericContext);
var functionPointer = Pop(StackType.I);
int firstArgument = header.IsInstance ? 1 : 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public sealed class XamarinCompressedFileLoader : IFileLoader
: MetadataReaderOptions.None;

return new LoadResult {
MetadataFile = new PEFile(fileName, stream, PEStreamOptions.PrefetchEntireImage, metadataOptions: options)
MetadataFile = new PEFile(fileName, uncompressedStream, PEStreamOptions.PrefetchEntireImage, metadataOptions: options)
};
}
}
Expand Down

0 comments on commit 757b5d5

Please sign in to comment.