From: Michael Vogt Date: Sun, 12 Apr 2026 13:47:48 +0000 (+0200) Subject: coccinelle: add SIZEOF() macro to work-around sizeof(*private) X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F41595%2Fhead;p=thirdparty%2Fsystemd.git coccinelle: add SIZEOF() macro to work-around sizeof(*private) We have code like `size_t max_size = sizeof(*private)` in three places. This is evaluated at compile time so its safe to use. However the new pointer-deref checker in coccinelle is not smart enough to know this and will flag those as errors. To avoid these false positives we have some options: 1. Reorder so that we do: ```C size_t max_size = 0; assert(private); max_size = sizeof(*private); ``` 2. Use something like `size_t max_size = sizeof(*ASSERT_PTR(private));` 3. Place the assert before the declaration 4. Workaround coccinelle via SIZEOF(*private) that we can then hide via parsing_hacks.h 5. Fix coccinelle (OCaml, hard) 6. ... somehting I missed? None of these is very appealing. I went for (4) but happy about suggestions. --- diff --git a/coccinelle/parsing_hacks.h b/coccinelle/parsing_hacks.h index 774dbb1e6a1..bc842355577 100644 --- a/coccinelle/parsing_hacks.h +++ b/coccinelle/parsing_hacks.h @@ -99,6 +99,11 @@ #define CMSG_BUFFER_TYPE(x) union { uint8_t align_check[(size) >= CMSG_SPACE(0) && (size) == CMSG_ALIGN(size) ? 1 : -1]; } #define SD_ID128_MAKE(...) ((const sd_id128) {}) +/* sizeof() does not evaluate its argument, so *ptr inside sizeof() is not a real dereference. + * The SIZEOF() macro is an alias for sizeof() that hides the argument from coccinelle to avoid + * false positives from check-pointer-deref.cocci. See assert-fundamental.h for the definition. */ +#define SIZEOF(x) 8 + /* Work around a bug in zlib.h parsing on Fedora (and possibly others) * See: https://github.com/coccinelle/coccinelle/issues/413 */ #define Z_EXPORT diff --git a/src/fundamental/assert-fundamental.h b/src/fundamental/assert-fundamental.h index e7f662512bf..d3425cb54df 100644 --- a/src/fundamental/assert-fundamental.h +++ b/src/fundamental/assert-fundamental.h @@ -105,3 +105,11 @@ static inline int __coverity_check_and_return__(int condition) { * the coccinelle check-pointer-deref warning for parameters that are safely handled before any * dereference (e.g. passed to a NULL-safe helper like iovec_is_set()). */ #define POINTER_MAY_BE_NULL(ptr) ({ (void) (ptr); }) + +/* sizeof() does not evaluate its argument - it is a compile-time constant expression - so *ptr + * inside sizeof() is not a real dereference. However, coccinelle cannot distinguish this from an + * actual dereference, and when sizeof(*ptr) appears in a variable initializer the assert(ptr) that + * follows cannot come first (declarations must precede statements). Use this macro in place + * of sizeof() to avoid the false positive - coccinelle sees SIZEOF() as a function call (via + * parsing_hacks.h) and never looks inside the argument. */ +#define SIZEOF(x) sizeof(x) diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c index 5e5ed1f620b..02f89c02ba7 100644 --- a/src/shared/tpm2-util.c +++ b/src/shared/tpm2-util.c @@ -2507,7 +2507,7 @@ static int tpm2_load_external( } static int tpm2_marshal_private(const TPM2B_PRIVATE *private, void **ret, size_t *ret_size) { - size_t max_size = sizeof(*private), blob_size = 0; + size_t max_size = SIZEOF(*private), blob_size = 0; _cleanup_free_ void *blob = NULL; TSS2_RC rc; @@ -2550,7 +2550,7 @@ static int tpm2_unmarshal_private(const void *data, size_t size, TPM2B_PRIVATE * } int tpm2_marshal_public(const TPM2B_PUBLIC *public, void **ret, size_t *ret_size) { - size_t max_size = sizeof(*public), blob_size = 0; + size_t max_size = SIZEOF(*public), blob_size = 0; _cleanup_free_ void *blob = NULL; TSS2_RC rc; @@ -2593,7 +2593,7 @@ static int tpm2_unmarshal_public(const void *data, size_t size, TPM2B_PUBLIC *re } int tpm2_marshal_nv_public(const TPM2B_NV_PUBLIC *nv_public, void **ret, size_t *ret_size) { - size_t max_size = sizeof(*nv_public), blob_size = 0; + size_t max_size = SIZEOF(*nv_public), blob_size = 0; _cleanup_free_ void *blob = NULL; TSS2_RC rc;