From af99ede1fde5a8c8cc877e06ab3c0e6de31d11cf Mon Sep 17 00:00:00 2001 From: Jade Lovelace Date: Sun, 19 Apr 2026 23:45:27 +0000 Subject: [PATCH] fix: UB casts to unspecified width enums in proto Found by edef's fuzzing. We::jade don't think this is security-relevant or likely to be mistreated by a compiler, but UB is bad. https://eel.is/c++draft/expr.static.cast#8 > If the enumeration type does not have a fixed underlying type, the value is unchanged if the original value is within the range of the enumeration values ([dcl.enum]), and otherwise, the behavior is undefined Notably, the range is defined as the smallest bitfield type that could hold all the values, not any real type which exists: https://eel.is/c++draft/dcl.enum#8. This is basically a footgun, and I'm writing a clang-tidy check to forbid casting to such types. But first I needed to write clang-tidy testing infrastructure: https://gerrit.lix.systems/c/lix/+/5493. Change-Id: Ieaaa0fe2a92fd9f24f60761e312741186a6a6964 --- lix/libstore/build-result.hh | 2 +- lix/libstore/gc-store.hh | 4 ++-- lix/libutil/error.hh | 5 ++--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/lix/libstore/build-result.hh b/lix/libstore/build-result.hh index ef7e64982..ba48dbba0 100644 --- a/lix/libstore/build-result.hh +++ b/lix/libstore/build-result.hh @@ -21,7 +21,7 @@ struct BuildResult * Therefore, don't remove status codes, and only add new status * codes at the end of the list. */ - enum Status { + enum Status : uint8_t { Built = 0, Substituted, AlreadyValid, diff --git a/lix/libstore/gc-store.hh b/lix/libstore/gc-store.hh index 121c00ceb..7d04ae6a4 100644 --- a/lix/libstore/gc-store.hh +++ b/lix/libstore/gc-store.hh @@ -39,13 +39,13 @@ struct GCOptions * Any that could not be deleted are returned via the * `kept` field of GCResults. */ - typedef enum { + enum GCAction : uint8_t { gcReturnLive, gcReturnDead, gcDeleteDead, gcDeleteSpecific, gcTryDeleteSpecific, - } GCAction; + }; GCAction action{gcDeleteDead}; diff --git a/lix/libutil/error.hh b/lix/libutil/error.hh index f1b9c29a2..2e1d8dfee 100644 --- a/lix/libutil/error.hh +++ b/lix/libutil/error.hh @@ -35,8 +35,7 @@ namespace nix { - -typedef enum { +enum Verbosity : uint8_t { lvlError = 0, lvlWarn, lvlNotice, @@ -45,7 +44,7 @@ typedef enum { lvlChatty, lvlDebug, lvlVomit -} Verbosity; +}; template<> struct json::is_integral_enum : std::true_type {};