From 6fee4584ea2cdd735a94fbf0b29bd381d43d2249 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Thu, 23 Jun 2022 12:23:24 -0500 Subject: [PATCH] util: Re-indent util_sign_extend, comment, and add asserts The current implementation depends on both of these things for correctness. If width > 64, you get UB wrap-around and, if val >= (1 << width), the subtract trick won't work. Reviewed-by: Alyssa Rosenzweig Reviewed-by: Kristian H. Kristensen Part-of: --- src/util/u_math.h | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/util/u_math.h b/src/util/u_math.h index 7a1ca9dc1bd..52f5c6d53a3 100644 --- a/src/util/u_math.h +++ b/src/util/u_math.h @@ -580,17 +580,21 @@ util_bswap16(uint16_t n) } /** - * Extend sign. + * Sign-extend a number + * + * The bit at position `width - 1` is replicated to all the higher bits. + * This assumes and asserts that the value fits into `width` bits. */ static inline int64_t util_sign_extend(uint64_t val, unsigned width) { - assert(width > 0); - if (val & (UINT64_C(1) << (width - 1))) { - return -(int64_t)((UINT64_C(1) << width) - val); - } else { - return val; - } + assert(width > 0 && width <= 64); + assert(width == 64 || val < (1ull << width)); + if (val & (UINT64_C(1) << (width - 1))) { + return -(int64_t)((UINT64_C(1) << width) - val); + } else { + return val; + } } static inline void*