]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic/macro: make CONST_MAX(DECIMAL_STR_MAX(…), STRLEN(…)) possible
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 6 Jul 2021 07:49:56 +0000 (09:49 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Fri, 9 Jul 2021 09:11:25 +0000 (11:11 +0200)
When those two macros were used together in CONST_MAX(), gcc would complain
about a type mismatch. So either DECIMAL_STR_MAX() should be made size_t like
STRLEN(), or STRLEN() be made unsigned.

Since those macros are only usable on arguments of (small) fixed size, any type
should be fine (even char would work…). For buffer size specifications, both
size_t and unsigned are OK. But unsigned was used for DECIMAL_STR_MAX macros
and FORMAT_foo_MAX macros, making STRLEN the only exception, so let's adjust
STRLEN() to be unsigned too.

Also: I don't think this is currently used anywhere, but if any of those macros
were used as an argument to sprintf, size_t would require a cast. ("%*s"
requires an int/unsigned argument.)

src/basic/macro.h
src/test/test-format-util.c

index 072fed4378931256fc9e3bc83cd2797652b0bc39..6507728a517ab99b836ae09012bc532be6ec6f3a 100644 (file)
@@ -213,7 +213,7 @@ static inline size_t GREEDY_ALLOC_ROUND_UP(size_t l) {
  *          Contrary to strlen(), this is a constant expression.
  * @x: a string literal.
  */
-#define STRLEN(x) (sizeof(""x"") - 1)
+#define STRLEN(x) ((unsigned) sizeof(""x"") - 1)
 
 /*
  * container_of - cast a member of a structure out to the containing structure
@@ -341,10 +341,10 @@ static inline int __coverity_check_and_return__(int condition) {
  * negative '-' prefix (hence works correctly on signed
  * types). Includes space for the trailing NUL. */
 #define DECIMAL_STR_MAX(type)                                           \
-        (2+(sizeof(type) <= 1 ? 3 :                                     \
-            sizeof(type) <= 2 ? 5 :                                     \
-            sizeof(type) <= 4 ? 10 :                                    \
-            sizeof(type) <= 8 ? 20 : sizeof(int[-2*(sizeof(type) > 8)])))
+        (2U+(sizeof(type) <= 1 ? 3U :                                   \
+             sizeof(type) <= 2 ? 5U :                                   \
+             sizeof(type) <= 4 ? 10U :                                  \
+             sizeof(type) <= 8 ? 20U : (unsigned) sizeof(int[-2*(sizeof(type) > 8)])))
 
 #define DECIMAL_STR_WIDTH(x)                            \
         ({                                              \
index 5562ac8761ca5bb0bbec2bbcfdc24624074558b6..4e6c90adfae0ae5a783dc2d367b04b94a9363fd2 100644 (file)
@@ -4,6 +4,15 @@
 #include "macro.h"
 #include "string-util.h"
 
+/* Do some basic checks on STRLEN() and DECIMAL_STR_MAX() */
+assert_cc(STRLEN("xxx") == 3);
+assert_cc(STRLEN("") == 0);
+assert_cc(DECIMAL_STR_MAX(uint8_t) == 5);
+assert_cc(DECIMAL_STR_MAX(int8_t) == 5);
+assert_cc(DECIMAL_STR_MAX(uint64_t) == 22);
+assert_cc(DECIMAL_STR_MAX(char) == 5);
+assert_cc(CONST_MAX(DECIMAL_STR_MAX(int8_t), STRLEN("xxx")) == 5);
+
 static void test_format_bytes_one(uint64_t val, bool trailing_B, const char *iec_with_p, const char *iec_without_p,
                                   const char *si_with_p, const char *si_without_p) {
         char buf[FORMAT_BYTES_MAX];