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.
This commit is contained in:
Willy Tarreau 2026-04-30 07:58:23 +02:00
parent 19e17fd6e2
commit 76d894956f

View File

@ -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;
}