From f7d88e553203b55339e496b96ac41b8b892f2a0f Mon Sep 17 00:00:00 2001 From: Evgeny Date: Wed, 15 Jul 2026 11:21:31 +0300 Subject: [PATCH] fix segfault in ca_ready_cb: ca_state owns all ca_ctx, single cleanup point MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added struct ca_ctx** ctxs to ca_state (parallel array) - ca_cleanup now frees all ctxs[i] and the ctxs array - ca_ready_cb: removed u_free(ctx), added etcp_conn_remove_ready_cbk before cleanup - ca_timeout_cb: removed u_free(ctx) — ctx lives until ca_cleanup - All error paths set ctxs[i]=NULL for ca_cleanup safety --- tools/chatgui/transport/chat_core.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/tools/chatgui/transport/chat_core.c b/tools/chatgui/transport/chat_core.c index fea51051..bb9583ef 100644 --- a/tools/chatgui/transport/chat_core.c +++ b/tools/chatgui/transport/chat_core.c @@ -896,6 +896,7 @@ struct ca_state { uint64_t node_id; struct ETCP_CONN** conns; void** timers; + struct ca_ctx** ctxs; void (*result_cb)(int result, uint64_t node_id, void* arg); void* result_arg; uint8_t pubkey[SC_PUBKEY_SIZE]; @@ -903,6 +904,7 @@ struct ca_state { static void ca_cleanup(struct ca_state* st) { if (!st) return; + if (st->ctxs) { for (int i = 0; i < st->addr_count; i++) u_free(st->ctxs[i]); u_free(st->ctxs); } u_free(st->conns); u_free(st->timers); u_free(st); @@ -911,7 +913,7 @@ static void ca_cleanup(struct ca_state* st) { static void ca_ready_cb(struct ETCP_CONN* conn, void* arg) { struct ca_ctx* ctx = (struct ca_ctx*)arg; struct ca_state* st = ctx->state; - if (st->delivered || st->cancelled) { u_free(ctx); return; } + if (st->delivered || st->cancelled) return; st->delivered = 1; DEBUG_INFO(DEBUG_CATEGORY_CONNECTIVITY, "%s: auto_connect SUCCESS idx=%d peer=0x%016llx", CC_ID, ctx->addr_index, (unsigned long long)st->node_id); @@ -919,7 +921,7 @@ static void ca_ready_cb(struct ETCP_CONN* conn, void* arg) { if (st->timers[i]) { uasync_cancel_timeout(st->inst->ua, st->timers[i]); st->timers[i] = NULL; } if (st->conns[i] && i != ctx->addr_index) { etcp_connection_close(st->conns[i]); st->conns[i] = NULL; } } - u_free(ctx); + etcp_conn_remove_ready_cbk(conn, ca_ready_cb, ctx); st->result_cb(CONN_MGR_OK, st->node_id, st->result_arg); ca_cleanup(st); } @@ -927,7 +929,7 @@ static void ca_ready_cb(struct ETCP_CONN* conn, void* arg) { static void ca_timeout_cb(void* arg) { struct ca_ctx* ctx = (struct ca_ctx*)arg; struct ca_state* st = ctx->state; - if (st->delivered || st->cancelled) { u_free(ctx); return; } + if (st->delivered || st->cancelled) return; st->timers[ctx->addr_index] = NULL; st->pending_count--; DEBUG_INFO(DEBUG_CATEGORY_CONNECTIVITY, "%s: auto_connect TIMEOUT idx=%d pending=%d/%d peer=0x%016llx", @@ -936,7 +938,6 @@ static void ca_timeout_cb(void* arg) { st->delivered = 1; st->result_cb(CONN_MGR_ERR_TIMEOUT, st->node_id, st->result_arg); } - u_free(ctx); } void chat_core_connect_auto_cancel(void* state) { @@ -1033,7 +1034,8 @@ void chat_core_connect_auto(uint64_t node_id, memcpy(pst->pubkey, pubkey, SC_PUBKEY_SIZE); pst->conns = u_calloc(addr_count, sizeof(struct ETCP_CONN*)); pst->timers = u_calloc(addr_count, sizeof(void*)); - if (!pst->conns || !pst->timers) { ca_cleanup(pst); cb(CONN_MGR_ERR_INTERNAL, node_id, arg); return; } + pst->ctxs = u_calloc(addr_count, sizeof(struct ca_ctx*)); + if (!pst->conns || !pst->timers || !pst->ctxs) { ca_cleanup(pst); cb(CONN_MGR_ERR_INTERNAL, node_id, arg); return; } for (int i = 0; i < addr_count; i++) { struct sockaddr_in sin; @@ -1046,7 +1048,7 @@ void chat_core_connect_auto(uint64_t node_id, struct ETCP_CONN* conn = etcp_connection_create(g_cc.inst, NULL); if (!conn) { DEBUG_ERROR(DEBUG_CATEGORY_CONNECTIVITY, "%s: auto_connect etcp_connection_create failed idx=%d", CC_ID, i); - pst->conns[i] = NULL; pst->timers[i] = NULL; pst->pending_count--; continue; + pst->conns[i] = NULL; pst->timers[i] = NULL; pst->ctxs[i] = NULL; pst->pending_count--; continue; } sc_init_ctx(&conn->crypto_ctx, &g_cc.inst->my_keys); sc_set_peer_public_key(&conn->crypto_ctx, pubkey, 0); @@ -1056,15 +1058,16 @@ void chat_core_connect_auto(uint64_t node_id, g_cc.inst->connections_count++; struct ca_ctx* pctx = u_calloc(1, sizeof(struct ca_ctx)); - if (!pctx) { etcp_connection_close(conn); pst->conns[i] = NULL; pst->timers[i] = NULL; pst->pending_count--; continue; } + if (!pctx) { etcp_connection_close(conn); pst->conns[i] = NULL; pst->timers[i] = NULL; pst->ctxs[i] = NULL; pst->pending_count--; continue; } pctx->state = pst; pctx->addr_index = i; + pst->ctxs[i] = pctx; etcp_conn_set_ready_cbk(conn, ca_ready_cb, pctx); if (!etcp_link_new(conn, best_socket, &sa, 0)) { DEBUG_ERROR(DEBUG_CATEGORY_CONNECTIVITY, "%s: auto_connect etcp_link_new failed idx=%d", CC_ID, i); u_free(pctx); etcp_connection_close(conn); - pst->conns[i] = NULL; pst->timers[i] = NULL; pst->pending_count--; continue; + pst->conns[i] = NULL; pst->timers[i] = NULL; pst->ctxs[i] = NULL; pst->pending_count--; continue; } pst->conns[i] = conn; pst->timers[i] = uasync_set_timeout(g_cc.inst->ua, CA_CONNECT_TIMEOUT_MS * 10,