Coverage Report

Created: 2026-11-12 07:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fluent-bit/tests/internal/fuzzers/parser_fuzzer.c
Line
Count
Source
1
/*  Fluent Bit
2
 *  ==========
3
 *  Copyright (C) 2019-2021 The Fluent Bit Authors
4
 *  Copyright (C) 2015-2018 Treasure Data Inc.
5
 *
6
 *  Licensed under the Apache License, Version 2.0 (the "License");
7
 *  you may not use this file except in compliance with the License.
8
 *  You may obtain a copy of the License at
9
 *
10
 *      http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 *  Unless required by applicable law or agreed to in writing, software
13
 *  distributed under the License is distributed on an "AS IS" BASIS,
14
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 *  See the License for the specific language governing permissions and
16
 *  limitations under the License.
17
 */
18
#include <stdint.h>
19
#include <string.h>
20
#include <stdlib.h>
21
#include <fluent-bit/flb_utils.h>
22
#include <fluent-bit/flb_time.h>
23
#include <fluent-bit/flb_parser.h>
24
#include <fluent-bit/flb_parser_decoder.h>
25
26
#include "flb_fuzz_header.h"
27
28
36.8k
#define TYPES_LEN 5
29
30
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
31
16.5k
{
32
16.5k
    TIMEOUT_GUARD
33
34
16.5k
    char *format      = NULL;
35
16.5k
    char *time_fmt    = NULL;
36
16.5k
    char *time_key    = NULL;
37
16.5k
    char *time_offset = NULL;
38
16.5k
    char *pregex      = NULL;
39
16.5k
    struct flb_parser_types *types = NULL;
40
16.5k
    struct flb_config *fuzz_config = NULL;
41
16.5k
    struct flb_parser *fuzz_parser = NULL;
42
16.5k
    int time_keep = 0;
43
16.5k
    int types_len = 0;
44
45
    /* Set fuzzer-malloc chance of failure */
46
16.5k
    flb_malloc_mod = 25000;
47
16.5k
    flb_malloc_p = 0;
48
49
16.5k
    if (size < 100) {
50
17
        return 0;
51
17
    }
52
53
    /* json parser */
54
16.5k
    fuzz_config = flb_config_init();
55
56
    /* format + pregex */
57
16.5k
    if (GET_MOD_EQ(4,0)) {
58
5.81k
        format = "json";
59
5.81k
    }
60
10.7k
    else if (GET_MOD_EQ(4,1)) {
61
277
        format = "regex";
62
#ifdef PREG_FUZZ
63
        pregex = malloc(30);
64
        pregex[29] = '\0';
65
        memcpy(pregex, data, 29);
66
        data += 29;
67
        size -= 29;
68
#else
69
277
        pregex = "^(?<INT>[^ ]+) (?<FLOAT>[^ ]+) (?<BOOL>[^ ]+) (?<STRING>.+)$";
70
277
#endif
71
277
    }
72
10.4k
    else if (GET_MOD_EQ(4,2)) {
73
1.54k
        format = "ltsv";
74
1.54k
    }
75
8.87k
    else {
76
8.87k
        format = "logfmt";
77
8.87k
    }
78
16.5k
    MOVE_INPUT(1);
79
80
    /* time_fmt */
81
16.5k
    if (GET_MOD_EQ(2,1)) {
82
2.36k
        time_fmt = get_null_terminated(15, &data, &size);
83
2.36k
    }
84
16.5k
    MOVE_INPUT(1);
85
86
    /* time_key */
87
16.5k
    if (GET_MOD_EQ(2,1)) {
88
1.99k
        time_key = get_null_terminated(15, &data, &size);
89
1.99k
    }
90
16.5k
    MOVE_INPUT(1);
91
92
    /* time_offset */
93
16.5k
    if (GET_MOD_EQ(2,1)) {
94
455
        time_offset = get_null_terminated(15, &data, &size);
95
455
    }
96
16.5k
    MOVE_INPUT(1);
97
98
    /* time_keep */
99
16.5k
    time_keep = (GET_MOD_EQ(2,1)) ? MK_TRUE : MK_FALSE;
100
16.5k
    MOVE_INPUT(1);
101
102
    /* types_str */
103
16.5k
    if (GET_MOD_EQ(2,1)) {
104
4.58k
        types =  flb_malloc(sizeof(struct flb_parser_types) * TYPES_LEN);
105
4.58k
        char *parser_type_keys[5] = {"AAA", "BBB", "CCC", "DDD", "EEE" };
106
4.58k
        int parser_types[5] = {FLB_PARSER_TYPE_INT, FLB_PARSER_TYPE_FLOAT,
107
4.58k
                               FLB_PARSER_TYPE_BOOL, FLB_PARSER_TYPE_STRING,
108
4.58k
                               FLB_PARSER_TYPE_HEX};
109
27.5k
        for (int i = 0; i < TYPES_LEN; i++) {
110
22.9k
            types[i].key     = strdup(parser_type_keys[i]);
111
22.9k
            types[i].key_len = strlen(parser_type_keys[i]);
112
22.9k
            types[i].type    = parser_types[i];
113
22.9k
        }
114
4.58k
        types_len = TYPES_LEN;
115
4.58k
    }
116
16.5k
    MOVE_INPUT(1);
117
118
    /* decoders */
119
16.5k
    struct mk_list *list = NULL;
120
16.5k
    if (GET_MOD_EQ(2,1)) {
121
11.5k
        MOVE_INPUT(1);
122
11.5k
        list = flb_malloc(sizeof(struct mk_list));
123
11.5k
        mk_list_init(list);
124
125
11.5k
        struct flb_parser_dec *dec = malloc(sizeof(struct flb_parser_dec));
126
11.5k
        dec->key            = flb_sds_create_len("AAA", 3);
127
11.5k
        dec->buffer         = flb_sds_create_size(FLB_PARSER_DEC_BUF_SIZE);
128
11.5k
        dec->add_extra_keys = FLB_TRUE;
129
11.5k
        mk_list_init(&dec->rules);
130
11.5k
        mk_list_add(&dec->_head, list);
131
132
11.5k
        struct flb_parser_dec_rule *dec_rule = malloc(sizeof(struct flb_parser_dec_rule));
133
11.5k
        dec_rule->type = (int)(data[0] % 0x02);
134
11.5k
        MOVE_INPUT(1);
135
11.5k
        dec_rule->backend = (int)(data[0] % 0x04);
136
11.5k
        MOVE_INPUT(1);
137
11.5k
        dec_rule->action = (int)data[0] % 0x03;
138
11.5k
        mk_list_add(&dec_rule->_head, &dec->rules);
139
140
11.5k
        if (GET_MOD_EQ(2,1)) {
141
8.65k
            struct flb_parser_dec_rule *dec_rule2 = malloc(sizeof(struct flb_parser_dec_rule));
142
8.65k
            dec_rule2->type = (int)(data[0] % 0x02);
143
8.65k
            MOVE_INPUT(1);
144
8.65k
            dec_rule2->backend = (int)(data[0] % 0x04);
145
8.65k
            MOVE_INPUT(1);
146
8.65k
            dec_rule->action = (int)data[0] % 0x03;
147
8.65k
            mk_list_add(&dec_rule2->_head, &dec->rules);
148
8.65k
        }
149
11.5k
    }
150
16.5k
    MOVE_INPUT(1);
151
    /* print our config struct */
152
16.5k
    flb_utils_print_setup(fuzz_config);
153
154
    /* now call into the parser */
155
16.5k
    fuzz_parser = flb_parser_create("fuzzer", format, pregex, FLB_TRUE,
156
16.5k
            time_fmt, time_key, time_offset, time_keep, 0, FLB_FALSE,
157
16.5k
            FLB_FALSE, types, types_len, list, fuzz_config);
158
159
    /* Second step is to use the random parser to parse random input */
160
16.5k
    if (fuzz_parser != NULL) {
161
16.4k
        void *out_buf = NULL;
162
16.4k
        size_t out_size = 0;
163
16.4k
        struct flb_time out_time;
164
16.4k
        flb_parser_do(fuzz_parser, (char*)data, size,
165
16.4k
                      &out_buf, &out_size, &out_time);
166
16.4k
        if (out_buf != NULL) {
167
11.0k
            free(out_buf);
168
11.0k
        }
169
16.4k
        flb_parser_destroy(fuzz_parser);
170
16.4k
    }
171
38
    else {
172
        /* Parser creation failed but we still need to clean
173
         * up types and decoders */
174
38
        if (types != NULL) {
175
108
            for (int i=0; i< TYPES_LEN; i++){
176
90
                flb_free(types[i].key);
177
90
            }
178
18
            flb_free(types);
179
18
        }
180
38
        if (list != NULL) {
181
20
            flb_parser_decoder_list_destroy(list);
182
20
        }
183
38
    }
184
185
    /* Cleanup everything but the parser */
186
16.5k
    flb_config_exit(fuzz_config);
187
16.5k
    if (time_fmt != NULL) {
188
2.36k
      flb_free(time_fmt);
189
2.36k
    }
190
16.5k
    if (time_key != NULL) {
191
1.99k
        flb_free(time_key);
192
1.99k
    }
193
16.5k
    if (time_offset != NULL) {
194
455
        flb_free(time_offset);
195
455
    }
196
#ifdef PREG_FUZZ
197
    if (pregex != NULL) {
198
        flb_free(pregex);
199
    }
200
#endif
201
202
16.5k
    return 0;
203
16.5k
}