/* 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 #include #include #include #include #include #include #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 = "^(?[^ ]+) (?[^ ]+) (?[^ ]+) (?.+)$"; #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; }