From: Zbigniew Jędrzejewski-Szmek Date: Tue, 6 Jul 2021 07:49:56 +0000 (+0200) Subject: basic/macro: make CONST_MAX(DECIMAL_STR_MAX(…), STRLEN(…)) possible X-Git-Tag: v250-rc1~952^2~10 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d3e40294572512810c9329933a488619e7ce22fd;p=thirdparty%2Fsystemd.git basic/macro: make CONST_MAX(DECIMAL_STR_MAX(…), STRLEN(…)) possible 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.) --- diff --git a/src/basic/macro.h b/src/basic/macro.h index 072fed43789..6507728a517 100644 --- a/src/basic/macro.h +++ b/src/basic/macro.h @@ -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) \ ({ \ diff --git a/src/test/test-format-util.c b/src/test/test-format-util.c index 5562ac8761c..4e6c90adfae 100644 --- a/src/test/test-format-util.c +++ b/src/test/test-format-util.c @@ -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];