From 994282d2dedfda8a4a89ba1735637884a3dc3a2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 22 May 2018 09:07:35 +0200 Subject: [PATCH 1/3] test-sizeof: show that a small 64 field is not enough to force the enum to be 64 bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On both 32 and 64 bits, the result is: enum Enum → 32 bits, unsigned enum BigEnum → 32 bits, unsigned enum BigEnum2 → 64 bits, unsigned big_enum2_pos → 4 big_enum2_neg → 8 The last two lines show that even if the enum is 64 bit, and the field of an enum is defined with UINT64_C(), the field can still be smaller. --- src/test/test-sizeof.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/test/test-sizeof.c b/src/test/test-sizeof.c index 2ebbbb304a..d7897ed765 100644 --- a/src/test/test-sizeof.c +++ b/src/test/test-sizeof.c @@ -26,7 +26,12 @@ enum Enum { }; enum BigEnum { - big_enum_value = UINT64_C(-1), + big_enum_value = UINT64_C(1), +}; + +enum BigEnum2 { + big_enum2_pos = UINT64_C(1), + big_enum2_neg = UINT64_C(-1), }; int main(void) { @@ -55,6 +60,10 @@ int main(void) { info(enum Enum); info(enum BigEnum); + info(enum BigEnum2); + assert_cc(sizeof(enum BigEnum2) == 8); + printf("big_enum2_pos → %zu\n", sizeof(big_enum2_pos)); + printf("big_enum2_neg → %zu\n", sizeof(big_enum2_neg)); return 0; } From 9b505bc257907a6b9a2bcd006796b0a1d0fab76d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 22 May 2018 09:36:08 +0200 Subject: [PATCH 2/3] sd-resolve: remove misleading casts As shown in previous commit, UINT64_C() has no effect here, the field can still be smaller. Remove it. --- src/systemd/sd-resolve.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/systemd/sd-resolve.h b/src/systemd/sd-resolve.h index 14d0cbde04..d4921e9559 100644 --- a/src/systemd/sd-resolve.h +++ b/src/systemd/sd-resolve.h @@ -43,9 +43,9 @@ typedef int (*sd_resolve_getaddrinfo_handler_t)(sd_resolve_query *q, int ret, co typedef int (*sd_resolve_getnameinfo_handler_t)(sd_resolve_query *q, int ret, const char *host, const char *serv, void *userdata); enum { - SD_RESOLVE_GET_HOST = UINT64_C(1), - SD_RESOLVE_GET_SERVICE = UINT64_C(2), - SD_RESOLVE_GET_BOTH = UINT64_C(3), + SD_RESOLVE_GET_HOST = 1 << 0, + SD_RESOLVE_GET_SERVICE = 1 << 1, + SD_RESOLVE_GET_BOTH = SD_RESOLVE_GET_HOST | SD_RESOLVE_GET_SERVICE, }; int sd_resolve_default(sd_resolve **ret); From b49c6ca089a3eb663e42aa55a06df8c1fea8543c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 22 May 2018 09:13:31 +0200 Subject: [PATCH 3/3] systemd-nspawn: make SettingsMask 64 bit wide The use of UINT64_C() in the SettingsMask enum definition is misleading: it does not mean that individual fields have this width. E.g., with enum { FOO = UINT64_C(1) } sizeof(FOO) gives 4. It only means that the shift is done properly. So 1 << 35 is undefined, but UINT64_C(1) << 35 is the expected 64 bit constant. Thus, the use UINT64_C() is useful, because we know that the shifts are done properly, no matter what the value of _RLIMIT_MAX is, but when those fields are used in expressions, we don't know what size they will be (probably 4). Let's add a define which "hides" the enum definition behind a define which gives the same value but is actually 64 bit. I think this is a nicer solution than requiring all users to cast SETTING_RLIMIT_FIRST before use. Fixes #9035. --- src/nspawn/nspawn-settings.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/nspawn/nspawn-settings.h b/src/nspawn/nspawn-settings.h index c786bf8c86..4e9cf3e315 100644 --- a/src/nspawn/nspawn-settings.h +++ b/src/nspawn/nspawn-settings.h @@ -56,9 +56,19 @@ typedef enum SettingsMask { SETTING_CPU_AFFINITY = UINT64_C(1) << 20, SETTING_RLIMIT_FIRST = UINT64_C(1) << 21, /* we define one bit per resource limit here */ SETTING_RLIMIT_LAST = UINT64_C(1) << (21 + _RLIMIT_MAX - 1), - _SETTINGS_MASK_ALL = (UINT64_C(1) << (21 + _RLIMIT_MAX)) - 1 + _SETTINGS_MASK_ALL = (UINT64_C(1) << (21 + _RLIMIT_MAX)) - 1, + _FORCE_ENUM_WIDTH = UINT64_MAX } SettingsMask; +/* We want to use SETTING_RLIMIT_FIRST in shifts, so make sure it is really 64 bits + * when used in expressions. */ +#define SETTING_RLIMIT_FIRST ((uint64_t) SETTING_RLIMIT_FIRST) +#define SETTING_RLIMIT_LAST ((uint64_t) SETTING_RLIMIT_LAST) + +assert_cc(sizeof(SettingsMask) == 8); +assert_cc(sizeof(SETTING_RLIMIT_FIRST) == 8); +assert_cc(sizeof(SETTING_RLIMIT_LAST) == 8); + typedef struct Settings { /* [Run] */ StartMode start_mode;