From cb2ee227c3f8ccf99f25835571a31b4b8a068ec1 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 22 Apr 2026 12:38:33 -0400 Subject: [PATCH] rlm_kafka: unbox async opaques with talloc_get_type_abort xctx->inst / xctx->thread / msg->_private are all void pointers that we know at the call-site should point back at our typed talloc chunks. Using talloc_get_type_abort turns a subtle type-system hole into a loud abort at the exact callsite if the opaque ever gets crossed over, instead of a mystery crash deep in the function body. The DR callback keeps its NULL-guard first - a NULL opaque is the documented signal for fire-and-forget produces, so it's part of the contract, not an error worth asserting on. --- src/modules/rlm_kafka/rlm_kafka.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/modules/rlm_kafka/rlm_kafka.c b/src/modules/rlm_kafka/rlm_kafka.c index 998abc4b151..7b8d3c91a82 100644 --- a/src/modules/rlm_kafka/rlm_kafka.c +++ b/src/modules/rlm_kafka/rlm_kafka.c @@ -596,7 +596,7 @@ typedef struct { */ static int kafka_xlat_instantiate(xlat_inst_ctx_t const *xctx) { - rlm_kafka_xlat_inst_t *inst = xctx->inst; + rlm_kafka_xlat_inst_t *inst = talloc_get_type_abort(xctx->inst, rlm_kafka_xlat_inst_t); rlm_kafka_t const *mod_inst = talloc_get_type_abort_const(xctx->mctx->mi->data, rlm_kafka_t); xlat_exp_t *topic_arg; xlat_exp_t const *topic_node; @@ -654,8 +654,8 @@ static int kafka_xlat_instantiate(xlat_inst_ctx_t const *xctx) */ static int kafka_xlat_thread_instantiate(xlat_thread_inst_ctx_t const *xctx) { - rlm_kafka_xlat_inst_t const *inst = xctx->inst; - rlm_kafka_xlat_thread_inst_t *t_inst = xctx->thread; + rlm_kafka_xlat_inst_t const *inst = talloc_get_type_abort_const(xctx->inst, rlm_kafka_xlat_inst_t); + rlm_kafka_xlat_thread_inst_t *t_inst = talloc_get_type_abort(xctx->thread, rlm_kafka_xlat_thread_inst_t); rlm_kafka_thread_t *t; /* @@ -789,9 +789,15 @@ static xlat_action_t kafka_xlat_produce(UNUSED TALLOC_CTX *xctx_ctx, UNUSED fr_d */ static void _kafka_delivery_report_cb(UNUSED rd_kafka_t *rk, rd_kafka_message_t const *msg, UNUSED void *opaque) { - rlm_kafka_msg_ctx_t *pctx = msg->_private; + rlm_kafka_msg_ctx_t *pctx; - if (!pctx) return; + /* + * A NULL opaque is the documented signal for + * fire-and-forget produces - nothing to resume or free, + * just return before we try to unbox the pointer. + */ + if (!msg->_private) return; + pctx = talloc_get_type_abort(msg->_private, rlm_kafka_msg_ctx_t); fr_dlist_remove(&pctx->t->inflight, pctx); -- 2.47.3