From d3e40294572512810c9329933a488619e7ce22fd Mon Sep 17 00:00:00 2001 From: =?utf8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 6 Jul 2021 09:49:56 +0200 Subject: [PATCH] =?utf8?q?basic/macro:=20make=20CONST=5FMAX(DECIMAL=5FSTR?= =?utf8?q?=5FMAX(=E2=80=A6),=20STRLEN(=E2=80=A6))=20possible?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 | 10 +++++----- src/test/test-format-util.c | 9 +++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) 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]; -- 2.47.3