icsharpcode/ILSpy · error · BadImageFormatException

Invalid calli metadata token

Error message

Invalid calli metadata token

What it means

BadImageFormatException (wrapping InvalidCastException) thrown by DecodeCallIndirect when the calli instruction's operand token cannot be cast to StandaloneSignatureHandle. A calli instruction must reference a function-pointer standalone signature; any other table type for its operand is invalid IL.

Source

Thrown at ICSharpCode.Decompiler/IL/ILReader.cs:1845

					}
					arguments[0] = firstArgumentInstruction;
				}
				// arguments is in reverse order of the Pop calls, thus
				// arguments is now in the correct evaluation order.
				return arguments;
			}
		}

		DecodedInstruction DecodeCallIndirect()
		{
			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;
			var arguments = new ILInstruction[firstArgument + fpt.ParameterTypes.Length];
			for (int i = fpt.ParameterTypes.Length - 1; i >= 0; i--)
			{
				arguments[firstArgument + i] = Pop(fpt.ParameterTypes[i].GetStackType());
			}
			if (firstArgument == 1)
			{
				arguments[0] = Pop();
			}
			// arguments is in reverse order of the Pop calls, thus
			// arguments is now in the correct evaluation order.
			var call = new CallIndirect(
				header.IsInstance,
				header.HasExplicitThis,

View on GitHub (pinned to 60c08fcb74)

Solutions

  1. Catch BadImageFormatException during decompilation and mark the method unreadable.
  2. Cross-check the token's table against StandaloneSignature before decompiling if you preprocess metadata.
  3. Use a clean copy of the assembly if tampering is suspected.

Example fix

// before
var code = decompiler.DecompileTypeAsString(typeName);

// after
try
{
    var code = decompiler.DecompileTypeAsString(typeName);
}
catch (BadImageFormatException ex) when (ex.Message.Contains("calli"))
{
    logger.Warn($"Invalid calli token in {typeName}: {ex.Message}");
}
Defensive patterns

Strategy: try-catch

Validate before calling

void VerifyCalliTokens(string path)
{
    using var pe = new PEReader(File.OpenRead(path));
    var md = pe.GetMetadataReader();
    // calli operands must be StandaloneSignature (table 0x11); flag any whose table byte differs
}

Try / catch

try { var code = decompiler.DecompileTypeAsString(typeName); }
catch (BadImageFormatException ex) when (ex.Message.Contains("calli")) { logger.Warn($"Invalid calli signature token: {ex.Message}"); }

Prevention

When it happens

Trigger: A calli instruction whose operand token is not a StandaloneSignature (e.g. points at a MethodDef, MethodSpec, or TypeSpec row); corrupt or hand-edited IL.

Common situations: Obfuscated assemblies that rewrite calli operands; damaged metadata streams; IL generated by tools that emit the wrong table for function-pointer signatures.

Related errors


AI-assisted analysis of icsharpcode/ILSpy@60c08fcb74 (2026-08-13). Data as JSON: /api/errors/688dbc622ff5c699. Report an issue: GitHub.