ImHex icon indicating copy to clipboard operation
ImHex copied to clipboard

[Bug] Signed Enums

Open crackedmind opened this issue 10 months ago • 1 comments

Operating System

Windows

What's the issue you encountered?

Cant create signed enums.

How can the issue be reproduced?

enum Test : s8 {
    None = -1,
    Opt0 = 0,
    Opt1 = 1,
};

struct TestContainer {
    Test t;
    if (t != Test::None) {
        u32 data;
    }
};

TestContainer container @ 0x00;

input: FF FE 00 00 00 output:

t = Test::???
data = 254

expected output: t = Test::None

ImHex Version

1.37.1

ImHex Build Type

  • [ ] Nightly or built from sources

Installation type

portable

Additional context?

No response

crackedmind avatar Feb 24 '25 12:02 crackedmind

I looked at this issue and it seems that even if you specify that the enum is 8 bit values, internally they are always 128 bits for the sake of simplifying the code. When you write None = -1, the pattern language interprets it as None = 0xFFFFFFFFFFFFFFFF. To being able to match 0xFF the PL would need to check the underlying type to parse the statement to mean None=0x00000000000000FF but that is not -1 in 128 bit representation so I can see why it doesn't do that. What it should try to do is to assign the value the the underlying type would have to be in order to satisfy the assignment and then convert that to a 128 bit integer, literally None = u8(-1),. That can be inserted in the code to test if it would fix the issue

enum Test : s8 {
    None = u8(-1),
    Opt0 = 0,
    Opt1 = 1,
};

struct TestContainer {
    Test t;
    if (t != Test::None) {
        u32 data;
    }
};

TestContainer container @ 0x00;

which will produce the desired output t = Test::None. So when PL parses a statement like:

enum Test : s8 {
    None = -1,
    Opt0 = 0,
    Opt1 = 1,
};

it should first auto convert it to

enum Test : s8 {
    None = u8(-1),
    Opt0 =u8( 0),
    Opt1 = u8(1),
};

internally which will result in the following pattern:

enum Test : s8 {
    None = u128(u8(-1)),
    Opt0 = u128(u8(0)),
    Opt1 = u128(u8(1)),
};

whereas now it produces

enum Test : s8 {
    None = u128(-1),
    Opt0 = u128(0),
    Opt1 = u128(1),
};

which only works for positive numbers. I don't think this will be hard to code and I don't think it will have unforeseen effects but I am busy with other projects so this would have to wait a bit and if nobody picks it up in the mean time I'll tackle it in the future.

paxcut avatar Feb 24 '25 22:02 paxcut