]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib: Fix MODULE_CONTEXT_REQUIRE() to always panic if context is unset
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 30 May 2023 20:17:21 +0000 (23:17 +0300)
committerTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 30 May 2023 20:17:21 +0000 (23:17 +0300)
Previously panic happened only if the module_contexts array was too small,
not when the element inside the array was NULL.

This required rewriting the macros partially as inline functions, which also
simplifies how they work.

src/lib/module-context.h

index 3d2b1d6cb064cb0afe7b86ca83da9f3acff91bd1..6cf7ffd44e80aa80b5675bd69dbdef5c53fb975a 100644 (file)
 #define OBJ_REGISTER_COMPATIBLE(obj, id_ctx) \
        COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE(OBJ_REGISTER(obj), (id_ctx).reg)
 
-#define MODULE_CONTEXT(obj, id_ctx) \
-       (module_get_context_id(&(id_ctx).id) < array_count(&(obj)->module_contexts) ? \
-        (*((void **)array_idx_modifiable(&(obj)->module_contexts,      \
-               module_get_context_id(&(id_ctx).id)) + \
-           OBJ_REGISTER_COMPATIBLE(obj, id_ctx))) : NULL)
-
-/* Will crash if context is missing. This is mainly used to simplify code and
-   keep static analyzers happy. This syntax discards result of i_panic and
-   returns NULL instead to keep compilers happy. */
-#define MODULE_CONTEXT_REQUIRE(obj, id_ctx) \
-       (module_get_context_id(&(id_ctx).id) < array_count(&(obj)->module_contexts) ? \
-        (*((void **)array_idx_modifiable(&(obj)->module_contexts,      \
-               module_get_context_id(&(id_ctx).id)) + \
-           OBJ_REGISTER_COMPATIBLE(obj, id_ctx))) : (i_panic("Module context " #id_ctx " missing"), NULL))
-
 #ifdef HAVE_TYPEOF
 #  define MODULE_CONTEXT_DEFINE(_name, _reg) \
        struct _name { \
@@ -96,6 +81,35 @@ static inline unsigned int module_get_context_id(struct module_context_id *id)
        return id->module_id;
 }
 
+static inline void *
+module_context_get(struct array *array, struct module_context_id *id)
+{
+       unsigned int module_id = module_get_context_id(id);
+       if (module_id >= array_count_i(array))
+               return NULL;
+       void **ctx = (void **)array_idx_modifiable_i(array, module_id);
+       return *ctx;
+}
+#define MODULE_CONTEXT(obj, id_ctx) \
+       (TRUE ? module_context_get(&(obj)->module_contexts.arr, &(id_ctx).id) : \
+       OBJ_REGISTER_COMPATIBLE(obj, id_ctx))
+
+static inline void *
+module_context_get_require(struct array *array, struct module_context_id *id,
+                          const char *panic_message)
+{
+       void *ctx = module_context_get(array, id);
+       if (ctx == NULL)
+               i_panic("%s", panic_message);
+       return ctx;
+}
+/* Will crash if context is missing. This is mainly used to simplify code and
+   prevent static analyzers from complaining about NULL pointer dereferences. */
+#define MODULE_CONTEXT_REQUIRE(obj, id_ctx) \
+       (TRUE ? module_context_get_require(&(obj)->module_contexts.arr, \
+               &(id_ctx).id, "Module context " #id_ctx " missing") : \
+       OBJ_REGISTER_COMPATIBLE(obj, id_ctx))
+
 #define MODULE_CONTEXT_SET_FULL(obj, id_ctx, ctx, module_ctx) STMT_START { \
        (void)COMPILE_ERROR_IF_TYPES_NOT_COMPATIBLE(module_ctx, \
                        (**(obj)->module_contexts.v)); \