]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
coccinelle: add SIZEOF() macro to work-around sizeof(*private) 41595/head
authorMichael Vogt <michael@amutable.com>
Sun, 12 Apr 2026 13:47:48 +0000 (15:47 +0200)
committerMichael Vogt <michael@amutable.com>
Sun, 12 Apr 2026 13:47:48 +0000 (15:47 +0200)
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.

coccinelle/parsing_hacks.h
src/fundamental/assert-fundamental.h
src/shared/tpm2-util.c

index 774dbb1e6a1024454d4e2dd35d6d07aa037c70a7..bc84235557719853e48b62e3d7c57a62e0381571 100644 (file)
 #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
index e7f662512bff51ed9fafb6a640bdc76bdaa5d31a..d3425cb54df0c1013164eca19c6afa1c75175a4b 100644 (file)
@@ -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)
index 5e5ed1f620b392983c659310d2c4b0fb2c3258ba..02f89c02ba71f2fde421906c861fac5e75e4e4cd 100644 (file)
@@ -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;