]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
macro: relax CONST_MAX() type check a tiny bit
authorLennart Poettering <lennart@poettering.net>
Thu, 29 Jul 2021 16:39:09 +0000 (18:39 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 30 Jul 2021 13:56:56 +0000 (15:56 +0200)
This checked for strict type compatibility so far, which mean CONST_MAX()
couldn't be used on two differently signed integers, even though
conceptually there's nothing wrong with allowing that here, as C
correctly picks the larger type in the ternary op.

hence, let's explicitly whitelist integer comparisons here, as long as
the signedness matches.

src/fundamental/macro-fundamental.h

index 967518600d404db52ad232d87789302899f2ff21..e9fb4d393804b2933c4460bd04efa2743f24abe4 100644 (file)
                 UNIQ_T(A, aq) > UNIQ_T(B, bq) ? UNIQ_T(A, aq) : UNIQ_T(B, bq); \
         })
 
-/* evaluates to (void) if _A or _B are not constant or of different types */
+#define IS_UNSIGNED_INTEGER_TYPE(type) \
+        (__builtin_types_compatible_p(typeof(type), unsigned char) ||   \
+         __builtin_types_compatible_p(typeof(type), unsigned short) ||  \
+         __builtin_types_compatible_p(typeof(type), unsigned) ||        \
+         __builtin_types_compatible_p(typeof(type), unsigned long) ||   \
+         __builtin_types_compatible_p(typeof(type), unsigned long long))
+
+#define IS_SIGNED_INTEGER_TYPE(type) \
+        (__builtin_types_compatible_p(typeof(type), signed char) ||   \
+         __builtin_types_compatible_p(typeof(type), signed short) ||  \
+         __builtin_types_compatible_p(typeof(type), signed) ||        \
+         __builtin_types_compatible_p(typeof(type), signed long) ||   \
+         __builtin_types_compatible_p(typeof(type), signed long long))
+
+/* Evaluates to (void) if _A or _B are not constant or of different types (being integers of different sizes
+ * is also OK as long as the signedness matches) */
 #define CONST_MAX(_A, _B) \
         (__builtin_choose_expr(                                         \
                 __builtin_constant_p(_A) &&                             \
                 __builtin_constant_p(_B) &&                             \
-                __builtin_types_compatible_p(typeof(_A), typeof(_B)),   \
+                (__builtin_types_compatible_p(typeof(_A), typeof(_B)) || \
+                 (IS_UNSIGNED_INTEGER_TYPE(_A) && IS_UNSIGNED_INTEGER_TYPE(_B)) || \
+                 (IS_SIGNED_INTEGER_TYPE(_A) && IS_SIGNED_INTEGER_TYPE(_B))), \
                 ((_A) > (_B)) ? (_A) : (_B),                            \
                 VOID_0))