Coverage Report

Created: 2026-06-07 07:09

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
61.2k
#define TYPES_LEN 5
29
30
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
31
18.4k
{
32
18.4k
    TIMEOUT_GUARD
33
34
18.4k
    char *format      = NULL;
35
18.4k
    char *time_fmt    = NULL;
36
18.4k
    char *time_key    = NULL;
37
18.4k
    char *time_offset = NULL;
38
18.4k
    char *pregex      = NULL;
39
18.4k
    struct flb_parser_types *types = NULL;
40
18.4k
    struct flb_config *fuzz_config = NULL;
41
18.4k
    struct flb_parser *fuzz_parser = NULL;
42
18.4k
    int time_keep = 0;
43
18.4k
    int types_len = 0;
44
45
    /* Set fuzzer-malloc chance of failure */
46
18.4k
    flb_malloc_mod = 25000;
47
18.4k
    flb_malloc_p = 0;
48
49
18.4k
    if (size < 100) {
50
17
        return 0;
51
17
    }
52
53
    /* json parser */
54
18.3k
    fuzz_config = flb_config_init();
55
56
    /* format + pregex */
57
18.3k
    if (GET_MOD_EQ(4,0)) {
58
10.2k
        format = "json";
59
10.2k
    }
60
8.13k
    else if (GET_MOD_EQ(4,1)) {
61
226
        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
226
        pregex = "^(?<INT>[^ ]+) (?<FLOAT>[^ ]+) (?<BOOL>[^ ]+) (?<STRING>.+)$";
70
226
#endif
71
226
    }
72
7.90k
    else if (GET_MOD_EQ(4,2)) {
73
858
        format = "ltsv";
74
858
    }
75
7.05k
    else {
76
7.05k
        format = "logfmt";
77
7.05k
    }
78
18.3k
    MOVE_INPUT(1);
79
80
    /* time_fmt */
81
18.3k
    if (GET_MOD_EQ(2,1)) {
82
2.81k
        time_fmt = get_null_terminated(15, &data, &size);
83
2.81k
    }
84
18.3k
    MOVE_INPUT(1);
85
86
    /* time_key */
87
18.3k
    if (GET_MOD_EQ(2,1)) {
88
2.36k
        time_key = get_null_terminated(15, &data, &size);
89
2.36k
    }
90
18.3k
    MOVE_INPUT(1);
91
92
    /* time_offset */
93
18.3k
    if (GET_MOD_EQ(2,1)) {
94
611
        time_offset = get_null_terminated(15, &data, &size);
95
611
    }
96
18.3k
    MOVE_INPUT(1);
97
98
    /* time_keep */
99
18.3k
    time_keep = (GET_MOD_EQ(2,1)) ? MK_TRUE : MK_FALSE;
100
18.3k
    MOVE_INPUT(1);
101
102
    /* types_str */
103
18.3k
    if (GET_MOD_EQ(2,1)) {
104
7.62k
        types =  flb_malloc(sizeof(struct flb_parser_types) * TYPES_LEN);
105
7.62k
        char *parser_type_keys[5] = {"AAA", "BBB", "CCC", "DDD", "EEE" };
106
7.62k
        int parser_types[5] = {FLB_PARSER_TYPE_INT, FLB_PARSER_TYPE_FLOAT,
107
7.62k
                               FLB_PARSER_TYPE_BOOL, FLB_PARSER_TYPE_STRING,
108
7.62k
                               FLB_PARSER_TYPE_HEX};
109
45.7k
        for (int i = 0; i < TYPES_LEN; i++) {
110
38.1k
            types[i].key     = strdup(parser_type_keys[i]);
111
38.1k
            types[i].key_len = strlen(parser_type_keys[i]);
112
38.1k
            types[i].type    = parser_types[i];
113
38.1k
        }
114
7.62k
        types_len = TYPES_LEN;
115
7.62k
    }
116
18.3k
    MOVE_INPUT(1);
117
118
    /* decoders */
119
18.3k
    struct mk_list *list = NULL;
120
18.3k
    if (GET_MOD_EQ(2,1)) {
121
11.4k
        MOVE_INPUT(1);
122
11.4k
        list = flb_malloc(sizeof(struct mk_list));
123
11.4k
        mk_list_init(list);
124
125
11.4k
        struct flb_parser_dec *dec = malloc(sizeof(struct flb_parser_dec));
126
11.4k
        dec->key            = flb_sds_create_len("AAA", 3);
127
11.4k
        dec->buffer         = flb_sds_create_size(FLB_PARSER_DEC_BUF_SIZE);
128
11.4k
        dec->add_extra_keys = FLB_TRUE;
129
11.4k
        mk_list_init(&dec->rules);
130
11.4k
        mk_list_add(&dec->_head, list);
131
132
11.4k
        struct flb_parser_dec_rule *dec_rule = malloc(sizeof(struct flb_parser_dec_rule));
133
11.4k
        dec_rule->type = (int)(data[0] % 0x02);
134
11.4k
        MOVE_INPUT(1);
135
11.4k
        dec_rule->backend = (int)(data[0] % 0x04);
136
11.4k
        MOVE_INPUT(1);
137
11.4k
        dec_rule->action = (int)data[0] % 0x03;
138
11.4k
        mk_list_add(&dec_rule->_head, &dec->rules);
139
140
11.4k
        if (GET_MOD_EQ(2,1)) {
141
6.87k
            struct flb_parser_dec_rule *dec_rule2 = malloc(sizeof(struct flb_parser_dec_rule));
142
6.87k
            dec_rule2->type = (int)(data[0] % 0x02);
143
6.87k
            MOVE_INPUT(1);
144
6.87k
            dec_rule2->backend = (int)(data[0] % 0x04);
145
6.87k
            MOVE_INPUT(1);
146
6.87k
            dec_rule->action = (int)data[0] % 0x03;
147
6.87k
            mk_list_add(&dec_rule2->_head, &dec->rules);
148
6.87k
        }
149
11.4k
    }
150
18.3k
    MOVE_INPUT(1);
151
    /* print our config struct */
152
18.3k
    flb_utils_print_setup(fuzz_config);
153
154
    /* now call into the parser */
155
18.3k
    fuzz_parser = flb_parser_create("fuzzer", format, pregex, FLB_TRUE,
156
18.3k
            time_fmt, time_key, time_offset, time_keep, 0, FLB_FALSE,
157
18.3k
            FLB_FALSE, types, types_len, list, fuzz_config);
158
159
    /* Second step is to use the random parser to parse random input */
160
18.3k
    if (fuzz_parser != NULL) {
161
18.3k
        void *out_buf = NULL;
162
18.3k
        size_t out_size = 0;
163
18.3k
        struct flb_time out_time;
164
18.3k
        flb_parser_do(fuzz_parser, (char*)data, size,
165
18.3k
                      &out_buf, &out_size, &out_time);
166
18.3k
        if (out_buf != NULL) {
167
8.50k
            free(out_buf);
168
8.50k
        }
169
18.3k
        flb_parser_destroy(fuzz_parser);
170
18.3k
    }
171
44
    else {
172
        /* Parser creation failed but we still need to clean
173
         * up types and decoders */
174
44
        if (types != NULL) {
175
168
            for (int i=0; i< TYPES_LEN; i++){
176
140
                flb_free(types[i].key);
177
140
            }
178
28
            flb_free(types);
179
28
        }
180
44
        if (list != NULL) {
181
23
            flb_parser_decoder_list_destroy(list);
182
23
        }
183
44
    }
184
185
    /* Cleanup everything but the parser */
186
18.3k
    flb_config_exit(fuzz_config);
187
18.3k
    if (time_fmt != NULL) {
188
2.81k
      flb_free(time_fmt);
189
2.81k
    }
190
18.3k
    if (time_key != NULL) {
191
2.36k
        flb_free(time_key);
192
2.36k
    }
193
18.3k
    if (time_offset != NULL) {
194
611
        flb_free(time_offset);
195
611
    }
196
#ifdef PREG_FUZZ
197
    if (pregex != NULL) {
198
        flb_free(pregex);
199
    }
200
#endif
201
202
18.3k
    return 0;
203
18.4k
}