/src/fluent-bit/tests/internal/fuzzers/input_fuzzer.c
Line | Count | Source |
1 | | #include <fluent-bit.h> |
2 | | #include <pthread.h> |
3 | | #include <stdlib.h> |
4 | | #include <unistd.h> |
5 | | #include <stdint.h> |
6 | | #include <sys/stat.h> |
7 | | #include <fluent-bit/flb_input_chunk.h> |
8 | | #include <fluent-bit/flb_storage.h> |
9 | | #include <fluent-bit/flb_router.h> |
10 | | #include <fluent-bit/flb_time.h> |
11 | | |
12 | | #include "chunkio/chunkio.h" |
13 | | #include "flb_fuzz_header.h" |
14 | | |
15 | | |
16 | | const char *input_chunk_property_keywords[] = { |
17 | | "log_suppress_interval", |
18 | | "routable", |
19 | | "alias", |
20 | | "mem_buf_limit", |
21 | | "listen", |
22 | | "log_level", |
23 | | "host", |
24 | | "port", |
25 | | "ipv6", |
26 | | "net.", |
27 | | "tls", |
28 | | "tls.verify", |
29 | | "tls.debug", |
30 | | "tls.ca_path", |
31 | | "tls.key_file", |
32 | | "tls.vhost", |
33 | | "tls.ca_file", |
34 | | "tls.crt_file", |
35 | | "tls.key_passwd", |
36 | | "threaded", |
37 | | "storage.type", |
38 | | }; |
39 | | |
40 | | int LLVMFuzzerTestOneInput(const uint8_t *data3, size_t size3) |
41 | 92 | { |
42 | 92 | int i; |
43 | 92 | int ret; |
44 | 92 | int in_ffd; |
45 | 92 | int out_ffd; |
46 | | |
47 | 92 | flb_ctx_t *ctx; |
48 | 92 | size_t total_bytes; |
49 | 92 | struct flb_input_instance *i_ins; |
50 | 92 | struct mk_list *tmp; |
51 | 92 | struct mk_list *head; |
52 | 92 | struct flb_input_chunk *ic; |
53 | 92 | struct flb_task *task; |
54 | | |
55 | 92 | if (size3 < 60) { |
56 | 0 | return 0; |
57 | 0 | } |
58 | | /* Set fuzzer-malloc chance of failure */ |
59 | 92 | #ifdef FLB_HAVE_TESTS_OSSFUZZ |
60 | 92 | flb_malloc_p = 0; |
61 | 92 | flb_malloc_mod = 25000; |
62 | 92 | #endif |
63 | 92 | char *input_buffer1 = get_null_terminated(30, &data3, &size3); |
64 | 92 | if (input_buffer1 == NULL) { |
65 | 0 | return 0; |
66 | 0 | } |
67 | 92 | size_t input_buffer1_len = strlen(input_buffer1); |
68 | | |
69 | 92 | char *input_buffer2 = get_null_terminated(10, &data3, &size3); |
70 | 92 | if (input_buffer2 == NULL) { |
71 | 0 | flb_free(input_buffer1); |
72 | 0 | return 0; |
73 | 0 | } |
74 | | |
75 | 92 | char *input_buffer3 = get_null_terminated(10, &data3, &size3); |
76 | 92 | if (input_buffer3 == NULL) { |
77 | 0 | flb_free(input_buffer1); |
78 | 0 | flb_free(input_buffer2); |
79 | 0 | return 0; |
80 | 0 | } |
81 | | |
82 | | /* Create context, flush every second (some checks omitted here) */ |
83 | 92 | ctx = flb_create(); |
84 | | |
85 | | /* create chunks in /tmp folder */ |
86 | 92 | ret = flb_service_set(ctx, |
87 | 92 | "flush", "2", "grace", "1", |
88 | 92 | "storage.path", "/tmp/input-chunk-test/", |
89 | 92 | "Log_Level", "error", |
90 | 92 | NULL); |
91 | 92 | if (ret != 0) { |
92 | 0 | flb_free(input_buffer1); |
93 | 0 | flb_free(input_buffer2); |
94 | 0 | flb_free(input_buffer3); |
95 | 0 | return 0; |
96 | 0 | } |
97 | | |
98 | | /* Lib input mode */ |
99 | 92 | in_ffd = flb_input(ctx, (char *) "lib", NULL); |
100 | 92 | ret = flb_input_set(ctx, in_ffd, |
101 | 92 | "tag", "test", |
102 | 92 | "storage.type", "filesystem", |
103 | 92 | NULL); |
104 | 92 | if (ret != 0) { |
105 | 0 | flb_free(input_buffer1); |
106 | 0 | flb_free(input_buffer2); |
107 | 0 | flb_free(input_buffer3); |
108 | 0 | return 0; |
109 | 0 | } |
110 | | |
111 | | /* an invalid output destination */ |
112 | 92 | out_ffd = flb_output(ctx, (char *) "http", NULL); |
113 | 92 | flb_output_set(ctx, out_ffd, |
114 | 92 | "match", "test", |
115 | 92 | "Host", "127.0.0.1", |
116 | 92 | "Port", "1", |
117 | 92 | "storage.total_limit_size", "1K", |
118 | 92 | NULL); |
119 | | |
120 | | /* Start */ |
121 | 92 | ret = flb_start(ctx); |
122 | 92 | if (ret != 0) { |
123 | 0 | flb_free(input_buffer1); |
124 | 0 | flb_free(input_buffer2); |
125 | 0 | flb_free(input_buffer3); |
126 | 0 | return 0; |
127 | 0 | } |
128 | | |
129 | 92 | i_ins = mk_list_entry_first(&ctx->config->inputs, |
130 | 92 | struct flb_input_instance, |
131 | 92 | _head); |
132 | | |
133 | | /* main fuzzing logic */ |
134 | 92 | flb_input_set_property(i_ins, input_buffer2, input_buffer3); |
135 | 2.02k | for (int i = 0; i < sizeof(input_chunk_property_keywords)/sizeof(char*); i++) { |
136 | 1.93k | flb_input_set_property(i_ins, |
137 | 1.93k | input_chunk_property_keywords[i], |
138 | 1.93k | input_buffer3); |
139 | 1.93k | } |
140 | | |
141 | | /* Ingest fuzz data sample */ |
142 | 276 | for (i = 0; i < 2; ++i) { |
143 | 184 | flb_lib_push(ctx, in_ffd, (char *) input_buffer1, input_buffer1_len); |
144 | 184 | sleep(1); |
145 | 184 | total_bytes = flb_input_chunk_total_size(i_ins); |
146 | 184 | ret = total_bytes > 1000 ? -1 : 0; |
147 | 184 | } |
148 | | |
149 | | /* FORCE clean up test tasks */ |
150 | 92 | mk_list_foreach_safe(head, tmp, &i_ins->tasks) { |
151 | 6 | task = mk_list_entry(head, struct flb_task, _head); |
152 | 6 | if (task->users != 0 || |
153 | 6 | mk_list_size(&task->retries) != 0 || |
154 | 6 | mk_list_size(&task->routes) != 0) { |
155 | 6 | continue; |
156 | 6 | } |
157 | | |
158 | 0 | flb_info("[task] cleanup test task"); |
159 | 0 | flb_task_destroy(task, FLB_TRUE); |
160 | 0 | } |
161 | | |
162 | | /* clean up test chunks */ |
163 | 92 | mk_list_foreach_safe(head, tmp, &i_ins->chunks) { |
164 | 7 | ic = mk_list_entry(head, struct flb_input_chunk, _head); |
165 | 7 | if (ic->task != NULL) { |
166 | 6 | continue; |
167 | 6 | } |
168 | | |
169 | 1 | flb_input_chunk_destroy(ic, FLB_TRUE); |
170 | 1 | } |
171 | 92 | flb_free(input_buffer1); |
172 | 92 | flb_free(input_buffer2); |
173 | 92 | flb_free(input_buffer3); |
174 | | |
175 | 92 | flb_time_msleep(200); |
176 | 92 | flb_stop(ctx); |
177 | 92 | flb_destroy(ctx); |
178 | | |
179 | 92 | return 0; |
180 | 92 | } |