Fix IcedAssembler immediate overflow and unwrap invoke exceptions

- TryBind wraps Convert.ChangeType in TryChangeType so an immediate that
  overflows a candidate parameter type returns false (letting a wider overload
  be tried) instead of throwing OverflowException out of assembly. Verified:
  "mov eax, 4294967295" and "mov eax, -2147483649" no longer crash.
- Immediate now carries a boxed long OR ulong; TryParseImmediate parses decimal
  values above long.MaxValue via a ulong fallback, and hex via ulong. Previously
  such literals were rejected at parse time.
- Unwrap TargetInvocationException from method.Invoke so callers see the real
  Iced failure, not the reflection wrapper.

Tests: 231 passing, 4 skipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
kbe
2026-07-22 11:43:48 +02:00
co-authored by Claude Opus 4.8
parent 0ddd812829
commit e8c84f0ba1
2 changed files with 94 additions and 14 deletions
@@ -82,6 +82,32 @@ public class IcedAssemblerTests
Assert.Equal(expected, jmp.NearBranchTarget);
}
[Theory]
[InlineData("mov eax, 4294967295")] // 0xFFFFFFFF — needs the uint overload, not int
[InlineData("mov eax, 0xFFFFFFFF")] // same value, hex form
[InlineData("mov rax, 18446744073709551615")] // ulong.MaxValue — decimal above long.MaxValue
public void Assemble_binds_wide_unsigned_immediates(string source)
{
var assembler = new IcedAssembler(64);
byte[] code = assembler.Assemble(source);
Assert.NotEmpty(code);
Instruction[] instructions = Disassemble(code, 64, 0);
Assert.Single(instructions);
Assert.Equal(Mnemonic.Mov, instructions[0].Mnemonic);
}
[Fact]
public void Assemble_rejects_immediate_that_fits_no_overload_without_crashing()
{
var assembler = new IcedAssembler(64);
// -2147483649 is below int.MinValue and eax has no wider signed overload; must be a
// clean NotSupportedException, not an OverflowException escaping from ChangeType.
Assert.Throws<NotSupportedException>(() => assembler.Assemble("mov eax, -2147483649"));
}
[Fact]
public void Assemble_throws_on_unsupported_operand()
{