hyprwm / aquamarine

Aquamarine is a very light linux rendering backend library
BSD 3-Clause "New" or "Revised" License
219 stars 16 forks source link

a few undefined behaviour casting enums #4

Closed gulafaran closed 1 month ago

gulafaran commented 2 months ago

found a few enum casting out of range i got no idea how to solve cleanly. thought id atleast make a bugreport about them.

https://github.com/hyprwm/aquamarine/blob/890d6177b2e008b79ef037c676d39b957f1f463d/src/backend/Wayland.cpp#L684 https://github.com/hyprwm/aquamarine/blob/890d6177b2e008b79ef037c676d39b957f1f463d/src/backend/Wayland.cpp#L751

casting to 0, while generated enum is

enum zwpLinuxBufferParamsV1Flags : uint32_t {
    ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT = 1,
    ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_INTERLACED = 2,
    ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_BOTTOM_FIRST = 4,
};
vaxerski commented 2 months ago

don't think we can escape the protocol ones.

Ferdi265 commented 1 month ago

According to C++ standard [expr.static.cast] p.9, it's only UB if the enum doesn't have an underlying type. The flags enum has an underlying type, so the cast is fine.

GCC doesn't enforce this, but Clang seems to consider casts to enums without an underlying type to be UB if the value is one bit bigger than the largest enum member:

enum foo {
  FOO = 200
};

enum bar : int {
  BAR = 200
};

constexpr foo f1 = foo(0);
constexpr foo f2 = foo(100);
constexpr foo f3 = foo(256); // error on Clang "256 is outside the valid range of values for the enumeration type"
constexpr bar b1 = bar(0);
constexpr bar b2 = bar(100);
constexpr bar b3 = bar(256);
gulafaran commented 1 month ago

According to C++ standard [expr.static.cast] p.9, it's only UB if the enum doesn't have an underlying type. The flags enum has an underlying type, so the cast is fine.

GCC doesn't enforce this, but Clang seems to consider casts to enums without an underlying type to be UB if the value is one bit bigger than the largest enum member:

enum foo {
  FOO = 200
};

enum bar : int {
  BAR = 200
};

constexpr foo f1 = foo(0);
constexpr foo f2 = foo(100);
constexpr foo f3 = foo(256); // error on Clang "256 is outside the valid range of values for the enumeration type"
constexpr bar b1 = bar(0);
constexpr bar b2 = bar(100);
constexpr bar b3 = bar(256);

yeah we figured that out in a hyprpaper PR just yesterday, heh so im closing this one. thanks tho :)