diff --git a/include/fluent-bit/flb_config_format.h b/include/fluent-bit/flb_config_format.h index 72f6f31cddd..8205ebcc1cd 100644 --- a/include/fluent-bit/flb_config_format.h +++ b/include/fluent-bit/flb_config_format.h @@ -29,4 +29,6 @@ #include "config_format/flb_cf_yaml.h" #endif -#endif \ No newline at end of file +#define FLB_DEFAULT_CF_BUF_SIZE 4096 + +#endif diff --git a/src/config_format/flb_cf_fluentbit.c b/src/config_format/flb_cf_fluentbit.c index f973654ad35..ac72f9425e4 100644 --- a/src/config_format/flb_cf_fluentbit.c +++ b/src/config_format/flb_cf_fluentbit.c @@ -40,7 +40,6 @@ #define PATH_MAX MAX_PATH #endif -#define FLB_CF_BUF_SIZE 4096 #define FLB_CF_FILE_NUM_LIMIT 1000 /* indent checker return codes */ @@ -418,6 +417,8 @@ static int read_config(struct flb_cf *cf, struct local_ctx *ctx, char *val = NULL; int val_len; char *buf; + char *fgets_ptr; + size_t bufsize = FLB_DEFAULT_CF_BUF_SIZE; char tmp[PATH_MAX]; flb_sds_t section = NULL; flb_sds_t indent = NULL; @@ -427,6 +428,9 @@ static int read_config(struct flb_cf *cf, struct local_ctx *ctx, struct flb_cf_section *current_section = NULL; struct flb_cf_group *current_group = NULL; struct cfl_variant *var; + unsigned long line_hard_limit; + + line_hard_limit = 32 * 1024 * 1024; /* 32MiB */ FILE *f = NULL; @@ -479,14 +483,14 @@ static int read_config(struct flb_cf *cf, struct local_ctx *ctx, #ifndef FLB_HAVE_STATIC_CONF /* Open configuration file */ - if ((f = fopen(cfg_file, "r")) == NULL) { + if ((f = fopen(cfg_file, "rb")) == NULL) { flb_warn("[config] I cannot open %s file", cfg_file); return -1; } #endif /* Allocate temporal buffer to read file content */ - buf = flb_malloc(FLB_CF_BUF_SIZE); + buf = flb_malloc(bufsize); if (!buf) { flb_errno(); goto error; @@ -501,7 +505,9 @@ static int read_config(struct flb_cf *cf, struct local_ctx *ctx, while (static_fgets(buf, FLB_CF_BUF_SIZE, in_data, &off)) { #else /* normal mode, read lines into a buffer */ - while (fgets(buf, FLB_CF_BUF_SIZE, f)) { + /* note that we use "fgets_ptr" so we can continue reading after realloc */ + fgets_ptr = buf; + while (fgets(fgets_ptr, bufsize - (fgets_ptr - buf), f)) { #endif len = strlen(buf); if (len > 0 && buf[len - 1] == '\n') { @@ -509,18 +515,31 @@ static int read_config(struct flb_cf *cf, struct local_ctx *ctx, if (len && buf[len - 1] == '\r') { buf[--len] = 0; } + /* after a successful line read, restore "fgets_ptr" to point to the + * beginning of buffer */ + fgets_ptr = buf; + } else if (feof(f)) { + /* handle EOF without a newline(CRLF or LF) */ + fgets_ptr = buf; } #ifndef FLB_HAVE_STATIC_CONF else { - /* - * If we don't find a break line, validate if we got an EOF or not. No EOF - * means that the incoming string is not finished so we must raise an - * exception. - */ - if (!feof(f)) { - config_error(cfg_file, line, "length of content has exceeded limit"); + /* resize the line buffer */ + bufsize *= 2; + if (bufsize > line_hard_limit) { + flb_error("reading line is exceeded to the limit size of %lu. Current size is: %zu", + line_hard_limit, bufsize); goto error; } + buf = flb_realloc(buf, bufsize); + if (!buf) { + flb_error("failed to resize line buffer to %zu", bufsize); + flb_errno(); + goto error; + } + /* read more, starting at the buf + len position */ + fgets_ptr = buf + len; + continue; } #endif diff --git a/tests/internal/config_format_fluentbit.c b/tests/internal/config_format_fluentbit.c index 9244a481600..5104ae62032 100644 --- a/tests/internal/config_format_fluentbit.c +++ b/tests/internal/config_format_fluentbit.c @@ -17,6 +17,7 @@ #define FLB_002 FLB_TESTS_DATA_PATH "/data/config_format/classic/indent_level_error.conf" #define FLB_003 FLB_TESTS_DATA_PATH "/data/config_format/classic/recursion.conf" #define FLB_004 FLB_TESTS_DATA_PATH "/data/config_format/classic/issue6281.conf" +#define FLB_005 FLB_TESTS_DATA_PATH "/data/config_format/classic/nolimitline.conf" #define ERROR_LOG "fluentbit_conf_error.log" @@ -258,11 +259,59 @@ void not_current_dir_files() } } +/* data/config_format/nolimitline.conf */ +void test_nolimit_line() +{ + struct mk_list *head; + struct flb_cf *cf; + struct flb_cf_section *s; + struct cfl_list *p_head; + struct cfl_kvpair *kv; + + cf = flb_cf_fluentbit_create(NULL, FLB_005, NULL, 0); + TEST_CHECK(cf != NULL); + + /* Total number of sections */ + TEST_CHECK(mk_list_size(&cf->sections) == 3); + + /* SERVICE check */ + TEST_CHECK(cf->service == NULL); + + /* Meta commands */ + TEST_CHECK(mk_list_size(&cf->metas) == 0); + + /* Check number sections per list */ + TEST_CHECK(mk_list_size(&cf->inputs) == 1); + TEST_CHECK(mk_list_size(&cf->filters) == 1); + TEST_CHECK(mk_list_size(&cf->outputs) == 1); + + /* Check the previous line buffer limit */ + s = flb_cf_section_get_by_name(cf, "filter"); + TEST_CHECK(s != NULL); + TEST_CHECK(mk_list_size(&s->groups) == 0); + + if (cfl_list_size(&s->properties->list) > 0) { + TEST_CHECK(cfl_list_size(&s->properties->list) == 4); + cfl_list_foreach(p_head, &s->properties->list) { + kv = cfl_list_entry(p_head, struct cfl_kvpair, _head); + if (strcmp(kv->key, "code") == 0) { + TEST_CHECK(cfl_sds_len(kv->val->data.as_string) > FLB_DEFAULT_CF_BUF_SIZE); + } + } + } + + printf("\n"); + flb_cf_dump(cf); + + flb_cf_destroy(cf); +} + TEST_LIST = { { "basic" , test_basic}, { "missing_value_issue5880" , missing_value}, { "indent_level_error" , indent_level_error}, { "recursion" , recursion}, { "not_current_dir_files", not_current_dir_files}, + { "no_limit_line", test_nolimit_line}, { 0 } }; diff --git a/tests/internal/data/config_format/classic/nolimitline.conf b/tests/internal/data/config_format/classic/nolimitline.conf new file mode 100644 index 00000000000..e7fff842015 --- /dev/null +++ b/tests/internal/data/config_format/classic/nolimitline.conf @@ -0,0 +1,11 @@ +[INPUT] + name dummy + +[FILTER] + Name lua + Match * + code local str = 'abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd'; function cb_filter(tag, ts, record) record.str = str; return 1, ts, record end + call cb_filter + +[OUTPUT] + name stdout