Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions include/fluent-bit/flb_plugin_alias.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

/* Fluent Bit
* ==========
* Copyright (C) 2015-2026 The Fluent Bit Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef FLB_PLUGIN_ALIAS_H
#define FLB_PLUGIN_ALIAS_H

#include <stddef.h>

/*
* Returned by flb_plugin_alias_rewrite() when an alias exists but an internal
* error prevents generating a rewritten string.
*/
#define FLB_PLUGIN_ALIAS_ERR ((char *) -1)

/*
* Returns the canonical plugin name for alias_name when a mapping exists,
* otherwise returns NULL.
*/
const char *flb_plugin_alias_get(int plugin_type, const char *alias_name,
size_t alias_name_length);

/*
* Rewrites plugin_reference when it starts with a known alias.
*
* Return values:
* - NULL: no rewrite needed
* - FLB_PLUGIN_ALIAS_ERR: rewrite needed but failed
* - allocated string: rewritten plugin reference (caller must free)
*/
char *flb_plugin_alias_rewrite(int plugin_type, const char *plugin_reference);

#endif
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ set(src
flb_crypto.c
flb_random.c
flb_plugin.c
flb_plugin_alias.c
flb_gzip.c
flb_snappy.c
flb_zstd.c
Expand Down
14 changes: 12 additions & 2 deletions src/flb_network.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ int flb_net_host_set(const char *plugin_name, struct flb_net_host *host, const c
int len;
int olen;
const char *s, *e, *u;
const char *separator;

memset(host, '\0', sizeof(struct flb_net_host));

Expand All @@ -174,7 +175,16 @@ int flb_net_host_set(const char *plugin_name, struct flb_net_host *host, const c
return -1;
}

s = address + len;
separator = strchr(address, ':');
if (separator != NULL &&
separator != address &&
separator[1] == '/' &&
separator[2] == '/') {
s = separator + 3;
}
else {
s = address + len;
}
if (*s == '[') {
/* IPv6 address (RFC 3986) */
e = strchr(++s, ']');
Expand Down Expand Up @@ -2344,4 +2354,4 @@ uint64_t flb_net_htonll(uint64_t value)
#else
return value;
#endif
}
}
40 changes: 34 additions & 6 deletions src/flb_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <fluent-bit/flb_macros.h>
#include <fluent-bit/flb_utils.h>
#include <fluent-bit/flb_plugin.h>
#include <fluent-bit/flb_plugin_alias.h>
#include <fluent-bit/flb_plugin_proxy.h>
#include <fluent-bit/flb_http_client_debug.h>
#include <fluent-bit/flb_output_thread.h>
Expand Down Expand Up @@ -128,6 +129,7 @@ static int check_protocol(const char *prot, const char *output)
{
int len;
char *p;
const char *alias_target;

p = strstr(output, "://");
if (p && p != output) {
Expand All @@ -137,12 +139,16 @@ static int check_protocol(const char *prot, const char *output)
len = strlen(output);
}

if (strlen(prot) != len) {
return 0;
/* Output plugin match */
if (strlen(prot) == (size_t) len &&
strncasecmp(prot, output, len) == 0) {
return 1;
}

/* Output plugin match */
if (strncasecmp(prot, output, len) == 0) {
alias_target = flb_plugin_alias_get(FLB_PLUGIN_OUTPUT, output, len);
if (alias_target != NULL &&
strlen(alias_target) == strlen(prot) &&
strcasecmp(prot, alias_target) == 0) {
return 1;
}

Expand Down Expand Up @@ -676,6 +682,8 @@ struct flb_output_instance *flb_output_new(struct flb_config *config,
{
int ret = -1;
int flags = 0;
const char *output_name;
char *output_uri;
struct mk_list *head;
struct flb_output_plugin *plugin;
struct flb_output_instance *instance = NULL;
Expand All @@ -684,9 +692,12 @@ struct flb_output_instance *flb_output_new(struct flb_config *config,
return NULL;
}

output_name = output;
output_uri = NULL;

mk_list_foreach(head, &config->out_plugins) {
plugin = mk_list_entry(head, struct flb_output_plugin, _head);
if (!check_protocol(plugin->name, output)) {
if (!check_protocol(plugin->name, output_name)) {
plugin = NULL;
continue;
}
Expand Down Expand Up @@ -818,7 +829,24 @@ struct flb_output_instance *flb_output_new(struct flb_config *config,
#endif

if (plugin->flags & FLB_OUTPUT_NET) {
ret = flb_net_host_set(plugin->name, &instance->host, output);
output_uri = flb_plugin_alias_rewrite(FLB_PLUGIN_OUTPUT, output_name);
if (output_uri == FLB_PLUGIN_ALIAS_ERR) {
if (instance->flags & FLB_OUTPUT_SYNCHRONOUS) {
flb_task_queue_destroy(instance->singleplex_queue);
}
flb_free(instance->http_server_config);
flb_free(instance);
return NULL;
Comment on lines +832 to +839
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fully unwind instance on the new alias-rewrite error path.

By this point instance->callback is already live and non-core plugins may also have allocated instance->context. Returning here only frees the outer structs, so FLB_PLUGIN_ALIAS_ERR leaks initialized state; singleplex_queue also has not been created yet on this path.

💡 Suggested cleanup
         output_uri = flb_plugin_alias_rewrite(FLB_PLUGIN_OUTPUT, output_name);
         if (output_uri == FLB_PLUGIN_ALIAS_ERR) {
-            if (instance->flags & FLB_OUTPUT_SYNCHRONOUS) {
+            if ((instance->flags & FLB_OUTPUT_SYNCHRONOUS) &&
+                instance->singleplex_queue != NULL) {
                 flb_task_queue_destroy(instance->singleplex_queue);
             }
+            if (instance->callback != NULL) {
+                flb_callback_destroy(instance->callback);
+            }
+            if (plugin->type != FLB_OUTPUT_PLUGIN_CORE &&
+                instance->context != NULL) {
+                flb_free(instance->context);
+            }
             flb_free(instance->http_server_config);
             flb_free(instance);
             return NULL;
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/flb_output.c` around lines 832 - 839, When flb_plugin_alias_rewrite
returns FLB_PLUGIN_ALIAS_ERR you must fully unwind the partially-initialized
instance: if instance->callback is set invoke the plugin teardown callback
(using the same callback signature used elsewhere) so the plugin can free its
state, free instance->context if non-NULL, destroy instance->singleplex_queue
only if it was created/non-NULL (and/or when instance->flags &
FLB_OUTPUT_SYNCHRONOUS), then free instance->http_server_config and finally free
instance; implement this sequence in the error branch that handles output_uri ==
FLB_PLUGIN_ALIAS_ERR to avoid leaking plugin state.

}
else if (output_uri != NULL) {
output_name = output_uri;
}

ret = flb_net_host_set(plugin->name, &instance->host, output_name);
if (output_uri != NULL) {
flb_free(output_uri);
}

if (ret != 0) {
if (instance->flags & FLB_OUTPUT_SYNCHRONOUS) {
flb_task_queue_destroy(instance->singleplex_queue);
Expand Down
144 changes: 144 additions & 0 deletions src/flb_plugin_alias.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

/* Fluent Bit
* ==========
* Copyright (C) 2015-2026 The Fluent Bit Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <stdio.h>
#include <string.h>

#include <fluent-bit/flb_mem.h>
#include <fluent-bit/flb_config.h>
#include <fluent-bit/flb_plugin.h>
#include <fluent-bit/flb_plugin_alias.h>

struct flb_plugin_alias_entry {
int plugin_type;
const char *alias_name;
const char *plugin_name;
};

/*
* Table that maps user-facing aliases to plugin short names.
*
* Keep this table focused on backwards/forwards compatibility names where the
* historical short name is still used internally by the plugin implementation.
*/
static struct flb_plugin_alias_entry plugin_aliases[] = {
{
FLB_PLUGIN_OUTPUT,
"elasticsearch",
"es"
},
{
0,
NULL,
NULL
}
};

static size_t protocol_part_length(const char *plugin_reference)
{
char *separator;

separator = strstr(plugin_reference, "://");
if (separator != NULL && separator != plugin_reference) {
return (size_t) (separator - plugin_reference);
}

return strlen(plugin_reference);
}

const char *flb_plugin_alias_get(int plugin_type, const char *alias_name,
size_t alias_name_length)
{
int index;
struct flb_plugin_alias_entry *entry;

if (alias_name == NULL || alias_name_length == 0) {
return NULL;
}

for (index = 0; plugin_aliases[index].alias_name != NULL; index++) {
entry = &plugin_aliases[index];

if (entry->plugin_type != plugin_type) {
continue;
}

if (strlen(entry->alias_name) != alias_name_length) {
continue;
}

if (strncasecmp(entry->alias_name, alias_name, alias_name_length) == 0) {
return entry->plugin_name;
}
}

return NULL;
}

char *flb_plugin_alias_rewrite(int plugin_type, const char *plugin_reference)
{
int ret;
size_t reference_length;
size_t protocol_length;
size_t plugin_name_length;
char *rewritten_reference;
const char *plugin_name;

if (plugin_reference == NULL) {
return NULL;
}

protocol_length = protocol_part_length(plugin_reference);
if (protocol_length == 0) {
return NULL;
}

plugin_name = flb_plugin_alias_get(plugin_type, plugin_reference,
protocol_length);
if (plugin_name == NULL) {
return NULL;
}

plugin_name_length = strlen(plugin_name);

if (plugin_name_length == protocol_length &&
strncasecmp(plugin_name, plugin_reference, protocol_length) == 0) {
return NULL;
}

reference_length = strlen(plugin_reference);
rewritten_reference = flb_calloc(1, reference_length - protocol_length +
plugin_name_length + 1);
if (rewritten_reference == NULL) {
flb_errno();
return FLB_PLUGIN_ALIAS_ERR;
}

memcpy(rewritten_reference, plugin_name, plugin_name_length);

ret = snprintf(rewritten_reference + plugin_name_length,
reference_length - protocol_length + 1,
"%s", plugin_reference + protocol_length);
if (ret < 0) {
flb_free(rewritten_reference);
return FLB_PLUGIN_ALIAS_ERR;
}

return rewritten_reference;
}
1 change: 1 addition & 0 deletions tests/internal/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ set(UNIT_TESTS_FILES
endianness.c
task_map.c
strptime.c
plugin_alias.c
storage_inherit.c
unicode.c
opentelemetry.c
Expand Down
Loading
Loading