Coverage Report

Created: 2026-02-09 07:38

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