summaryrefslogtreecommitdiffstats
path: root/fluent-bit/tests/internal/fuzzers
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--fluent-bit/tests/internal/fuzzers/CMakeLists.txt60
-rw-r--r--fluent-bit/tests/internal/fuzzers/aws_credentials_fuzzer.c132
-rw-r--r--fluent-bit/tests/internal/fuzzers/aws_util_fuzzer.c107
-rw-r--r--fluent-bit/tests/internal/fuzzers/base64_fuzzer.c20
-rw-r--r--fluent-bit/tests/internal/fuzzers/cmetrics_decode_fuzz.c69
-rw-r--r--fluent-bit/tests/internal/fuzzers/config_fuzzer.c417
-rw-r--r--fluent-bit/tests/internal/fuzzers/config_map_fuzzer.c212
-rw-r--r--fluent-bit/tests/internal/fuzzers/config_random_fuzzer.c57
-rw-r--r--fluent-bit/tests/internal/fuzzers/config_yaml_fuzzer.c65
-rw-r--r--fluent-bit/tests/internal/fuzzers/ctrace_fuzzer.c24
-rw-r--r--fluent-bit/tests/internal/fuzzers/engine_fuzzer.c171
-rw-r--r--fluent-bit/tests/internal/fuzzers/filter_stdout_fuzzer.c62
-rw-r--r--fluent-bit/tests/internal/fuzzers/flb_fuzz_header.h42
-rw-r--r--fluent-bit/tests/internal/fuzzers/flb_json_fuzzer.c82
-rw-r--r--fluent-bit/tests/internal/fuzzers/flb_mp_fuzzer.c55
-rw-r--r--fluent-bit/tests/internal/fuzzers/fstore_fuzzer.c86
-rw-r--r--fluent-bit/tests/internal/fuzzers/http_fuzzer.c116
-rw-r--r--fluent-bit/tests/internal/fuzzers/input_fuzzer.c164
-rw-r--r--fluent-bit/tests/internal/fuzzers/local_test.c85
-rw-r--r--fluent-bit/tests/internal/fuzzers/msgpack_parse_fuzzer.c30
-rw-r--r--fluent-bit/tests/internal/fuzzers/msgpack_to_gelf_fuzzer.c25
-rw-r--r--fluent-bit/tests/internal/fuzzers/multiline_fuzzer.c180
-rw-r--r--fluent-bit/tests/internal/fuzzers/pack_json_state_fuzzer.c25
-rw-r--r--fluent-bit/tests/internal/fuzzers/parse_json_fuzzer.c69
-rw-r--r--fluent-bit/tests/internal/fuzzers/parse_logfmt_fuzzer.c50
-rw-r--r--fluent-bit/tests/internal/fuzzers/parse_ltsv_fuzzer.c35
-rw-r--r--fluent-bit/tests/internal/fuzzers/parser_fuzzer.c203
-rw-r--r--fluent-bit/tests/internal/fuzzers/record_ac_fuzzer.c101
-rw-r--r--fluent-bit/tests/internal/fuzzers/signv4_fuzzer.c111
-rw-r--r--fluent-bit/tests/internal/fuzzers/strp_fuzzer.c35
-rw-r--r--fluent-bit/tests/internal/fuzzers/utils_fuzzer.c242
31 files changed, 3132 insertions, 0 deletions
diff --git a/fluent-bit/tests/internal/fuzzers/CMakeLists.txt b/fluent-bit/tests/internal/fuzzers/CMakeLists.txt
new file mode 100644
index 00000000..e76be548
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/CMakeLists.txt
@@ -0,0 +1,60 @@
+set(UNIT_TESTS_FILES
+ aws_util_fuzzer.c
+ aws_credentials_fuzzer.c
+ base64_fuzzer.c
+ engine_fuzzer.c
+ cmetrics_decode_fuzz.c
+ config_fuzzer.c
+ config_random_fuzzer.c
+ ctrace_fuzzer.c
+ input_fuzzer.c
+ signv4_fuzzer.c
+ flb_json_fuzzer.c
+ flb_mp_fuzzer.c
+ filter_stdout_fuzzer.c
+ fstore_fuzzer.c
+ parser_fuzzer.c
+ parse_json_fuzzer.c
+ parse_logfmt_fuzzer.c
+ parse_ltsv_fuzzer.c
+ msgpack_parse_fuzzer.c
+ msgpack_to_gelf_fuzzer.c
+ multiline_fuzzer.c
+ pack_json_state_fuzzer.c
+ http_fuzzer.c
+ strp_fuzzer.c
+ utils_fuzzer.c
+ config_map_fuzzer.c
+ record_ac_fuzzer.c
+ config_yaml_fuzzer.c
+ )
+
+# Prepare list of unit tests
+foreach(source_file ${UNIT_TESTS_FILES})
+ get_filename_component(source_file_we ${source_file} NAME_WE)
+ set(source_file_we flb-it-fuzz-${source_file_we})
+
+ add_executable(
+ ${source_file_we}
+ ${source_file} local_test.c
+ )
+
+ if(FLB_JEMALLOC)
+ target_link_libraries(${source_file_we} libjemalloc ${CMAKE_THREAD_LIBS_INIT})
+ else()
+ target_link_libraries(${source_file_we} ${CMAKE_THREAD_LIBS_INIT})
+ endif()
+
+ if(FLB_STREAM_PROCESSOR)
+ target_link_libraries(${source_file_we} flb-sp)
+ endif()
+
+ target_link_libraries(${source_file_we} fluent-bit-static)
+
+ if (FLB_TESTS_OSSFUZZ)
+ add_executable(${source_file_we}_OSSFUZZ ${source_file})
+ target_link_libraries(${source_file_we}_OSSFUZZ ${CMAKE_THREAD_LIBS_INIT})
+ set_target_properties(${source_file_we}_OSSFUZZ PROPERTIES LINK_FLAGS $ENV{LIB_FUZZING_ENGINE})
+ target_link_libraries(${source_file_we}_OSSFUZZ fluent-bit-static)
+ endif()
+endforeach()
diff --git a/fluent-bit/tests/internal/fuzzers/aws_credentials_fuzzer.c b/fluent-bit/tests/internal/fuzzers/aws_credentials_fuzzer.c
new file mode 100644
index 00000000..d6ccb22e
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/aws_credentials_fuzzer.c
@@ -0,0 +1,132 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* Fluent Bit
+ * ==========
+ * Copyright (C) 2023 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 <stdint.h>
+#include <fluent-bit.h>
+#include <fluent-bit/flb_sds.h>
+#include <fluent-bit/flb_aws_credentials.h>
+#include <fluent-bit/flb_mem.h>
+#include "flb_fuzz_header.h"
+
+int initialization_crutch()
+{
+ struct flb_config *config;
+ config = flb_config_init();
+ if (config == NULL) {
+ return -1;
+ }
+ flb_config_exit(config);
+ return 0;
+}
+
+
+void fuzz_sts(const uint8_t *data, size_t size) {
+ char *sks_response = get_null_terminated(150, &data, &size);
+
+ struct flb_aws_credentials *creds;
+ time_t expiration;
+
+ creds = flb_parse_sts_resp(sks_response, &expiration);
+ if (creds != NULL) {
+ flb_aws_credentials_destroy(creds);
+ }
+
+ if (size > 300) {
+ char *action = get_null_terminated(50, &data, &size);
+ char *role_arn = get_null_terminated(50, &data, &size);
+ char *session_name = get_null_terminated(50, &data, &size);
+ char *external_id = get_null_terminated(50, &data, &size);
+ char *identity_token = get_null_terminated(50, &data, &size);
+
+ flb_sds_t s1 = flb_sts_uri(action, role_arn, session_name,
+ external_id, identity_token);
+ if (s1 != NULL) {
+ flb_sds_destroy(s1);
+ }
+
+ flb_free(action);
+ flb_free(role_arn);
+ flb_free(session_name);
+ flb_free(external_id);
+ flb_free(identity_token);
+ }
+
+ if (sks_response != NULL) {
+ flb_free(sks_response);
+ }
+}
+
+
+void fuzz_http(const uint8_t *data, size_t size) {
+ time_t expiration;
+ struct flb_aws_credentials *creds = NULL;
+
+ char *response = get_null_terminated(250, &data, &size);
+ creds = flb_parse_http_credentials(response, 250, &expiration);
+ if (creds != NULL) {
+ flb_aws_credentials_destroy(creds);
+ }
+ flb_free(response);
+}
+
+
+void fuzz_process(const uint8_t *data, size_t size) {
+ char** tokens = NULL;
+ char *input = get_null_terminated(250, &data, &size);
+ tokens = parse_credential_process(input);
+ if (tokens != NULL) {
+ flb_free(tokens);
+ }
+ flb_free(input);
+}
+
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ /* Set flb_malloc_mod to be fuzzer-data dependent */
+ if (size < 304) {
+ return 0;
+ }
+ flb_malloc_p = 0;
+ flb_malloc_mod = *(int*)data;
+ data += 4;
+ size -= 4;
+
+ /* Avoid division by zero for modulo operations */
+ if (flb_malloc_mod == 0) {
+ flb_malloc_mod = 1;
+ }
+ if (initialization_crutch() == -1) {
+ return 0;
+ }
+
+ const uint8_t *data_copy = data;
+ size_t size_copy = size;
+ fuzz_sts(data_copy, size_copy);
+
+ data_copy = data;
+ size_copy = size;
+ fuzz_http(data_copy, size_copy);
+
+ data_copy = data;
+ size_copy = size;
+ fuzz_process(data_copy, size_copy);
+
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/aws_util_fuzzer.c b/fluent-bit/tests/internal/fuzzers/aws_util_fuzzer.c
new file mode 100644
index 00000000..dcaa2b9e
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/aws_util_fuzzer.c
@@ -0,0 +1,107 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* Fluent Bit
+ * ==========
+ * Copyright (C) 2023 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 <stdint.h>
+#include <fluent-bit.h>
+#include <fluent-bit/flb_sds.h>
+#include <fluent-bit/flb_aws_util.h>
+#include <fluent-bit/flb_mem.h>
+#include "flb_fuzz_header.h"
+
+int initialization_crutch()
+{
+ struct flb_config *config;
+ config = flb_config_init();
+ if (config == NULL) {
+ return -1;
+ }
+ flb_config_exit(config);
+ return 0;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ char *format = NULL;
+ char *tag = NULL;
+ char *tag_delimiter = NULL;
+
+ /* Set flb_malloc_mod to be fuzzer-data dependent */
+ if (size < 4) {
+ return 0;
+ }
+ flb_malloc_p = 0;
+ flb_malloc_mod = *(int*)data;
+ data += 4;
+ size -= 4;
+
+ /* Avoid division by zero for modulo operations */
+ if (flb_malloc_mod == 0) {
+ flb_malloc_mod = 1;
+ }
+
+ if (size < 300) {
+ return 0;
+ }
+
+ format = get_null_terminated(50, &data, &size);
+ tag = get_null_terminated(100, &data, &size);
+ tag_delimiter = get_null_terminated(100, &data, &size);
+
+ struct tm day = { 0, 0, 0, 15, 7, 120};
+ time_t t;
+ memset(&t, 0, sizeof(time_t));
+
+ if (format && tag && tag_delimiter) {
+ if (!initialization_crutch()) {
+ flb_sds_t s3_key_format = NULL;
+ s3_key_format = flb_get_s3_key(format, t, tag, tag_delimiter, 0);
+ if (s3_key_format) {
+ flb_sds_destroy(s3_key_format);
+ }
+ if (size > 200) {
+ char *json_val = get_null_terminated(100, &data, &size);
+ if (json_val != NULL) {
+ flb_sds_t s1 = flb_aws_error(json_val, strlen(json_val));
+ if (s1 != NULL) {
+ flb_sds_destroy(s1);
+ }
+ flb_free(json_val);
+ }
+ char *xml_val = get_null_terminated(100, &data, &size);
+ if (xml_val != NULL) {
+ flb_sds_t s2 = flb_aws_xml_error(xml_val, strlen(xml_val));
+ if (s2 != NULL) {
+ flb_sds_destroy(s2);
+ }
+ flb_free(xml_val);
+ }
+ }
+ }
+ }
+ if (format) {
+ flb_free(format);
+ }
+ if (tag) {
+ flb_free(tag);
+ }
+ if (tag_delimiter) {
+ flb_free(tag_delimiter);
+ }
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/base64_fuzzer.c b/fluent-bit/tests/internal/fuzzers/base64_fuzzer.c
new file mode 100644
index 00000000..90c4c08f
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/base64_fuzzer.c
@@ -0,0 +1,20 @@
+#include <unistd.h>
+#include <stdint.h>
+#include <fluent-bit/flb_base64.h>
+#include <fluent-bit/flb_mem.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ char out[100];
+ size_t olen;
+
+ /* Set fuzzer-malloc chance of failure */
+ flb_malloc_p = 0;
+ flb_malloc_mod = 25000;
+
+ flb_base64_encode((unsigned char *) out, 100,
+ &olen, (unsigned char *)data, size);
+ flb_base64_decode((unsigned char *) out, 100,
+ &olen, (unsigned char *)data, size);
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/cmetrics_decode_fuzz.c b/fluent-bit/tests/internal/fuzzers/cmetrics_decode_fuzz.c
new file mode 100644
index 00000000..1d1098c0
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/cmetrics_decode_fuzz.c
@@ -0,0 +1,69 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* Fluent Bit
+ * ==========
+ * Copyright (C) 2015-2023 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 <cmetrics/cmt_decode_opentelemetry.h>
+#include <cmetrics/cmt_decode_prometheus.h>
+
+
+int
+LLVMFuzzerTestOneInput(const uint8_t * data, size_t size)
+{
+ struct cfl_list decoded_contexts;
+ struct cmt *cmt = NULL;
+ size_t off = 0;
+ uint8_t decider;
+ int result;
+
+ /* At least one byte is needed for deciding which decoder to use */
+ if (size < 1) {
+ return 0;
+ }
+
+ decider = data[0] % 3;
+
+ /* Adjust data pointer since the first byte is used */
+ data += 1;
+ size -= 1;
+
+ /* Fuzz a given decoder */
+ if (decider == 0) {
+ result = cmt_decode_opentelemetry_create(&decoded_contexts, data, size,
+ &off);
+ if (result == CMT_DECODE_OPENTELEMETRY_SUCCESS) {
+ cmt_decode_opentelemetry_destroy (&decoded_contexts);
+ }
+ }
+ else if (decider == 1) {
+ result = cmt_decode_msgpack_create(&cmt, (char *) data, size, &off);
+ if (result == 0) {
+ cmt_destroy(cmt);
+ }
+ }
+ else if (decider == 2) {
+ if (size == 0) {
+ return 0;
+ }
+ struct cmt_decode_prometheus_parse_opts opts;
+ result = cmt_decode_prometheus_create(&cmt, data, size, &opts);
+ if (result == CMT_DECODE_PROMETHEUS_SUCCESS) {
+ cmt_decode_prometheus_destroy(cmt);
+ }
+ }
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/config_fuzzer.c b/fluent-bit/tests/internal/fuzzers/config_fuzzer.c
new file mode 100644
index 00000000..5512dac2
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/config_fuzzer.c
@@ -0,0 +1,417 @@
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fluent-bit/flb_parser.h>
+#include <fluent-bit/flb_slist.h>
+#include <fluent-bit/flb_kv.h>
+#include "flb_fuzz_header.h"
+
+/* A sample of configurations */
+char conf_file[] = "# Parser: no_year\n"
+"# ===============\n"
+"# the given format don't contain the Year, this is a common\n"
+"# case on old Syslog implementations.\n"
+"#\n"
+"[PARSER]\n"
+" Name no_year\n"
+" Format json\n"
+" Time_Key time\n"
+" Time_Format %b %d %H:%M:%S\n"
+" Time_Keep On\n"
+"\n"
+"# Parser: no_year_N\n"
+"# =================\n"
+"# Just for compatibility, check a string with no year but including Nanoseconds.\n"
+"#\n"
+"[PARSER]\n"
+" Name no_year_N\n"
+" Format json\n"
+" Time_Key time\n"
+" Time_Format %b %d %H:%M:%S.%L\n"
+" Time_Keep On\n"
+"\n"
+"# Parser: no_year_NC\n"
+"# =================\n"
+"# Just for compatibility, check a string with no year but including Nanoseconds with comma as fractional separator.\n"
+"#\n"
+"[PARSER]\n"
+" Name no_year_NC\n"
+" Format json\n"
+" Time_Key time\n"
+" Time_Format %b %d %H:%M:%S,%L\n"
+" Time_Keep On\n"
+"\n"
+"# Parser: no_year_TZ\n"
+"# =================\n"
+"# Time string with no year and including timezone\n"
+"#\n"
+"[PARSER]\n"
+" Name no_year_TZ\n"
+" Format json\n"
+" Time_Key time\n"
+" Time_Format %b %d %H:%M:%S %z\n"
+" Time_Keep On\n"
+"\n"
+"# Parser: no_year_N_TZ\n"
+"# ====================\n"
+"# Time string with no year, nanoseconds and timezone\n"
+"#\n"
+"[PARSER]\n"
+" Name no_year_N_TZ\n"
+" Format json\n"
+" Time_Key time\n"
+" Time_Format %b %d %H:%M:%S.%L %z\n"
+" Time_Keep On\n"
+"\n"
+"\n"
+"# Parser: no_year_NC_TZ\n"
+"# ====================\n"
+"# Time string with no year, nanoseconds and timezone with comma as fractional separator.\n"
+"#\n"
+"[PARSER]\n"
+" Name no_year_NC_TZ\n"
+" Format json\n"
+" Time_Key time\n"
+" Time_Format %b %d %H:%M:%S,%L %z\n"
+" Time_Keep On\n"
+"\n"
+"\n"
+"# Parser: default_UTC\n"
+"# ===================\n"
+"# Time string with timezone in UTC\n"
+"#\n"
+"[PARSER]\n"
+" Name default_UTC\n"
+" Format json\n"
+" Time_Key time\n"
+" Time_Format %m/%d/%Y %H:%M:%S\n"
+" Time_Keep On\n"
+"\n"
+"# Parser: default_UTC_Z\n"
+"# =====================\n"
+"# Time string with timezone in UTC and ending Z\n"
+"#\n"
+"[PARSER]\n"
+" Name default_UTC_Z\n"
+" Format json\n"
+" Time_Key time\n"
+" Time_Format %m/%d/%Y %H:%M:%SZ\n"
+" Time_Keep On\n"
+"\n"
+"# Parser: default_UTC_N_Z\n"
+"# =======================\n"
+"# Time string with timezone in UTC, nanoseconds and ending Z\n"
+"#\n"
+"[PARSER]\n"
+" Name default_UTC_N_Z\n"
+" Format json\n"
+" Time_Key time\n"
+" Time_Format %m/%d/%Y %H:%M:%S.%LZ\n"
+" Time_Keep On\n"
+"\n"
+"# Parser: default_UTC_NC_Z\n"
+"# =======================\n"
+"# Time string with timezone in UTC, nanoseconds with comma as fractional separator and ending Z\n"
+"#\n"
+"[PARSER]\n"
+" Name default_UTC_NC_Z\n"
+" Format json\n"
+" Time_Key time\n"
+" Time_Format %m/%d/%Y %H:%M:%S,%LZ\n"
+" Time_Keep On\n"
+"\n"
+"# Parser: generic_TZ\n"
+"# ==================\n"
+"# Generic date with timezone\n"
+"#\n"
+"[PARSER]\n"
+" Name generic_TZ\n"
+" Format json\n"
+" Time_Key time\n"
+" Time_Format %m/%d/%Y %H:%M:%S %z\n"
+" Time_Keep On\n"
+"\n"
+"# Parser: generic\n"
+"# ===============\n"
+"# Generic date\n"
+"#\n"
+"[PARSER]\n"
+" Name generic\n"
+" Format json\n"
+" Time_Key time\n"
+" Time_Format %m/%d/%Y %H:%M:%S\n"
+" Time_Keep On\n"
+"\n"
+"# Parser: generic_N\n"
+"# ===============\n"
+"# Generic date with nanoseconds\n"
+"#\n"
+"[PARSER]\n"
+" Name generic_N\n"
+" Format json\n"
+" Time_Key time\n"
+" Time_Format %m/%d/%Y %H:%M:%S.%L\n"
+" Time_Keep On\n"
+"\n"
+"# Parser: generic_NC\n"
+"# ===============\n"
+"# Generic date with nanoseconds with comma as fractional separator\n"
+"#\n"
+"[PARSER]\n"
+" Name generic_NC\n"
+" Format json\n"
+" Time_Key time\n"
+" Time_Format %m/%d/%Y %H:%M:%S,%L\n"
+" Time_Keep On\n"
+"\n"
+"# Parser: generic_N_TZ\n"
+"# ====================\n"
+"# Generic date with nanoseconds and timezone\n"
+"#\n"
+"[PARSER]\n"
+" Name generic_N_TZ\n"
+" Format json\n"
+" Time_Key time\n"
+" Time_Format %m/%d/%Y %H:%M:%S.%L %z\n"
+" Time_Keep On\n"
+"\n"
+"# Parser: generic_NC_TZ\n"
+"# ====================\n"
+"# Generic date with nanoseconds with comma as fractional separator and timezone\n"
+"#\n"
+"[PARSER]\n"
+" Name generic_NC_TZ\n"
+" Format json\n"
+" Time_Key time\n"
+" Time_Format %m/%d/%Y %H:%M:%S,%L %z\n"
+" Time_Keep On\n"
+"\n"
+"# Parser: apache_error\n"
+"# ====================\n"
+"# Apache error log time format\n"
+"#\n"
+"[PARSER]\n"
+" Name apache_error\n"
+" Format json\n"
+" Time_Key time\n"
+" Time_Format %a %b %d %H:%M:%S.%L %Y\n"
+" Time_Keep On\n"
+"# Parser: mysql_quoted_stuff\n"
+"# ====================\n"
+"# Apache error log time format\n"
+"#\n"
+"[PARSER]\n"
+" Name mysql_quoted_stuff\n"
+" Format regex\n"
+" Regex ^(?<time>.*?),(?<key001>.*)$\n"
+" Time_Key time\n"
+" Time_Format %Y-%M-%S %H:%M:%S\n"
+" Time_Keep On\n"
+" Decode_Field_As mysql_quoted key001\n"
+"# Parser: REGEX_generic_NC_TZ\n"
+"# ====================\n"
+"# Generic date with nanoseconds with comma as fractional separator and timezone\n"
+"#\n"
+"[PARSER]\n"
+" Name REGEX_generic_NC_TZ\n"
+" Format regex\n"
+" Regex ^(?<key001>[^ ]*) (?<key002>[^ ]*) (?<time>.+)$\n"
+" Time_Key time\n"
+" Time_Format %m/%d/%Y %H:%M:%S,%L %z\n"
+" Time_Keep On\n"
+"\n"
+"# Parser: REGEX_apache_error\n"
+"# ====================\n"
+"# Apache error log time format\n"
+"#\n"
+"[PARSER]\n"
+" Name REGEX_apache_error\n"
+" Format regex\n"
+" Regex ^(?<key001>[^ ]*) (?<key002>[^ ]*) (?<time>.+)$\n"
+" Time_Key time\n"
+" Time_Format %a %b %d %H:%M:%S.%L %Y\n"
+" Time_Keep On\n"
+"\n"
+"\n"
+"\n"
+"# Parser: REGEX_mysql_quoted_stuff\n"
+"# ====================\n"
+"# Apache error log time format\n"
+"#\n"
+"[PARSER]\n"
+" Name REGEX_mysql_quoted_stuff\n"
+" Format regex\n"
+" Regex ^(?<time>.*?),(?<key001>.*)$\n"
+" Time_Key time\n"
+" Time_Format %Y-%M-%S %H:%M:%S\n"
+" Time_Keep On\n"
+" Decode_Field_As mysql_quoted key001\n"
+"\n"
+"\n"
+"\n"
+"# Parser: REGEX2_mysql_quoted_stuff\n"
+"# ====================\n"
+"# Apache error log time format\n"
+"#\n"
+"[PARSER]\n"
+" Name REGEX2_mysql_quoted_stuff\n"
+" Format logfmt\n"
+" Regex ^(?<time>.*?),(?<key001>.*)$\n"
+" Time_Key time\n"
+" Time_Format %Y-%M-%S %H:%M:%S\n"
+" Time_Keep On\n"
+" Decode_Field_As mysql_quoted key001\n"
+" Types A1:integer A2:string A3:bool A4:float A5:hex\n"
+"\n"
+"\n"
+"\n"
+"# Parser: REGEX3_mysql_quoted_stuff\n"
+"# ====================\n"
+"# Apache error log time format\n"
+"#\n"
+"[PARSER]\n"
+" Name REGEX3_mysql_quoted_stuff\n"
+" Format json\n"
+" Regex ^(?<time>.*?),(?<key001>.*)$\n"
+" Time_Key time\n"
+" Time_Format %Y-%M-%S %H:%M:%S\n"
+" Time_Keep On\n"
+" Decode_Field_As escaped_utf8 key001\n"
+" Types A1:integer A2:string A3:bool A4:float A5:hex\n"
+"\n"
+"\n"
+"\n"
+"# Parser: REGEX33_mysql_quoted_stuff\n"
+"# ====================\n"
+"# Apache error log time format\n"
+"#\n"
+"[PARSER]\n"
+" Name REGEX33_mysql_quoted_stuff\n"
+" Format json\n"
+" Regex ^(?<time>.*?),(?<key001>.*)$\n"
+" Time_Key time\n"
+" Time_Format %Y-%M-%S %H:%M:%S\n"
+" Time_Keep On\n"
+" Decode_Field_As escaped key001\n"
+" Types A1:integer A2:string A3:bool A4:float A5:hex\n"
+"\n"
+"\n"
+"\n"
+"# Parser: REGEX4_mysql_quoted_stuff\n"
+"# ====================\n"
+"# Apache error log time format\n"
+"#\n"
+"[PARSER]\n"
+" Name REGEX4_mysql_quoted_stuff\n"
+" Format json\n"
+" Regex ^(?<time>.*?),(?<key001>.*)$\n"
+" Time_Key time\n"
+" Time_Format %Y-%M-%S %H:%M:%S\n"
+" Time_Keep On\n"
+" Decode_Field_As json key001\n"
+" Types A1:integer A2:string A3:bool A4:float A5:hex\n"
+"[MULTILINE_PARSER]\n"
+" name exception_test\n"
+" type regex\n"
+" flush_timeout 1000\n"
+" rule \"start_state\" \"/(Dec \\d+ \\d+\\:\\d+\\:\\d+)(.*)/\" \"cont\"\n"
+" rule \"cont\" \"/^\\s+at.*/\" \"cont\"\n";
+
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ /* Set fuzzer-malloc chance of failure */
+ flb_malloc_p = 0;
+ flb_malloc_mod = 25000;
+
+ /* Limit the size of the config files to 32KB. */
+ if (size > 32768) {
+ return 0;
+ }
+
+ /* Write the config file to a location we know OSS-Fuzz has */
+ char filename[256];
+ sprintf(filename, "/tmp/libfuzzer.%d", getpid());
+ FILE *fp = fopen(filename, "wb");
+ if (!fp) {
+ return 0;
+ }
+ fwrite(conf_file, strlen(conf_file), 1, fp);
+ fclose(fp);
+
+
+ /* Now parse random data based on the config files */
+ struct flb_config *config = NULL;
+ config = flb_config_init();
+ int ret = flb_parser_conf_file(filename, config);
+ if (ret == 0) {
+ struct mk_list *head = NULL;
+ mk_list_foreach(head, &config->parsers) {
+ size_t out_size;
+ char *out_buf = NULL;
+ struct flb_parser *parser = NULL;
+ struct flb_time out_time;
+ parser = mk_list_entry(head, struct flb_parser, _head);
+ flb_parser_do(parser, (const char*)data, size, (void **)&out_buf,
+ &out_size, &out_time);
+ if (out_buf != NULL) {
+ free(out_buf);
+ }
+ }
+ }
+ flb_parser_exit(config);
+ flb_config_exit(config);
+
+ if (size > 100) {
+ /* Now let's do a second run where we also call flb_config_set_property */
+ config = flb_config_init();
+ ret = flb_parser_conf_file(filename, config);
+ char *key_1 = get_null_terminated(15, &data, &size);
+ char *val_1 = get_null_terminated(15, &data, &size);
+ char *key_2 = get_null_terminated(15, &data, &size);
+ char *val_2 = get_null_terminated(15, &data, &size);
+ char *progname = get_null_terminated(15, &data, &size);
+
+ flb_config_set_property(config, key_1, val_1);
+ flb_config_set_property(config, key_2, val_2);
+ flb_config_set_program_name(config, progname);
+ set_log_level_from_env(config);
+
+ struct mk_list prop;
+ flb_kv_init(&prop);
+ flb_kv_item_create(&prop, key_1, val_1);
+ flb_config_prop_get(progname, &prop);
+ flb_slist_entry_get(&prop, (int)data[0]);
+ flb_slist_dump(&prop);
+
+ if (ret == 0) {
+ struct mk_list *head = NULL;
+ mk_list_foreach(head, &config->parsers) {
+ size_t out_size;
+ char *out_buf = NULL;
+ struct flb_parser *parser = NULL;
+ struct flb_time out_time;
+
+ parser = mk_list_entry(head, struct flb_parser, _head);
+ flb_parser_do(parser, (const char*)data, size, (void **)&out_buf,
+ &out_size, &out_time);
+ if (out_buf != NULL) {
+ free(out_buf);
+ }
+ }
+ }
+ flb_parser_exit(config);
+ flb_config_exit(config);
+ flb_free(key_1);
+ flb_free(val_1);
+ flb_free(key_2);
+ flb_free(val_2);
+ flb_free(progname);
+ flb_kv_release(&prop);
+ }
+
+ /* clean up the file */
+ unlink(filename);
+
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/config_map_fuzzer.c b/fluent-bit/tests/internal/fuzzers/config_map_fuzzer.c
new file mode 100644
index 00000000..79697f65
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/config_map_fuzzer.c
@@ -0,0 +1,212 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+#include <fluent-bit/flb_info.h>
+#include <fluent-bit/flb_kv.h>
+#include <fluent-bit/flb_slist.h>
+#include <fluent-bit/flb_mem.h>
+#include <fluent-bit/flb_config.h>
+#include <fluent-bit/flb_config_map.h>
+
+#include "flb_fuzz_header.h"
+
+struct context {
+ /* Single values */
+ int num_int;
+ size_t size;
+ time_t time;
+ char boolean;
+ double num_double;
+ flb_sds_t string;
+ struct mk_list *list1;
+ struct mk_list *list2;
+
+ /* Multiple entries */
+ struct mk_list *mult_num_int;
+ struct mk_list *mult_boolean;
+ struct mk_list *mult_num_double;
+ struct mk_list *mult_string;
+ struct mk_list *mult_list1;
+ struct mk_list *mult_list2;
+};
+
+struct flb_config_map config_map[] = {
+ {
+ FLB_CONFIG_MAP_BOOL,
+ "boolean",
+ "true",
+ 0, FLB_TRUE, offsetof(struct context, boolean),
+ NULL
+ },
+ {
+ FLB_CONFIG_MAP_INT,
+ "num_int",
+ "123",
+ 0, FLB_TRUE, offsetof(struct context, num_int),
+ NULL
+ },
+ {
+ FLB_CONFIG_MAP_DOUBLE,
+ "num_double", "0.12345",
+ 0, FLB_TRUE, offsetof(struct context, num_double),
+ NULL
+ },
+ {
+ FLB_CONFIG_MAP_STR,
+ "string",
+ "test",
+ 0, FLB_TRUE, offsetof(struct context, string),
+ NULL
+ },
+
+ /* SIZE */
+ {
+ FLB_CONFIG_MAP_SIZE,
+ "test_size",
+ "2M",
+ 0, FLB_TRUE, offsetof(struct context, size),
+ NULL
+ },
+
+ /* TIME */
+ {
+ FLB_CONFIG_MAP_TIME,
+ "test_time",
+ "2H",
+ 0, FLB_TRUE, offsetof(struct context, time),
+ NULL
+ },
+
+ /* CSLIST */
+ {
+ FLB_CONFIG_MAP_CLIST,
+ "test_clist",
+ "a, b, c ,d,e , f, g,h,i,jk , lm , n o,pqr,, , ,stuv,xyz",
+ 0, FLB_TRUE, offsetof(struct context, list1),
+ NULL
+ },
+
+ /* SLIST */
+ {
+ FLB_CONFIG_MAP_SLIST_4,
+ "test_slist",
+ "a b c de f ghi jk l m n o pqr stuv xyz",
+ 0, FLB_TRUE, offsetof(struct context, list2),
+ NULL
+ },
+
+ /* EOF */
+ {0}
+};
+
+struct flb_config_map config_map_mult[] = {
+ {
+ FLB_CONFIG_MAP_BOOL,
+ "no_mult",
+ "true",
+ 0, FLB_TRUE, 1,
+ NULL
+ },
+ {
+ FLB_CONFIG_MAP_BOOL,
+ "mult_boolean",
+ NULL,
+ FLB_CONFIG_MAP_MULT, FLB_TRUE, offsetof(struct context, mult_boolean),
+ NULL
+ },
+ {
+ FLB_CONFIG_MAP_INT,
+ "mult_num_int",
+ "123",
+ FLB_CONFIG_MAP_MULT, FLB_TRUE, offsetof(struct context, mult_num_int),
+ NULL
+ },
+ {
+ FLB_CONFIG_MAP_DOUBLE,
+ "mult_num_double", "0.12345",
+ FLB_CONFIG_MAP_MULT, FLB_TRUE, offsetof(struct context, mult_num_double),
+ NULL
+ },
+ {
+ FLB_CONFIG_MAP_STR,
+ "mult_string",
+ "test",
+ FLB_CONFIG_MAP_MULT, FLB_TRUE, offsetof(struct context, mult_string),
+ NULL
+ },
+ {
+ FLB_CONFIG_MAP_CLIST,
+ "mult_clist",
+ "a, b, c ,d,e , f, g,h,i,jk , lm , n o,pqr,, , ,stuv,xyz",
+ FLB_CONFIG_MAP_MULT, FLB_TRUE, offsetof(struct context, mult_list1),
+ NULL
+ },
+ {
+ FLB_CONFIG_MAP_SLIST_4,
+ "mult_slist",
+ "a b c de f ghi jk l m n o pqr stuv xyz",
+ FLB_CONFIG_MAP_MULT, FLB_TRUE, offsetof(struct context, mult_list2),
+ NULL
+ },
+
+ /* EOF */
+ {0}
+};
+
+struct flb_config_map *configs[] = {config_map_mult, config_map};
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ /* Set flb_malloc_mod to be fuzzer-data dependent */
+ if (size < 4) {
+ return 0;
+ }
+ flb_malloc_p = 0;
+ flb_malloc_mod = *(int*)data;
+ data += 4;
+ size -= 4;
+
+ /* Avoid division by zero for modulo operations */
+ if (flb_malloc_mod == 0) {
+ flb_malloc_mod = 1;
+ }
+
+ if (size < 40) {
+ return 0;
+ }
+
+ struct mk_list *map = NULL;
+ struct flb_config *config = NULL;
+ struct context ctx;
+ bzero(&ctx, sizeof(struct context));
+ struct mk_list prop;
+ bzero(&prop, sizeof(struct mk_list));
+
+ char *fuzz_str1 = get_null_terminated(15, &data, &size);
+ char *fuzz_str2 = get_null_terminated(15, &data, &size);
+ char *fuzz_str3 = get_null_terminated(size, &data, &size);
+
+ for (int i = 0; i < 2; i++) {
+ config = flb_config_init();
+ if (config) {
+ memset(&ctx, '\0', sizeof(struct context));
+
+ flb_kv_init(&prop);
+ if (flb_kv_item_create(&prop, fuzz_str1, fuzz_str2) != NULL) {
+ /* Assign one of the config maps */
+ map = flb_config_map_create(config, configs[i]);
+ if (map) {
+ if (flb_config_map_set(&prop, map, &ctx) != -1) {
+ flb_config_map_properties_check(fuzz_str3, &prop, map);
+ }
+ flb_config_map_destroy(map);
+ }
+ }
+ flb_kv_release(&prop);
+ flb_config_exit(config);
+ }
+ }
+
+ flb_free(fuzz_str1);
+ flb_free(fuzz_str2);
+ flb_free(fuzz_str3);
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/config_random_fuzzer.c b/fluent-bit/tests/internal/fuzzers/config_random_fuzzer.c
new file mode 100644
index 00000000..ead06ad0
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/config_random_fuzzer.c
@@ -0,0 +1,57 @@
+/* Fluent Bit
+ * ==========
+ * Copyright (C) 2019-2021 The Fluent Bit Authors
+ * Copyright (C) 2015-2018 Treasure Data Inc.
+ *
+ * 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 <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fluent-bit/flb_parser.h>
+#include <fluent-bit/flb_slist.h>
+#include "flb_fuzz_header.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ /* Set fuzzer-malloc chance of failure */
+ flb_malloc_p = 0;
+ flb_malloc_mod = 25000;
+
+ /* Limit the size of the config files to 32KB. */
+ if (size > 32768) {
+ return 0;
+ }
+
+ /* Write the config file to a location we know OSS-Fuzz has */
+ char filename[256];
+ sprintf(filename, "/tmp/libfuzzer.%d", getpid());
+ FILE *fp = fopen(filename, "wb");
+ if (!fp) {
+ return 0;
+ }
+ fwrite(data, size, 1, fp);
+ fclose(fp);
+
+ /* Now parse a random config file */
+ struct flb_config *config = NULL;
+ config = flb_config_init();
+ flb_parser_conf_file(filename, config);
+ flb_parser_exit(config);
+ flb_config_exit(config);
+
+ /* Cleanup written config file */
+ unlink(filename);
+
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/config_yaml_fuzzer.c b/fluent-bit/tests/internal/fuzzers/config_yaml_fuzzer.c
new file mode 100644
index 00000000..99e17ba6
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/config_yaml_fuzzer.c
@@ -0,0 +1,65 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* Fluent Bit
+ * ==========
+ * Copyright (C) 2015-2023 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 <fluent-bit/flb_info.h>
+#include <fluent-bit/flb_mem.h>
+#include <fluent-bit/flb_kv.h>
+#include <fluent-bit/flb_config_format.h>
+
+#include <cfl/cfl.h>
+#include <cfl/cfl_list.h>
+
+#include "flb_fuzz_header.h"
+
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ /* Set fuzzer-malloc chance of failure */
+ flb_malloc_p = 0;
+ flb_malloc_mod = 25000;
+
+ /* Limit the size of the config files to 32KB. */
+ if (size > 32768) {
+ return 0;
+ }
+
+ /* Write the config file to a location we know OSS-Fuzz has */
+ char filename[256];
+ sprintf(filename, "/tmp/libfuzzer.%d.yaml", getpid());
+ FILE *fp = fopen(filename, "wb");
+ if (!fp) {
+ return 0;
+ }
+ fwrite(data, size, 1, fp);
+ fclose(fp);
+
+
+ struct flb_cf *cf;
+ struct flb_cf_section *s;
+
+ cf = flb_cf_yaml_create(NULL, filename, NULL, 0);
+ if (cf != NULL) {
+ flb_cf_destroy(cf);
+ }
+
+ /* clean up the file */
+ unlink(filename);
+
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/ctrace_fuzzer.c b/fluent-bit/tests/internal/fuzzers/ctrace_fuzzer.c
new file mode 100644
index 00000000..bcd2ca58
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/ctrace_fuzzer.c
@@ -0,0 +1,24 @@
+#include <stdint.h>
+#include <fluent-bit/flb_mem.h>
+#include <ctraces/ctraces.h>
+#include <ctraces/ctr_decode_msgpack.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size){
+ size_t off = 0;
+ struct ctrace *ctr = NULL;
+ size_t msgpack_text_size;
+ char *msgpack_text_buffer = NULL;
+
+ /* Set fuzzer-malloc chance of failure */
+ flb_malloc_p = 0;
+ flb_malloc_mod = 25000;
+
+ ctr_decode_msgpack_create(&ctr, data, size, &off);
+ if (ctr != NULL) {
+ ctr_encode_msgpack_create(ctr, &msgpack_text_buffer, &msgpack_text_size);
+ ctr_encode_msgpack_destroy(msgpack_text_buffer);
+
+ ctr_destroy(ctr);
+ }
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/engine_fuzzer.c b/fluent-bit/tests/internal/fuzzers/engine_fuzzer.c
new file mode 100644
index 00000000..498b86a8
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/engine_fuzzer.c
@@ -0,0 +1,171 @@
+#include <fluent-bit.h>
+#include <fluent-bit/flb_parser.h>
+#include <fluent-bit/flb_parser.h>
+#include <fluent-bit/flb_input_chunk.h>
+#include <fluent-bit/flb_metrics.h>
+#include "flb_fuzz_header.h"
+
+#include <stdio.h>
+#include <monkey/mk_core.h>
+
+struct flb_parser *parser;
+ flb_ctx_t *ctx;
+ int in_ffd;
+ int out_ffd;
+int filter_ffd;
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ if (size < 100) {
+ return 0;
+ }
+ /* Set fuzzer-malloc chance of failure */
+ flb_malloc_p = 0;
+ flb_malloc_mod = 25000;
+
+ uint8_t ud = data[0];
+ MOVE_INPUT(1);
+ #define NM_SIZE 50
+ char *null_terminated = get_null_terminated(NM_SIZE, &data, &size);
+
+ char *nm3 = get_null_terminated(10, &data, &size);
+ char *nm4 = get_null_terminated(10, &data, &size);
+ int random_i1 = *(int *)data;
+ MOVE_INPUT(4);
+ int random_i2 = *(int *)data;
+
+ #define FUNC_NUMS 10
+ switch (ud % FUNC_NUMS) {
+ case 0:
+ flb_output(ctx, null_terminated, nm3);
+ break;
+ case 1:
+ flb_filter(ctx, null_terminated, nm3);
+ break;
+ case 2:
+ flb_input(ctx, null_terminated, nm3);
+ break;
+ case 3:
+ flb_output_check(ctx->config);
+ break;
+ case 4: {
+ struct mk_list *head;
+ struct flb_input_instance *entry;
+ mk_list_foreach(head, &ctx->config->inputs) {
+ entry = mk_list_entry(head, struct flb_input_instance, _head);
+ flb_input_name_exists(nm3, ctx->config);
+ flb_input_get_property(nm3, entry);
+ flb_input_name(entry);
+ flb_input_collector_running(0, entry);
+ flb_input_collector_pause(random_i1, entry);
+ flb_input_collector_resume(random_i2, entry);
+ flb_input_net_default_listener(nm4, random_i1, entry);
+ flb_input_collector_start(random_i2, entry);
+ }
+ }
+ break;
+ case 5: {
+ struct mk_list *head;
+ struct flb_input_instance *entry;
+ mk_list_foreach(head, &ctx->config->inputs) {
+ entry = mk_list_entry(head, struct flb_input_instance, _head);
+ if (entry->storage != NULL) {
+ char bufbuf[100];
+ flb_input_chunk_append_raw(entry, FLB_INPUT_LOGS, 0, "A",
+ 1, "\0", 0);
+
+ struct flb_input_chunk *ic = NULL;
+ ic = flb_input_chunk_create(entry, FLB_INPUT_LOGS, nm3, 10);
+ if (ic != NULL) {
+ flb_input_chunk_get_size(ic);
+ flb_input_chunk_set_up_down(ic);
+ flb_input_chunk_down(ic);
+ flb_input_chunk_set_up(ic);
+ flb_input_chunk_get_name(ic);
+ char *tag_buf;
+ int tag_len;
+ flb_input_chunk_get_tag(ic, &tag_buf, &tag_len);
+ size_t flushed;
+ flb_input_chunk_flush(ic, &flushed);
+ }
+ }
+ }
+ }
+ break;
+ case 6:
+ flb_input_check(ctx->config);
+ flb_input_pause_all(ctx->config);
+ break;
+ case 7: {
+ struct mk_list *head;
+ struct flb_output_instance *entry;
+ mk_list_foreach(head, &ctx->config->outputs) {
+ entry = mk_list_entry(head, struct flb_output_instance, _head);
+ flb_output_net_default(nm4, random_i1, entry);
+ flb_output_name(entry);
+ }
+ }
+ break;
+ default:
+ flb_lib_push(ctx, in_ffd, null_terminated, NM_SIZE);
+ break;
+ }
+
+ flb_free(null_terminated);
+ flb_free(nm3);
+ flb_free(nm4);
+ return 0;
+}
+
+int callback_test(void* data, size_t size, void* cb_data)
+{
+ return 0;
+}
+
+struct flb_lib_out_cb cb;
+
+
+int LLVMFuzzerInitialize(int *argc, char ***argv) {
+ /* Set fuzzer-malloc chance of failure */
+ flb_malloc_p = 0;
+ flb_malloc_mod = 25000;
+
+ ctx = flb_create();
+ flb_service_set(ctx, "Flush", "0", "Grace",
+ "0", "Log_Level", "debug", NULL);
+
+ in_ffd = flb_input(ctx, (char *) "lib", NULL);
+ flb_input_set(ctx, in_ffd, (char *) "test", NULL);
+ flb_input_set(ctx, in_ffd, (char *) "BBBB", NULL);
+ flb_input_set(ctx, in_ffd, (char *) "AAAA", NULL);
+ flb_input_set(ctx, in_ffd, (char *) "AAAAA", NULL);
+ flb_input_set(ctx, in_ffd, (char *) "CC", NULL);
+ flb_input_set(ctx, in_ffd, (char *) "A", NULL);
+
+ parser = flb_parser_create("timestamp", "regex", "^(?<time>.*)$", FLB_TRUE,
+ "%s.%L", "time", NULL, MK_FALSE, 0, FLB_FALSE,
+ NULL, 0, NULL, ctx->config);
+ filter_ffd = flb_filter(ctx, (char *) "parser", NULL);
+ int ret;
+ ret = flb_filter_set(ctx, filter_ffd, "Match", "test",
+ "Key_Name", "@timestamp",
+ "Parser", "timestamp",
+ "Reserve_Data", "On",
+ NULL);
+
+ cb.cb = callback_test;
+ cb.data = NULL;
+ out_ffd = flb_output(ctx, (char *) "lib", &cb);
+ flb_output_set(ctx, out_ffd, "Match", "*",
+ "format", "json", NULL);
+
+ flb_output_set(ctx, out_ffd,"match", "test", NULL);
+ flb_output_set(ctx, out_ffd,"region", "us-west-2", NULL);
+ flb_output_set(ctx, out_ffd,"log_group_name", "fluent", NULL);
+ flb_output_set(ctx, out_ffd,"log_stream_prefix", "from-fluent-", NULL);
+ flb_output_set(ctx, out_ffd,"auto_create_group", "On", NULL);
+ flb_output_set(ctx, out_ffd,"net.keepalive", "Off", NULL);
+ flb_output_set(ctx, out_ffd,"Retry_Limit", "1", NULL);
+
+ /* start the engine */
+ flb_start(ctx);
+}
diff --git a/fluent-bit/tests/internal/fuzzers/filter_stdout_fuzzer.c b/fluent-bit/tests/internal/fuzzers/filter_stdout_fuzzer.c
new file mode 100644
index 00000000..ed9a3f49
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/filter_stdout_fuzzer.c
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* Fluent Bit
+ * ==========
+ * Copyright (C) 2015-2022 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 <stdint.h>
+#include <fluent-bit.h>
+#include "flb_fuzz_header.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ int ret;
+ flb_ctx_t *ctx;
+ int in_ffd;
+ int out_ffd;
+
+ /* Set fuzzer-malloc chance of failure */
+ flb_malloc_p = 0;
+ flb_malloc_mod = 25000;
+
+
+ ctx = flb_create();
+ flb_service_set(ctx, "Flush", "1", "Grace", "1", "Log_Level", "error", NULL);
+ in_ffd = flb_input(ctx, (char *) "lib", NULL);
+ if (in_ffd >= 0) {
+ flb_input_set(ctx, in_ffd, "tag", "test", NULL);
+
+ out_ffd = flb_output(ctx, (char *) "stdout", NULL);
+ if (out_ffd >= 0) {
+ flb_output_set(ctx, out_ffd, "match", "test", NULL);
+
+ ret = flb_start(ctx);
+ if (ret == 0) {
+ char *p = get_null_terminated(size, &data, &size);
+ for (int i = 0; i < strlen(p); i++) {
+ flb_lib_push(ctx, in_ffd, p+i, 1);
+ }
+ free(p);
+
+ sleep(1); /* waiting flush */
+ }
+ }
+ }
+ flb_stop(ctx);
+ flb_destroy(ctx);
+
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/flb_fuzz_header.h b/fluent-bit/tests/internal/fuzzers/flb_fuzz_header.h
new file mode 100644
index 00000000..cda08920
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/flb_fuzz_header.h
@@ -0,0 +1,42 @@
+/* Fluent Bit
+ * ==========
+ * Copyright (C) 2019-2021 The Fluent Bit Authors
+ * Copyright (C) 2015-2018 Treasure Data Inc.
+ *
+ * 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 <stdint.h>
+#include <string.h>
+
+#define GET_MOD_EQ(max, idx) (data[0] % max) == idx
+#define MOVE_INPUT(offset) data += offset; size -= offset;
+
+#define TIMEOUT_GUARD if (size > 32768) return 0;
+
+char *get_null_terminated(size_t size, const uint8_t **data,
+ size_t *total_data_size)
+{
+ char *tmp = flb_malloc(size+1);
+ if (tmp == NULL) {
+ tmp = malloc(size+1);
+ }
+ memcpy(tmp, *data, size);
+ tmp[size] = '\0';
+
+ /* Modify the fuzz variables */
+ *total_data_size -= size;
+ *data += size;
+
+ return tmp;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/flb_json_fuzzer.c b/fluent-bit/tests/internal/fuzzers/flb_json_fuzzer.c
new file mode 100644
index 00000000..916b1a51
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/flb_json_fuzzer.c
@@ -0,0 +1,82 @@
+/* Fluent Bit
+ * ==========
+ * Copyright (C) 2019-2021 The Fluent Bit Authors
+ * Copyright (C) 2015-2018 Treasure Data Inc.
+ *
+ * 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 <stdlib.h>
+#include <stdint.h>
+#include <fluent-bit/flb_pack.h>
+#include <fluent-bit/flb_str.h>
+#include "flb_fuzz_header.h"
+
+int LLVMFuzzerTestOneInput(unsigned char *data, size_t size)
+{
+ TIMEOUT_GUARD
+ /* Set fuzzer-malloc chance of failure */
+ flb_malloc_p = 0;
+ flb_malloc_mod = 25000;
+
+ if (size < 1) {
+ return 0;
+ }
+ unsigned char decider = *data;
+ data++;
+ size--;
+
+ /* json packer */
+ char *out_buf = NULL;
+ size_t out_size;
+ int root_type;
+ int ret = flb_pack_json((char*)data, size, &out_buf, &out_size, &root_type, NULL);
+
+ if (ret == 0) {
+ size_t off = 0;
+ msgpack_unpacked result;
+ msgpack_unpacked_init(&result);
+ int ret2 = msgpack_unpack_next(&result, out_buf, out_size, &off);
+ if (ret2 == MSGPACK_UNPACK_SUCCESS) {
+ msgpack_object root = result.data;
+ char *tmp = NULL;
+ tmp = flb_msgpack_to_json_str(0, &root);
+ if (tmp != NULL) {
+ flb_free(tmp);
+ }
+ }
+ msgpack_unpacked_destroy(&result);
+ flb_sds_t d;
+ d = flb_sds_create("date");
+ if (decider < 0x30) {
+ flb_sds_t ret_s = flb_pack_msgpack_to_json_format(out_buf, out_size,
+ FLB_PACK_JSON_FORMAT_LINES,
+ (int)decider, d);
+ free(out_buf);
+ if (ret_s != NULL) {
+ flb_sds_destroy(ret_s);
+ }
+ }
+ else {
+ flb_sds_t ret_s = flb_pack_msgpack_to_json_format(out_buf, out_size,
+ FLB_PACK_JSON_FORMAT_LINES,
+ FLB_PACK_JSON_DATE_EPOCH, NULL);
+ free(out_buf);
+ if (ret_s != NULL) {
+ flb_sds_destroy(ret_s);
+ }
+ }
+ flb_sds_destroy(d);
+ }
+
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/flb_mp_fuzzer.c b/fluent-bit/tests/internal/fuzzers/flb_mp_fuzzer.c
new file mode 100644
index 00000000..b33c9040
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/flb_mp_fuzzer.c
@@ -0,0 +1,55 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* Fluent Bit
+ * ==========
+ * Copyright (C) 2015-2023 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 <stdlib.h>
+#include <stdint.h>
+#include <fluent-bit/flb_mem.h>
+#include <fluent-bit/flb_mp.h>
+
+#include "flb_fuzz_header.h"
+
+int LLVMFuzzerTestOneInput(unsigned char *data, size_t size)
+{
+ /* Set flb_malloc_mod to be fuzzer-data dependent */
+ if (size < 5) {
+ return 0;
+ }
+ flb_malloc_p = 0;
+ flb_malloc_mod = *(int*)data;
+ data += 4;
+ size -= 4;
+
+ /* Avoid division by zero for modulo operations */
+ if (flb_malloc_mod == 0) {
+ flb_malloc_mod = 1;
+ }
+
+ unsigned char decider = *data;
+ data++;
+ size--;
+
+ int out_records;
+ size_t processed_bytes;
+ if (decider % 2 == 0) {
+ flb_mp_validate_log_chunk(data, size, &out_records, &processed_bytes);
+ }
+ else if (decider % 2 == 1) {
+ flb_mp_validate_metric_chunk(data, size, &out_records, &processed_bytes);
+ }
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/fstore_fuzzer.c b/fluent-bit/tests/internal/fuzzers/fstore_fuzzer.c
new file mode 100644
index 00000000..e2a95106
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/fstore_fuzzer.c
@@ -0,0 +1,86 @@
+/* Fluent Bit
+ * ==========
+ * Copyright (C) 2019-2022 The Fluent Bit Authors
+ * Copyright (C) 2015-2018 Treasure Data Inc.
+ *
+ * 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 <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include <fluent-bit/flb_info.h>
+#include <fluent-bit/flb_fstore.h>
+#include <fluent-bit/flb_mem.h>
+#include <fluent-bit/flb_compat.h>
+
+#include <chunkio/chunkio.h>
+#include <chunkio/cio_utils.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+
+#define FSF_STORE_PATH "/tmp/flb-fstore"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ int ret;
+ void *out_buf;
+ size_t out_size;
+ struct stat st_data;
+ struct flb_fstore *fs;
+ struct flb_fstore_stream *st;
+ struct flb_fstore_file *fsf;
+
+ /* Set flb_malloc_mod to be fuzzer-data dependent */
+ if (size < 4) {
+ return 0;
+ }
+ flb_malloc_p = 0;
+ flb_malloc_mod = *(int*)data;
+ data += 4;
+ size -= 4;
+
+ /* Avoid division by zero for modulo operations */
+ if (flb_malloc_mod == 0) {
+ flb_malloc_mod = 1;
+ }
+
+ cio_utils_recursive_delete(FSF_STORE_PATH);
+ fs = flb_fstore_create(FSF_STORE_PATH, FLB_FSTORE_FS);
+ if (fs == NULL) {
+ return 0;
+ }
+ st = flb_fstore_stream_create(fs, "abc");
+ if (st != NULL) {
+ fsf = flb_fstore_file_create(fs, st, "example.txt", size);
+
+ if (fsf != NULL) {
+ ret = flb_fstore_file_append(fsf, data, size);
+ if (ret == 0) {
+ ret = flb_fstore_file_content_copy(fs, fsf, &out_buf, &out_size);
+ if (ret == 0) {
+ assert(memcmp(out_buf, data, size) == 0);
+ }
+ flb_free(out_buf);
+ }
+ }
+ }
+
+ flb_fstore_dump(fs);
+ flb_fstore_destroy(fs);
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/http_fuzzer.c b/fluent-bit/tests/internal/fuzzers/http_fuzzer.c
new file mode 100644
index 00000000..28f0c8d2
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/http_fuzzer.c
@@ -0,0 +1,116 @@
+#include <stdlib.h>
+#include <fluent-bit/flb_time.h>
+#include <fluent-bit/flb_parser.h>
+#include <fluent-bit/flb_info.h>
+#include <fluent-bit/flb_mem.h>
+#include <fluent-bit/flb_error.h>
+#include <fluent-bit/flb_socket.h>
+#include <fluent-bit/flb_stream.h>
+#include <fluent-bit/flb_connection.h>
+#include <fluent-bit/flb_http_client.h>
+
+#include "flb_fuzz_header.h"
+
+extern int fuzz_process_data(struct flb_http_client *c);
+extern int fuzz_check_connection(struct flb_http_client *c);
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ /* Set fuzzer-malloc chance of failure */
+ flb_malloc_p = 0;
+ flb_malloc_mod = 25000;
+
+ struct flb_upstream *u;
+ struct flb_connection *u_conn = NULL;
+ struct flb_http_client *c;
+ struct flb_config *config;
+ char *uri = NULL;
+
+ if (size < 160) {
+ return 0;
+ }
+
+ config = flb_config_init();
+ if (config == NULL) {
+ return 0;
+ }
+
+ u = flb_upstream_create(config, "127.0.0.1", 8001, 0, NULL);
+
+ u_conn = flb_connection_create(-1,
+ FLB_TRANSPORT_TCP,
+ (void *) u,
+ NULL,
+ NULL);
+
+ if (u_conn == NULL) {
+ return 0;
+ }
+
+ char *proxy = NULL;
+ if (GET_MOD_EQ(2,1)) {
+ proxy = get_null_terminated(50, &data, &size);
+ }
+
+ uri = get_null_terminated(20, &data, &size);
+
+ int method = (int)data[0];
+ c = flb_http_client(u_conn, method, uri, NULL, 0,
+ "127.0.0.1", 8001, proxy, 0);
+ if (c != NULL) {
+ char *null_terminated = get_null_terminated(30, &data, &size);
+
+ /* Perform a set of operations on the http_client */
+ flb_http_basic_auth(c, null_terminated, null_terminated);
+ flb_http_set_content_encoding_gzip(c);
+ flb_http_set_keepalive(c);
+ flb_http_strip_port_from_host(c);
+ flb_http_allow_duplicated_headers(c, 0);
+
+ flb_http_buffer_size(c, (*(size_t *)data) & 0xfff);
+ MOVE_INPUT(4)
+ flb_http_add_header(c, "User-Agent", 10, "Fluent-Bit", 10);
+ flb_http_add_header(c, (char*)data, size, "Fluent-Bit", 10);
+ flb_http_buffer_size(c, (int)data[0]);
+ MOVE_INPUT(1)
+ flb_http_buffer_available(c);
+
+ size_t b_sent;
+ flb_http_do(c, &b_sent);
+
+ size_t out_size = 0;
+ flb_http_buffer_increase(c, (*(size_t *)data) & 0xfff, &out_size);
+ MOVE_INPUT(4)
+
+ /* Now we need to simulate the reading of data */
+ c->resp.status = 200;
+
+ if (c->resp.data != NULL) {
+ flb_free(c->resp.data);
+ }
+
+ char *new_nulltm = get_null_terminated(30, &data, &size);
+ c->resp.data_len = 30;
+ c->resp.data = new_nulltm;
+ fuzz_process_data(c);
+ fuzz_check_connection(c);
+
+ flb_http_client_destroy(c);
+ flb_free(null_terminated);
+ }
+
+ /* Now try the http_client_proxy_connect function. */
+ flb_http_client_proxy_connect(u_conn);
+
+ flb_connection_destroy(u_conn);
+ flb_upstream_destroy(u);
+ flb_config_exit(config);
+ if (uri != NULL) {
+ flb_free(uri);
+ }
+ if (proxy != NULL) {
+ flb_free(proxy);
+ }
+
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/input_fuzzer.c b/fluent-bit/tests/internal/fuzzers/input_fuzzer.c
new file mode 100644
index 00000000..57458d36
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/input_fuzzer.c
@@ -0,0 +1,164 @@
+#include <fluent-bit.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <sys/stat.h>
+#include <fluent-bit/flb_input_chunk.h>
+#include <fluent-bit/flb_storage.h>
+#include <fluent-bit/flb_router.h>
+#include <fluent-bit/flb_time.h>
+
+#include "chunkio/chunkio.h"
+#include "flb_fuzz_header.h"
+
+
+const char *input_chunk_property_keywords[] = {
+ "log_suppress_interval",
+ "routable",
+ "alias",
+ "mem_buf_limit",
+ "listen",
+ "log_level",
+ "host",
+ "port",
+ "ipv6",
+ "net.",
+ "tls",
+ "tls.verify",
+ "tls.debug",
+ "tls.ca_path",
+ "tls.key_file",
+ "tls.vhost",
+ "tls.ca_file",
+ "tls.crt_file",
+ "tls.key_passwd",
+ "threaded",
+ "storage.type",
+};
+
+int LLVMFuzzerTestOneInput(const uint8_t *data3, size_t size3)
+{
+ int i;
+ int ret;
+ int in_ffd;
+ int out_ffd;
+
+ flb_ctx_t *ctx;
+ size_t total_bytes;
+ struct flb_input_instance *i_ins;
+ struct mk_list *tmp;
+ struct mk_list *head;
+ struct flb_input_chunk *ic;
+ struct flb_task *task;
+
+ if (size3 < 60) {
+ return 0;
+ }
+ /* Set fuzzer-malloc chance of failure */
+ flb_malloc_p = 0;
+ flb_malloc_mod = 25000;
+ char *input_buffer1 = get_null_terminated(30, &data3, &size3);
+ if (input_buffer1 == NULL) {
+ return 0;
+ }
+ size_t input_buffer1_len = strlen(input_buffer1);
+
+ char *input_buffer2 = get_null_terminated(10, &data3, &size3);
+ if (input_buffer2 == NULL) {
+ return 0;
+ }
+ size_t input_buffer_len2 = strlen(input_buffer2);
+
+ char *input_buffer3 = get_null_terminated(10, &data3, &size3);
+ if (input_buffer3 == NULL) {
+ return 0;
+ }
+ size_t input_buffer_len3 = strlen(input_buffer3);
+ /* Create context, flush every second (some checks omitted here) */
+ ctx = flb_create();
+
+ /* create chunks in /tmp folder */
+ ret = flb_service_set(ctx,
+ "flush", "2", "grace", "1",
+ "storage.path", "/tmp/input-chunk-test/",
+ "Log_Level", "error",
+ NULL);
+ if (ret != 0) {
+ flb_free(input_buffer1);
+ flb_free(input_buffer2);
+ flb_free(input_buffer3);
+ return 0;
+ }
+
+ /* Lib input mode */
+ in_ffd = flb_input(ctx, (char *) "lib", NULL);
+ ret = flb_input_set(ctx, in_ffd,
+ "tag", "test",
+ "storage.type", "filesystem",
+ NULL);
+ if (ret != 0) {
+ flb_free(input_buffer1);
+ flb_free(input_buffer2);
+ flb_free(input_buffer3);
+ return 0;
+ }
+
+ /* an invalid output destination */
+ out_ffd = flb_output(ctx, (char *) "http", NULL);
+ flb_output_set(ctx, out_ffd,
+ "match", "test",
+ "Host", "127.0.0.1",
+ "Port", "1",
+ "storage.total_limit_size", "1K",
+ NULL);
+
+ /* Start */
+ ret = flb_start(ctx);
+ if (ret != 0) {
+ flb_free(input_buffer1);
+ flb_free(input_buffer2);
+ flb_free(input_buffer3);
+ return 0;
+ }
+
+ i_ins = mk_list_entry_first(&ctx->config->inputs,
+ struct flb_input_instance,
+ _head);
+
+ /* main fuzzing logic */
+ flb_input_set_property(i_ins, input_buffer2, input_buffer3);
+ for (int i = 0; i < sizeof(input_chunk_property_keywords)/sizeof(char*); i++) {
+ flb_input_set_property(i_ins,
+ input_chunk_property_keywords[i],
+ input_buffer3);
+ }
+
+ /* Ingest fuzz data sample */
+ for (i = 0; i < 2; ++i) {
+ flb_lib_push(ctx, in_ffd, (char *) input_buffer1, input_buffer1_len);
+ sleep(1);
+ total_bytes = flb_input_chunk_total_size(i_ins);
+ ret = total_bytes > 1000 ? -1 : 0;
+ }
+
+ /* FORCE clean up test tasks */
+ mk_list_foreach_safe(head, tmp, &i_ins->tasks) {
+ task = mk_list_entry(head, struct flb_task, _head);
+ flb_info("[task] cleanup test task");
+ flb_task_destroy(task, FLB_TRUE);
+ }
+
+ /* clean up test chunks */
+ mk_list_foreach_safe(head, tmp, &i_ins->chunks) {
+ ic = mk_list_entry(head, struct flb_input_chunk, _head);
+ flb_input_chunk_destroy(ic, FLB_TRUE);
+ }
+ flb_free(input_buffer1);
+ flb_free(input_buffer2);
+ flb_free(input_buffer3);
+
+ flb_time_msleep(200);
+ flb_stop(ctx);
+ flb_destroy(ctx);
+}
diff --git a/fluent-bit/tests/internal/fuzzers/local_test.c b/fluent-bit/tests/internal/fuzzers/local_test.c
new file mode 100644
index 00000000..309f66b7
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/local_test.c
@@ -0,0 +1,85 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* Fluent Bit
+ * ==========
+ * Copyright (C) 2019-2020 The Fluent Bit Authors
+ * Copyright (C) 2015-2018 Treasure Data Inc.
+ *
+ * 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 <fluent-bit/flb_info.h>
+#include <fluent-bit/flb_log.h>
+#include <fluent-bit/flb_mem.h>
+#include <monkey/mk_core.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+/* declare external function test */
+int LLVMFuzzerTestOneInput(unsigned char *data, size_t size);
+
+int main(int argc, char **argv)
+{
+ int i;
+ int ret;
+ FILE *fp;
+ char *buffer;
+ long bytes;
+ struct stat st;
+
+ if (argc < 2) {
+ flb_error("usage: %s TESTCASE_FILE", argv[0]);
+ exit(EXIT_FAILURE);
+ }
+
+ /* Validate the file */
+ ret = stat(argv[1], &st);
+ if (ret == -1) {
+ flb_errno();
+ flb_error("cannot stat(2) testcase file '%s'", argv[1]);
+ exit(EXIT_FAILURE);
+ }
+
+ if (!(fp = fopen(argv[1], "rb"))) {
+ flb_errno();
+ flb_error("cannot fopen(2) testcase file '%s'", argv[1]);
+ return -1;
+ }
+
+ buffer = flb_malloc(st.st_size);
+ if (!buffer) {
+ flb_errno();
+ return -1;
+ }
+
+ bytes = fread(buffer, st.st_size, 1, fp);
+ if (bytes < 1) {
+ fclose(fp);
+ flb_free(buffer);
+ return -1;
+ }
+ fclose(fp);
+
+ /* Invoke the fuzzer entry-point function */
+ for (i = 0; i < 100; i++) {
+ ret = LLVMFuzzerTestOneInput((unsigned char *) buffer, st.st_size);
+ }
+ flb_free(buffer);
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/msgpack_parse_fuzzer.c b/fluent-bit/tests/internal/fuzzers/msgpack_parse_fuzzer.c
new file mode 100644
index 00000000..cbf2ecf1
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/msgpack_parse_fuzzer.c
@@ -0,0 +1,30 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <msgpack.h>
+#include <fluent-bit/flb_pack.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size){
+ /* Set flb_malloc_mod to be fuzzer-data dependent */
+ if (size < 4) {
+ return 0;
+ }
+ flb_malloc_p = 0;
+ flb_malloc_mod = *(int*)data;
+ data += 4;
+ size -= 4;
+
+ /* Avoid division by zero for modulo operations */
+ if (flb_malloc_mod == 0) {
+ flb_malloc_mod = 1;
+ }
+
+ if (size != 512)
+ return 0;
+
+ /* target the conversion of raw msgpack to json */
+ flb_sds_t record;
+ record = flb_msgpack_raw_to_json_sds(data, size);
+ flb_sds_destroy(record);
+
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/msgpack_to_gelf_fuzzer.c b/fluent-bit/tests/internal/fuzzers/msgpack_to_gelf_fuzzer.c
new file mode 100644
index 00000000..cf57437b
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/msgpack_to_gelf_fuzzer.c
@@ -0,0 +1,25 @@
+#include <stdint.h>
+#include <string.h>
+#include <msgpack.h>
+#include <fluent-bit/flb_pack.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size){
+ /* Set fuzzer-malloc chance of failure */
+ flb_malloc_mod = 25000;
+ flb_malloc_p = 0;
+ if (size != 512)
+ return 0;
+
+ /* Target the conversion of raw msgpack to gelf */
+ flb_sds_t record;
+ struct flb_time tm = {0};
+ struct flb_gelf_fields fields = {0};
+ fields.short_message_key = flb_sds_create("AAAAAAAAAA");
+ record = flb_msgpack_raw_to_gelf((char*)data, size, &tm, &fields);
+
+ /* cleanup */
+ flb_sds_destroy(record);
+ flb_sds_destroy(fields.short_message_key);
+
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/multiline_fuzzer.c b/fluent-bit/tests/internal/fuzzers/multiline_fuzzer.c
new file mode 100644
index 00000000..bc03e246
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/multiline_fuzzer.c
@@ -0,0 +1,180 @@
+/* Fluent Bit
+ * ==========
+ * Copyright (C) 2019-2021 The Fluent Bit Authors
+ * Copyright (C) 2015-2018 Treasure Data Inc.
+ *
+ * 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 <stdint.h>
+#include <stdlib.h>
+
+#include <fluent-bit/flb_info.h>
+#include <fluent-bit/flb_mem.h>
+#include <fluent-bit/flb_pack.h>
+#include <fluent-bit/flb_parser.h>
+#include <fluent-bit/multiline/flb_ml.h>
+#include <fluent-bit/multiline/flb_ml_parser.h>
+#include <fluent-bit/multiline/flb_ml_rule.h>
+
+#include "flb_fuzz_header.h"
+
+static int flush_callback(struct flb_ml_parser *parser,
+ struct flb_ml_stream *mst, void *data, char *buf_data,
+ size_t buf_size) {
+ return 0;
+}
+
+struct record_check {
+ char *buf;
+};
+
+struct expected_result {
+ int current_record;
+ char *key;
+ struct record_check *out_records;
+};
+
+char *random_strings[4];
+
+void test_multiline_parser(msgpack_object *root2, int rand_val) {
+ struct expected_result res = {0};
+ struct flb_config *config = NULL;
+
+ config = flb_config_init();
+
+ struct flb_ml *ml = NULL;
+ ml = flb_ml_create(config, "fuzz-test");
+
+ if (ml != NULL) {
+ uint64_t stream_ids[5];
+
+ flb_ml_parser_instance_create(ml, "docker");
+ flb_ml_parser_instance_create(ml, "python");
+ flb_ml_parser_instance_create(ml, "go");
+ flb_ml_parser_instance_create(ml, "cri");
+ struct flb_ml_parser_ins *mlp_i =
+ flb_ml_parser_instance_create(ml, "java");
+ flb_ml_parser_instance_set(mlp_i, "key_content", "log");
+
+ if (rand_val & 0x01) {
+ flb_ml_stream_create(ml, "java", -1, flush_callback, (void *)&res,
+ &(stream_ids[0]));
+ }
+ if (rand_val >> 1 & 0x01) {
+ flb_ml_stream_create(ml, "python", -1, flush_callback, (void *)&res,
+ &(stream_ids[1]));
+ }
+ if (rand_val >> 2 & 0x01) {
+ flb_ml_stream_create(ml, "go", -1, flush_callback, (void *)&res,
+ &(stream_ids[2]));
+ }
+ if (rand_val >> 3 & 0x01) {
+ flb_ml_stream_create(ml, "docker", -1, flush_callback, (void *)&res,
+ &(stream_ids[3]));
+ }
+ if (rand_val >> 4 & 0x01) {
+ flb_ml_stream_create(ml, "cri", -1, flush_callback, (void *)&res,
+ &(stream_ids[4]));
+ }
+
+ /* Target with msgpack object */
+ if (root2 != NULL) {
+ struct flb_time tm;
+ flb_time_get(&tm);
+ for (int i = 0; i < 4; i++) {
+ flb_ml_append_object(ml, stream_ids[i], &tm, NULL, root2);
+ }
+ }
+
+ /* Target with raw text */
+ struct flb_time tm2;
+ flb_time_get(&tm2);
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 5; j++) {
+ if (random_strings[i] != NULL && stream_ids[j] != NULL) {
+ /* stream_ids index by j, random_strings index by i */
+ flb_ml_append_text(ml, stream_ids[j], &tm2,
+ random_strings[i], strlen(random_strings[i]));
+ flb_ml_append_text(ml, stream_ids[j], &tm2,
+ random_strings[i], strlen(random_strings[i]));
+ flb_ml_append_text(ml, stream_ids[j], &tm2,
+ random_strings[i], strlen(random_strings[i]));
+ flb_ml_append_text(ml, stream_ids[j], &tm2,
+ random_strings[i],strlen(random_strings[i]));
+ flb_ml_append_text(ml, stream_ids[j], &tm2,
+ random_strings[i], strlen(random_strings[i]));
+ }
+ }
+ }
+ }
+
+ flb_ml_flush_pending_now(ml);
+
+ if (ml) {
+ flb_ml_destroy(ml);
+ }
+
+ flb_config_exit(config);
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ TIMEOUT_GUARD
+ /* Set fuzzer-malloc chance of failure */
+ flb_malloc_mod = 25000;
+ flb_malloc_p = 0;
+ /* Ensure there's enough data */
+ if (size < 250) {
+ return 0;
+ }
+
+ int rand_val = *(int *)data;
+ data += 4;
+ size -= 4;
+ for (int i = 0; i < 4; i++) {
+ random_strings[i] = NULL;
+ }
+
+ random_strings[0] = get_null_terminated(40, &data, &size);
+ random_strings[1] = get_null_terminated(40, &data, &size);
+ random_strings[2] = get_null_terminated(40, &data, &size);
+ random_strings[3] = get_null_terminated(40, &data, &size);
+
+ char *out_buf = NULL;
+ size_t out_size;
+ int root_type;
+ int ret =
+ flb_pack_json((char *)data, size, &out_buf, &out_size, &root_type, NULL);
+ if (ret == 0) {
+ size_t off = 0;
+ msgpack_unpacked result;
+ msgpack_unpacked_init(&result);
+ int ret2 = msgpack_unpack_next(&result, out_buf, out_size, &off);
+ if (ret2 == MSGPACK_UNPACK_SUCCESS) {
+ msgpack_object root = result.data;
+
+ /* Pass fuzz data into the multiline parser code */
+ test_multiline_parser(&root, rand_val);
+ }
+ msgpack_unpacked_destroy(&result);
+ free(out_buf);
+ } else {
+ test_multiline_parser(NULL, rand_val);
+ }
+
+ for (int i = 0; i < 4; i++) {
+ if (random_strings[i] != NULL) {
+ free(random_strings[i]);
+ }
+ }
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/pack_json_state_fuzzer.c b/fluent-bit/tests/internal/fuzzers/pack_json_state_fuzzer.c
new file mode 100644
index 00000000..4549557a
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/pack_json_state_fuzzer.c
@@ -0,0 +1,25 @@
+#include <stdint.h>
+#include <stdlib.h>
+#include <fluent-bit/flb_pack.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size){
+ int out_size= 0;
+ char *out_buf = NULL;
+ struct flb_pack_state state;
+ /* Set fuzzer-malloc chance of failure */
+ flb_malloc_mod = 25000;
+ flb_malloc_p = 0;
+
+ /* Exit early to avoid timeouts due to excessive size */
+ if (size > 4096)
+ return 0;
+
+ /* Target json packer */
+ flb_pack_state_init(&state);
+ flb_pack_json_state(data, size, &out_buf, &out_size, &state);
+ flb_pack_state_reset(&state);
+ if (out_buf != NULL)
+ flb_free(out_buf);
+
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/parse_json_fuzzer.c b/fluent-bit/tests/internal/fuzzers/parse_json_fuzzer.c
new file mode 100644
index 00000000..dab8880d
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/parse_json_fuzzer.c
@@ -0,0 +1,69 @@
+/* Fluent Bit
+ * ==========
+ * Copyright (C) 2019-2021 The Fluent Bit Authors
+ * Copyright (C) 2015-2018 Treasure Data Inc.
+ *
+ * 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 <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fluent-bit/flb_time.h>
+#include <fluent-bit/flb_parser.h>
+#include "flb_fuzz_header.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size){
+ TIMEOUT_GUARD
+ void *out_buf = NULL;
+ size_t out_size = 0;
+ struct flb_time out_time;
+ struct flb_config *fuzz_config;
+ struct flb_parser *fuzz_parser;
+
+ /* Set flb_malloc_mod to be fuzzer-data dependent */
+ if (size < 4) {
+ return 0;
+ }
+ flb_malloc_p = 0;
+ flb_malloc_mod = *(int*)data;
+ data += 4;
+ size -= 4;
+
+ /* Avoid division by zero for modulo operations */
+ if (flb_malloc_mod == 0) {
+ flb_malloc_mod = 1;
+ }
+
+ /* json parser */
+ fuzz_config = flb_config_init();
+ if (fuzz_config == NULL) {
+ return 0;
+ }
+
+ fuzz_parser = flb_parser_create("fuzzer", "json", NULL, FLB_TRUE, NULL,
+ NULL, NULL, MK_FALSE, MK_TRUE, FLB_FALSE,
+ NULL, 0, NULL, fuzz_config);
+ if (fuzz_parser) {
+ flb_parser_do(fuzz_parser, (char*)data, size,
+ &out_buf, &out_size, &out_time);
+
+ if (out_buf != NULL) {
+ free(out_buf);
+ }
+
+ flb_parser_destroy(fuzz_parser);
+ }
+ flb_config_exit(fuzz_config);
+
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/parse_logfmt_fuzzer.c b/fluent-bit/tests/internal/fuzzers/parse_logfmt_fuzzer.c
new file mode 100644
index 00000000..c65a2adb
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/parse_logfmt_fuzzer.c
@@ -0,0 +1,50 @@
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fluent-bit/flb_time.h>
+#include <fluent-bit/flb_parser.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size){
+ void *out_buf = NULL;
+ size_t out_size = 0;
+ struct flb_time out_time;
+ struct flb_config *fuzz_config;
+ struct flb_parser *fuzz_parser;
+
+ /* Set flb_malloc_mod to be fuzzer-data dependent */
+ if (size < 4) {
+ return 0;
+ }
+ flb_malloc_p = 0;
+ flb_malloc_mod = *(int*)data;
+ data += 4;
+ size -= 4;
+
+ /* Avoid division by zero for modulo operations */
+ if (flb_malloc_mod == 0) {
+ flb_malloc_mod = 1;
+ }
+
+ /* logfmt parser */
+ fuzz_config = flb_config_init();
+ if (fuzz_config == NULL) {
+ return 0;
+ }
+ fuzz_parser = flb_parser_create("fuzzer", "logfmt", NULL, FLB_TRUE,
+ NULL, NULL, NULL, MK_FALSE,
+ MK_TRUE, FLB_FALSE, NULL, 0, NULL,
+ fuzz_config);
+ if (fuzz_parser) {
+ flb_parser_do(fuzz_parser, (char*)data, size,
+ &out_buf, &out_size, &out_time);
+
+ if (out_buf != NULL) {
+ free(out_buf);
+ }
+ flb_parser_destroy(fuzz_parser);
+ }
+
+ flb_config_exit(fuzz_config);
+
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/parse_ltsv_fuzzer.c b/fluent-bit/tests/internal/fuzzers/parse_ltsv_fuzzer.c
new file mode 100644
index 00000000..cb8bf95a
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/parse_ltsv_fuzzer.c
@@ -0,0 +1,35 @@
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fluent-bit/flb_time.h>
+#include <fluent-bit/flb_parser.h>
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size){
+ void *out_buf = NULL;
+ size_t out_size = 0;
+ struct flb_time out_time;
+ struct flb_config *fuzz_config;
+ struct flb_parser *fuzz_parser;
+
+ /* Set fuzzer-malloc chance of failure */
+ flb_malloc_mod = 25000;
+ flb_malloc_p = 0;
+
+ /* ltsvc parser */
+ fuzz_config = flb_config_init();
+ fuzz_parser = flb_parser_create("fuzzer", "ltsv", NULL, FLB_TRUE,
+ NULL, NULL, NULL, MK_FALSE,
+ MK_TRUE, FLB_FALSE, NULL, 0, NULL,
+ fuzz_config);
+ flb_parser_do(fuzz_parser, (char*)data, size,
+ &out_buf, &out_size, &out_time);
+
+ if (out_buf != NULL) {
+ free(out_buf);
+ }
+
+ flb_parser_destroy(fuzz_parser);
+ flb_config_exit(fuzz_config);
+
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/parser_fuzzer.c b/fluent-bit/tests/internal/fuzzers/parser_fuzzer.c
new file mode 100644
index 00000000..a0355551
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/parser_fuzzer.c
@@ -0,0 +1,203 @@
+/* Fluent Bit
+ * ==========
+ * Copyright (C) 2019-2021 The Fluent Bit Authors
+ * Copyright (C) 2015-2018 Treasure Data Inc.
+ *
+ * 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 <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fluent-bit/flb_utils.h>
+#include <fluent-bit/flb_time.h>
+#include <fluent-bit/flb_parser.h>
+#include <fluent-bit/flb_parser_decoder.h>
+
+#include "flb_fuzz_header.h"
+
+#define TYPES_LEN 5
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ TIMEOUT_GUARD
+
+ char *format = NULL;
+ char *time_fmt = NULL;
+ char *time_key = NULL;
+ char *time_offset = NULL;
+ char *pregex = NULL;
+ struct flb_parser_types *types = NULL;
+ struct flb_config *fuzz_config = NULL;
+ struct flb_parser *fuzz_parser = NULL;
+ int time_keep = 0;
+ int types_len = 0;
+
+ /* Set fuzzer-malloc chance of failure */
+ flb_malloc_mod = 25000;
+ flb_malloc_p = 0;
+
+ if (size < 100) {
+ return 0;
+ }
+
+ /* json parser */
+ fuzz_config = flb_config_init();
+
+ /* format + pregex */
+ if (GET_MOD_EQ(4,0)) {
+ format = "json";
+ }
+ else if (GET_MOD_EQ(4,1)) {
+ format = "regex";
+#ifdef PREG_FUZZ
+ pregex = malloc(30);
+ pregex[29] = '\0';
+ memcpy(pregex, data, 29);
+ data += 29;
+ size -= 29;
+#else
+ pregex = "^(?<INT>[^ ]+) (?<FLOAT>[^ ]+) (?<BOOL>[^ ]+) (?<STRING>.+)$";
+#endif
+ }
+ else if (GET_MOD_EQ(4,2)) {
+ format = "ltsv";
+ }
+ else {
+ format = "logfmt";
+ }
+ MOVE_INPUT(1);
+
+ /* time_fmt */
+ if (GET_MOD_EQ(2,1)) {
+ time_fmt = get_null_terminated(15, &data, &size);
+ }
+ MOVE_INPUT(1);
+
+ /* time_key */
+ if (GET_MOD_EQ(2,1)) {
+ time_key = get_null_terminated(15, &data, &size);
+ }
+ MOVE_INPUT(1);
+
+ /* time_offset */
+ if (GET_MOD_EQ(2,1)) {
+ time_offset = get_null_terminated(15, &data, &size);
+ }
+ MOVE_INPUT(1);
+
+ /* time_keep */
+ time_keep = (GET_MOD_EQ(2,1)) ? MK_TRUE : MK_FALSE;
+ MOVE_INPUT(1);
+
+ /* types_str */
+ if (GET_MOD_EQ(2,1)) {
+ types = flb_malloc(sizeof(struct flb_parser_types) * TYPES_LEN);
+ char *parser_type_keys[5] = {"AAA", "BBB", "CCC", "DDD", "EEE" };
+ int parser_types[5] = {FLB_PARSER_TYPE_INT, FLB_PARSER_TYPE_FLOAT,
+ FLB_PARSER_TYPE_BOOL, FLB_PARSER_TYPE_STRING,
+ FLB_PARSER_TYPE_HEX};
+ for (int i = 0; i < TYPES_LEN; i++) {
+ types[i].key = strdup(parser_type_keys[i]);
+ types[i].key_len = strlen(parser_type_keys[i]);
+ types[i].type = parser_types[i];
+ }
+ types_len = TYPES_LEN;
+ }
+ MOVE_INPUT(1);
+
+ /* decoders */
+ struct mk_list *list = NULL;
+ if (GET_MOD_EQ(2,1)) {
+ MOVE_INPUT(1);
+ list = flb_malloc(sizeof(struct mk_list));
+ mk_list_init(list);
+
+ struct flb_parser_dec *dec = malloc(sizeof(struct flb_parser_dec));
+ dec->key = flb_sds_create_len("AAA", 3);
+ dec->buffer = flb_sds_create_size(FLB_PARSER_DEC_BUF_SIZE);
+ dec->add_extra_keys = FLB_TRUE;
+ mk_list_init(&dec->rules);
+ mk_list_add(&dec->_head, list);
+
+ struct flb_parser_dec_rule *dec_rule = malloc(sizeof(struct flb_parser_dec_rule));
+ dec_rule->type = (int)(data[0] % 0x02);
+ MOVE_INPUT(1);
+ dec_rule->backend = (int)(data[0] % 0x04);
+ MOVE_INPUT(1);
+ dec_rule->action = (int)data[0] % 0x03;
+ mk_list_add(&dec_rule->_head, &dec->rules);
+
+ if (GET_MOD_EQ(2,1)) {
+ struct flb_parser_dec_rule *dec_rule2 = malloc(sizeof(struct flb_parser_dec_rule));
+ dec_rule2->type = (int)(data[0] % 0x02);
+ MOVE_INPUT(1);
+ dec_rule2->backend = (int)(data[0] % 0x04);
+ MOVE_INPUT(1);
+ dec_rule->action = (int)data[0] % 0x03;
+ mk_list_add(&dec_rule2->_head, &dec->rules);
+ }
+ }
+ MOVE_INPUT(1);
+ /* print our config struct */
+ flb_utils_print_setup(fuzz_config);
+
+ /* now call into the parser */
+ fuzz_parser = flb_parser_create("fuzzer", format, pregex, FLB_TRUE,
+ time_fmt, time_key, time_offset, time_keep, 0, FLB_FALSE,
+ types, types_len, list, fuzz_config);
+
+ /* Second step is to use the random parser to parse random input */
+ if (fuzz_parser != NULL) {
+ void *out_buf = NULL;
+ size_t out_size = 0;
+ struct flb_time out_time;
+ flb_parser_do(fuzz_parser, (char*)data, size,
+ &out_buf, &out_size, &out_time);
+ if (out_buf != NULL) {
+ free(out_buf);
+ }
+ flb_parser_destroy(fuzz_parser);
+ }
+ else {
+ /* Parser creation failed but we still need to clean
+ * up types and decoders */
+ if (types != NULL) {
+ for (int i=0; i< TYPES_LEN; i++){
+ flb_free(types[i].key);
+ }
+ flb_free(types);
+ }
+ if (list != NULL) {
+ flb_parser_decoder_list_destroy(list);
+ }
+ }
+
+ /* Cleanup everything but the parser */
+ flb_config_exit(fuzz_config);
+ if (time_fmt != NULL) {
+ flb_free(time_fmt);
+ }
+ if (time_key != NULL) {
+ flb_free(time_key);
+ }
+ if (time_offset != NULL) {
+ flb_free(time_offset);
+ }
+#ifdef PREG_FUZZ
+ if (pregex != NULL) {
+ flb_free(pregex);
+ }
+#endif
+
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/record_ac_fuzzer.c b/fluent-bit/tests/internal/fuzzers/record_ac_fuzzer.c
new file mode 100644
index 00000000..9f2ae580
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/record_ac_fuzzer.c
@@ -0,0 +1,101 @@
+#include <fluent-bit/flb_info.h>
+#include <fluent-bit/flb_mem.h>
+#include <fluent-bit/flb_error.h>
+#include <fluent-bit/flb_sds.h>
+#include <fluent-bit/flb_pack.h>
+#include <fluent-bit/flb_record_accessor.h>
+#include <fluent-bit/record_accessor/flb_ra_parser.h>
+#include <msgpack.h>
+#include "flb_fuzz_header.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ /* Limit size to 32KB */
+ if (size > 32768 || size < 6) {
+ return 0;
+ }
+
+ char *outbuf = NULL;
+ char *ra_str = NULL;
+ size_t outsize;
+ int type;
+ int len;
+ size_t off = 0;
+ msgpack_object map;
+
+ /* Set flb_malloc_mod to be fuzzer-data dependent */
+ flb_malloc_p = 0;
+ flb_malloc_mod = *(int*)data;
+ data += 4;
+ size -= 4;
+
+ /* Avoid division by zero for modulo operations */
+ if (flb_malloc_mod == 0) {
+ flb_malloc_mod = 1;
+ }
+
+ if (size < 100) {
+ return 0;
+ }
+
+ struct flb_record_accessor *ra = NULL;
+
+ /* Sample JSON message */
+ len = 60;
+ char *json_raw = get_null_terminated(len, &data, &size);
+
+ /* Convert to msgpack */
+ int ret = flb_pack_json(json_raw, len, &outbuf, &outsize, &type, NULL);
+ if (ret == -1) {
+ flb_free(json_raw);
+ return 0;
+ }
+ flb_free(json_raw);
+
+ char *null_terminated = get_null_terminated(size, &data, &size);
+
+ ra_str = flb_sds_create(null_terminated);
+ if (ra_str != NULL) {
+ ra = flb_ra_create(ra_str, FLB_FALSE);
+ if (!ra) {
+ flb_sds_destroy(ra_str);
+ flb_free(null_terminated);
+ flb_free(outbuf);
+ return 0;
+ }
+
+ flb_ra_is_static(ra);
+
+ msgpack_unpacked result;
+ msgpack_unpacked_init(&result);
+ msgpack_unpack_next(&result, outbuf, outsize, &off);
+ map = result.data;
+
+ flb_sds_t str = flb_ra_translate(ra, NULL, -1, map, NULL);
+ if (!str) {
+ flb_ra_destroy(ra);
+ flb_sds_destroy(ra_str);
+ msgpack_unpacked_destroy(&result);
+
+ /* General cleanup */
+ flb_free(null_terminated);
+ flb_free(outbuf);
+ return 0;
+ }
+ flb_ra_dump(ra);
+
+
+ flb_sds_destroy(str);
+ flb_ra_destroy(ra);
+ flb_sds_destroy(ra_str);
+ msgpack_unpacked_destroy(&result);
+ }
+
+ if (outbuf != NULL) {
+ flb_free(outbuf);
+ }
+ if (null_terminated != NULL) {
+ flb_free(null_terminated);
+ }
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/signv4_fuzzer.c b/fluent-bit/tests/internal/fuzzers/signv4_fuzzer.c
new file mode 100644
index 00000000..4393d159
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/signv4_fuzzer.c
@@ -0,0 +1,111 @@
+#include <fluent-bit/flb_info.h>
+#include <fluent-bit/flb_mem.h>
+#include <fluent-bit/flb_http_client.h>
+#include <fluent-bit/flb_upstream.h>
+#include <fluent-bit/flb_signv4.h>
+#include <fluent-bit/flb_aws_credentials.h>
+#include <monkey/mk_core.h>
+#include <unistd.h>
+#include <fluent-bit/flb_sds.h>
+#include "flb_fuzz_header.h"
+
+#define AWS_ACCESS_KEY_ID "AWS_ACCESS_KEY_ID"
+#define AWS_SECRET_ACCESS_KEY "AWS_SECRET_ACCESS_KEY"
+#define AWS_SESSION_TOKEN "AWS_SESSION_TOKEN"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ if (size < 59) {
+ return 0;
+ }
+
+ /* Set flb_malloc_mod to be fuzzer-data dependent */
+ flb_malloc_p = 0;
+ flb_malloc_mod = *(int*)data;
+ data += 4;
+ size -= 4;
+
+ /* Avoid division by zero for modulo operations */
+ if (flb_malloc_mod == 0) {
+ flb_malloc_mod = 1;
+ }
+
+ char s3_mode = data[0];
+ MOVE_INPUT(1)
+ int method = (int)data[0];
+
+ /* Prepare a general null-terminated string */
+ char *uri = get_null_terminated(50, &data, &size);
+ char *null_terminated = get_null_terminated(size, &data, &size);
+
+ /* Now begin the core work of the fuzzer */
+ struct flb_config *config;
+ struct mk_list *tests;
+ struct flb_aws_provider *provider;
+ config = flb_calloc(1, sizeof(struct flb_config));
+ if (!config) {
+ flb_free(uri);
+ flb_free(null_terminated);
+ return 0;
+ }
+ mk_list_init(&config->upstreams);
+ provider = flb_aws_env_provider_create();
+
+ /* Create the necessary http context */
+ struct flb_upstream *http_u;
+ struct flb_connection *http_u_conn = NULL;
+ struct flb_http_client *http_c;
+ struct flb_config *http_config;
+
+ http_config = flb_config_init();
+ if (http_config == NULL) {
+ flb_aws_provider_destroy(provider);
+ flb_free(uri);
+ flb_free(null_terminated);
+ flb_free(config);
+ return 0;
+ }
+
+ http_u = flb_upstream_create(http_config, "127.0.0.1", 8001, 0, NULL);
+ if (http_u != NULL) {
+ http_u_conn = flb_calloc(1, sizeof(struct flb_connection));
+ if (http_u_conn != NULL) {
+ http_u_conn->upstream = http_u;
+
+ http_c = flb_http_client(http_u_conn, method, uri,
+ null_terminated, size, "127.0.0.1", 8001, NULL, 0);
+ if (http_c) {
+ /* Call into the main target flb_signv4_do*/
+ time_t t = 1440938160;
+ char *region = "us-east-1";
+ char *access_key = "AKIDEXAMPLE";
+ char *service = "service";
+ char *secret_key = "wJalrXUtnFEMI/K7MDENG+bPxRfiCYEXAMPLEKEY";
+ int ret = setenv(AWS_ACCESS_KEY_ID, access_key, 1);
+ if (ret >= 0) {
+ ret = setenv(AWS_SECRET_ACCESS_KEY, secret_key, 1);
+ if (ret >= 0) {
+ flb_sds_t signature = flb_signv4_do(http_c, FLB_TRUE, FLB_FALSE,
+ t, region, service, s3_mode, NULL, provider);
+ if (signature) {
+ flb_sds_destroy(signature);
+ }
+ }
+ }
+ flb_http_client_destroy(http_c);
+ }
+ }
+ flb_upstream_destroy(http_u);
+ }
+
+ /* Cleanup */
+ flb_config_exit(http_config);
+ flb_aws_provider_destroy(provider);
+ flb_free(config);
+
+ flb_free(null_terminated);
+ flb_free(http_u_conn);
+ flb_free(uri);
+
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/strp_fuzzer.c b/fluent-bit/tests/internal/fuzzers/strp_fuzzer.c
new file mode 100644
index 00000000..3de21c7a
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/strp_fuzzer.c
@@ -0,0 +1,35 @@
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fluent-bit/flb_time.h>
+#include <fluent-bit/flb_parser.h>
+#include <msgpack.h>
+#include <fluent-bit/flb_info.h>
+#include <fluent-bit/flb_mem.h>
+#include <fluent-bit/flb_pack.h>
+#include <fluent-bit/flb_utils.h>
+#include <fluent-bit/flb_version.h>
+#include <fluent-bit/flb_strptime.h>
+
+#include "flb_fuzz_header.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ if (size < 40) {
+ return 0;
+ }
+
+ /* Set fuzzer-malloc chance of failure */
+ flb_malloc_mod = 25000;
+ flb_malloc_p = 0;
+
+ char *fmt = get_null_terminated(size - 30, &data, &size);
+ char *buf = get_null_terminated(size, &data, &size);
+
+ struct tm tt;
+ flb_strptime(buf, fmt, &tt);
+
+ flb_free(buf);
+ flb_free(fmt);
+ return 0;
+}
diff --git a/fluent-bit/tests/internal/fuzzers/utils_fuzzer.c b/fluent-bit/tests/internal/fuzzers/utils_fuzzer.c
new file mode 100644
index 00000000..2352adf3
--- /dev/null
+++ b/fluent-bit/tests/internal/fuzzers/utils_fuzzer.c
@@ -0,0 +1,242 @@
+/* Fluent Bit
+ * ==========
+ * Copyright (C) 2019-2021 The Fluent Bit Authors
+ * Copyright (C) 2015-2018 Treasure Data Inc.
+ *
+ * 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 <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <msgpack.h>
+#include <fluent-bit/flb_mem.h>
+#include <fluent-bit/flb_utils.h>
+#include <fluent-bit/flb_slist.h>
+#include <fluent-bit/flb_gzip.h>
+#include <fluent-bit/flb_hash_table.h>
+#include <fluent-bit/flb_uri.h>
+#include <fluent-bit/flb_hash.h>
+#include <fluent-bit/flb_regex.h>
+#include "flb_fuzz_header.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
+{
+ TIMEOUT_GUARD
+
+ if (size < 750) {
+ return 0;
+ }
+
+ /* Set fuzzer-malloc chance of failure */
+ flb_malloc_mod = 25000;
+ flb_malloc_p = 0;
+
+ uint64_t ran_hash = *(uint64_t *)data;
+ char *null_terminated1 = get_null_terminated(25, &data, &size);
+ char *null_terminated2 = get_null_terminated(25, &data, &size);
+ char *null_terminated3 = get_null_terminated(25, &data, &size);
+
+ /* Prepare a general null-terminated string */
+ char *null_terminated = (char*)malloc(size+1);
+ null_terminated[size] = '\0';
+ memcpy(null_terminated, data, size);
+
+ /* Fuzzing of flb_utils.c */
+ int sec;
+ long nsec;
+ size_t new_size;
+ char *prot = NULL;
+ char *host = NULL;
+ char *port = NULL;
+ char *uri = NULL;
+ char *new_dst = NULL;
+
+ if (flb_utils_write_str_buf(null_terminated, size, &new_dst, &new_size) == 0) {
+ flb_free(new_dst);
+ }
+
+ struct mk_list *list = flb_utils_split(null_terminated, 'A', 3);
+ if (list != NULL) {
+ flb_utils_split_free(list);
+ }
+ struct mk_list *list2 = flb_utils_split_quoted(null_terminated, 'A', 3);
+ if (list2 != NULL) {
+ flb_utils_split_free(list2);
+ }
+
+ if (flb_utils_url_split(null_terminated, &prot, &host, &port, &uri) == 0) {
+ flb_free(prot);
+ flb_free(port);
+ flb_free(host);
+ flb_free(uri);
+ }
+
+ char *split_protocol = NULL;
+ char *split_username = NULL;
+ char *split_password = NULL;
+ char *split_host = NULL;
+ char *split_port = NULL;
+ if (flb_utils_proxy_url_split(null_terminated, &split_protocol,
+ &split_username, &split_password, &split_host, &split_port) == 0) {
+ if (split_protocol) {
+ flb_free(split_protocol);
+ }
+ if (split_username) {
+ flb_free(split_username);
+ }
+ if (split_password) {
+ flb_free(split_password);
+ }
+ if (split_host) {
+ flb_free(split_host);
+ }
+ if (split_port) {
+ flb_free(split_port);
+ }
+ }
+
+
+ flb_utils_size_to_bytes(null_terminated);
+ flb_utils_time_split(null_terminated, &sec, &nsec);
+ flb_utils_time_to_seconds(null_terminated);
+ flb_utils_bool(null_terminated);
+ flb_utils_hex2int(null_terminated, size);
+
+ /* Fuzzong of flb_uri.c */
+ struct flb_uri *uri2 = NULL;
+ uri2 = flb_uri_create(null_terminated);
+ if (uri2 != NULL) {
+ flb_uri_get(uri2, (int)data[0]);
+ flb_uri_dump(uri2);
+ flb_uri_destroy(uri2);
+ }
+ flb_sds_t encoded = flb_uri_encode((char*)data, size);
+ if (encoded != NULL) {
+ flb_sds_destroy(encoded);
+ }
+
+ /* Fuzzing of flb_hash.c */
+ struct flb_hash_table *ht = NULL;
+ ht = flb_hash_table_create((int)(data[2] % 0x04),
+ (size_t)data[0],
+ (int)data[1]);
+ if (ht != NULL) {
+ flb_hash_table_add(ht, null_terminated, size, null_terminated, size);
+
+ char *out_buf = NULL;
+ size_t out_size;
+ flb_hash_table_get(ht, null_terminated, size, (void **)&out_buf, &out_size);
+
+ /* now let's create some more instances */
+ char *instances1[128] = { NULL };
+ char *instances2[128] = { NULL };
+ for (int i = 0; i < 128; i++) {
+ char *in1 = malloc(3);
+ char *in2 = malloc(3);
+ memcpy(in1, data+(i*4), 2);
+ memcpy(in2, data+(i*4)+2, 2);
+ in1[2] = '\0';
+ in2[2] = '\0';
+ flb_hash_table_add(ht, in1, 2, in2, 2);
+ instances1[i] = in1;
+ instances2[i] = in2;
+ }
+
+ for(int i = 0; i < 20; i++) {
+ char *hash_out_buf;
+ size_t hash_out_size;
+ flb_hash_table_get_by_id(ht, (int)data[i], null_terminated,
+ (const char **)&hash_out_buf, &hash_out_size);
+ }
+
+ flb_hash_table_del(ht, null_terminated1);
+ flb_hash_table_exists(ht, ran_hash);
+ flb_hash_table_del_ptr(ht, null_terminated2, strlen(null_terminated2), NULL);
+ flb_hash_table_get_ptr(ht, null_terminated3, strlen(null_terminated3));
+
+ flb_hash_table_destroy(ht);
+ for (int i =0; i<128; i++) {
+ flb_free(instances1[i]);
+ flb_free(instances2[i]);
+ }
+ }
+
+ /* sds */
+ flb_sds_t fs = flb_sds_create_len((const char*)data, size);
+ if (fs != NULL) {
+ fs = flb_sds_cat_esc(fs, "AAABBBCCC", 9, "ABC", 3);
+ if (fs != NULL) {
+ flb_sds_destroy(fs);
+ }
+ }
+
+ /* Fuzzing of flb_gzip.c */
+ void *str = NULL;
+ size_t len;
+ void *out_data = NULL;
+ size_t out_len;
+ if (flb_gzip_compress((char*)data, size, &str, &len) != -1) {
+ flb_gzip_uncompress(str, len, &out_data, &out_len);
+ }
+ if (str != NULL) {
+ free(str);
+ }
+ if (out_data != NULL) {
+ free(out_data);
+ }
+ void *out_data2 = NULL;
+ size_t out2_len;
+ int uncompress_ret = flb_gzip_uncompress((char*)data, size, &out_data2, &out2_len);
+ if (uncompress_ret != -1 && out_data2 != NULL) {
+ flb_free(out_data2);
+ }
+
+ /* Fuzzing the sha routines */
+ struct flb_hash sha512;
+ uint8_t buf[64];
+
+ flb_hash_init(&sha512, FLB_HASH_SHA512);
+ flb_hash_update(&sha512, (unsigned char *) null_terminated, 32);
+ flb_hash_update(&sha512, (unsigned char *) null_terminated+32, 32);
+ flb_hash_update(&sha512, (unsigned char *) null_terminated+64, 32);
+ flb_hash_finalize(&sha512, buf, sizeof(buf));
+ flb_hash_cleanup(&sha512);
+
+ /* regex */
+ char *pregex = "^(?<INT>[^ ]+) (?<FLOAT>[^ ]+) (?<BOOL>[^ ]+) (?<STRING>.+)$";
+ flb_regex_init();
+ struct flb_regex *freg = flb_regex_create(pregex);
+ if (freg != NULL) {
+ flb_regex_match(freg, (unsigned char*)null_terminated, size);
+ flb_regex_destroy(freg);
+ }
+ flb_regex_exit();
+
+ /* slist */
+ struct mk_list list3;
+ flb_slist_create(&list3);
+ flb_sds_t slist_str = flb_sds_create_len((const char*)data, size);
+ flb_slist_add_sds(&list3, slist_str);
+ flb_slist_entry_get(&list3, 100);
+ flb_slist_dump(&list3);
+ flb_slist_destroy(&list3);
+
+
+ /* General cleanup */
+ flb_free(null_terminated);
+ flb_free(null_terminated1);
+ flb_free(null_terminated2);
+ flb_free(null_terminated3);
+ return 0;
+}