From 76d894956f7c83bd503afc65a8c8240a6c527f40 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 30 Apr 2026 07:58:23 +0200 Subject: [PATCH] BUG/MINOR: sink: do not free existing sinks on allocation error In 3.1 with commit 1bdf6e884a ("MEDIUM: sink: implement sink_find_early()") sink creation started to support plugging to an existing sink and only updating the description. However if the strdup() for the new description failed, it would go down the error path releasing everything, while leaving the released entry in the sink list and leaving other users still attached to it. Here we take a different approach, we first allocate the new description, and release the old one on success, otherwise we leave the entry unchanged. And we only release new sinks, not old ones. This way allocation errors just do not change what is already referenced elsewhere, so that error unrolling remains clean. This remains of low importance anyway since it's only a case of boot error aggravation. Not really needed to be backported. --- src/sink.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/sink.c b/src/sink.c index e207db871..ec0eb9d46 100644 --- a/src/sink.c +++ b/src/sink.c @@ -116,19 +116,19 @@ struct sink *sink_find_early(const char *name, const char *from, const char *fil /* creates a new sink and adds it to the list, it's still generic and not fully * initialized. Returns NULL on allocation failure. If another one already * exists with the same name, it will be returned. The caller can detect it as - * a newly created one has type SINK_TYPE_NEW. + * a newly created one has type SINK_TYPE_NEW. Allocation failures do not change + * existing sinks. */ static struct sink *__sink_new(const char *name, const char *desc, int fmt) { struct sink *sink; uint8_t _new = 0; + char *new_desc = NULL; sink = _sink_find(name); if (sink) { - if (sink->type == SINK_TYPE_FORWARD_DECLARED) { - ha_free(&sink->desc); // free previous desc + if (sink->type == SINK_TYPE_FORWARD_DECLARED) goto forward_declared; - } goto end; } @@ -142,10 +142,12 @@ static struct sink *__sink_new(const char *name, const char *desc, int fmt) goto err; forward_declared: - sink->desc = strdup(desc); - if (!sink->desc) + new_desc = strdup(desc); + if (!new_desc) goto err; + free(sink->desc); + sink->desc = new_desc; sink->fmt = fmt; sink->type = SINK_TYPE_NEW; sink->maxlen = BUFSIZE; @@ -158,9 +160,11 @@ static struct sink *__sink_new(const char *name, const char *desc, int fmt) return sink; err: - ha_free(&sink->name); - ha_free(&sink->desc); - ha_free(&sink); + if (_new) { + ha_free(&sink->name); + ha_free(&sink->desc); + ha_free(&sink); + } return NULL; }