mirror of https://github.com/icsharpcode/ILSpy.git
Browse Source
An addition or subtraction on an enum whose constant operand's numeric value does not fit the underlying type (an int constant standing for a high uint member, e.g. -501 for 0xfffffe0b) failed to resolve as enum arithmetic and fell back to integer arithmetic with casts, producing '(uint)((int)value - -501)' and, for the same source expression in an argument position, '(uint)value - 4294966795u'. Retry the failed resolution once with constant operands reinterpreted in the enum type; the reinterpretation is lossless whenever the constant's stack type matches the enum's underlying stack type, because the IL constant is the member's bit pattern. Valid non-enum resolutions like 'data - 1' (enum minus underlying, yielding the enum) are unaffected because the retry only runs when the plain resolution fails. Assisted-by: Claude:claude-fable-5:Claude Codepull/3897/head
6 changed files with 160 additions and 1 deletions
@ -0,0 +1,22 @@
@@ -0,0 +1,22 @@
|
||||
// The constants are out of range for the enums' underlying types, so they must not be
|
||||
// recovered as the members whose bit patterns they happen to truncate to (Val1 in both
|
||||
// cases): the enum arithmetic would compute a different result than the IL does.
|
||||
public enum ByteEnum : byte |
||||
{ |
||||
Val1 = 112 |
||||
} |
||||
public static class EnumArithmeticOutOfRange |
||||
{ |
||||
public static int SubtractFromUShortEnum(UShortEnum value) |
||||
{ |
||||
return (int)value - -501; |
||||
} |
||||
public static int SubtractFromByteEnum(ByteEnum value) |
||||
{ |
||||
return (int)value - 70000; |
||||
} |
||||
} |
||||
public enum UShortEnum : ushort |
||||
{ |
||||
Val1 = 65035 |
||||
} |
||||
@ -0,0 +1,50 @@
@@ -0,0 +1,50 @@
|
||||
#define CORE_ASSEMBLY "System.Runtime" |
||||
|
||||
.assembly extern CORE_ASSEMBLY |
||||
{ |
||||
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: |
||||
.ver 4:0:0:0 |
||||
} |
||||
|
||||
// The constant operands below are out of range for the enums' underlying types, but their |
||||
// low bits do match a member: -501 truncates to UShortEnum.Val1 (0xfe0b) and 70000 to |
||||
// ByteEnum.Val1 (0x70). Reinterpreting them as those members would change the result of the |
||||
// subtraction, so the decompiler has to keep the integer arithmetic. |
||||
|
||||
.class public auto ansi sealed UShortEnum |
||||
extends [CORE_ASSEMBLY]System.Enum |
||||
{ |
||||
.field public specialname rtspecialname uint16 value__ |
||||
.field public static literal valuetype UShortEnum Val1 = uint16(0xfe0b) |
||||
} |
||||
|
||||
.class public auto ansi sealed ByteEnum |
||||
extends [CORE_ASSEMBLY]System.Enum |
||||
{ |
||||
.field public specialname rtspecialname uint8 value__ |
||||
.field public static literal valuetype ByteEnum Val1 = uint8(0x70) |
||||
} |
||||
|
||||
.class public auto ansi abstract sealed beforefieldinit EnumArithmeticOutOfRange |
||||
extends [CORE_ASSEMBLY]System.Object |
||||
{ |
||||
.method public hidebysig static int32 SubtractFromUShortEnum (valuetype UShortEnum 'value') cil managed |
||||
{ |
||||
.maxstack 8 |
||||
|
||||
ldarg.0 |
||||
ldc.i4 -501 |
||||
sub |
||||
ret |
||||
} |
||||
|
||||
.method public hidebysig static int32 SubtractFromByteEnum (valuetype ByteEnum 'value') cil managed |
||||
{ |
||||
.maxstack 8 |
||||
|
||||
ldarg.0 |
||||
ldc.i4 70000 |
||||
sub |
||||
ret |
||||
} |
||||
} |
||||
Loading…
Reference in new issue