xref: /netbsd-src/external/bsd/tmux/dist/fuzz/input-fuzzer.c (revision ccd9df534e375a4366c5b55f23782053c7a98d82)
1 /*
2  * Copyright (c) 2020 Sergey Nizovtsev <snizovtsev@gmail.com>
3  *
4  * Permission to use, copy, modify, and distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
13  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
14  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include <stddef.h>
18 #include <assert.h>
19 #include <fcntl.h>
20 
21 #include "tmux.h"
22 
23 #define FUZZER_MAXLEN 512
24 #define PANE_WIDTH 80
25 #define PANE_HEIGHT 25
26 
27 struct event_base *libevent;
28 
29 int
30 LLVMFuzzerTestOneInput(const u_char *data, size_t size)
31 {
32 	struct bufferevent	*vpty[2];
33 	struct window		*w;
34 	struct window_pane 	*wp;
35 	int			 error;
36 
37 	/*
38 	 * Since AFL doesn't support -max_len paramenter we have to
39 	 * discard long inputs manually.
40 	 */
41 	if (size > FUZZER_MAXLEN)
42 		return 0;
43 
44 	w = window_create(PANE_WIDTH, PANE_HEIGHT, 0, 0);
45 	wp = window_add_pane(w, NULL, 0, 0);
46 	bufferevent_pair_new(libevent, BEV_OPT_CLOSE_ON_FREE, vpty);
47 	wp->ictx = input_init(wp, vpty[0], NULL);
48 	window_add_ref(w, __func__);
49 
50 	wp->fd = open("/dev/null", O_WRONLY);
51 	if (wp->fd == -1)
52 		errx(1, "open(\"/dev/null\") failed");
53 	wp->event = bufferevent_new(wp->fd, NULL, NULL, NULL, NULL);
54 
55 	input_parse_buffer(wp, (u_char *)data, size);
56 	while (cmdq_next(NULL) != 0)
57 		;
58 	error = event_base_loop(libevent, EVLOOP_NONBLOCK);
59 	if (error == -1)
60 		errx(1, "event_base_loop failed");
61 
62 	assert(w->references == 1);
63 	window_remove_ref(w, __func__);
64 
65 	bufferevent_free(vpty[0]);
66 	bufferevent_free(vpty[1]);
67 
68 	return 0;
69 }
70 
71 int
72 LLVMFuzzerInitialize(__unused int *argc, __unused char ***argv)
73 {
74 	const struct options_table_entry	*oe;
75 
76 	global_environ = environ_create();
77 	global_options = options_create(NULL);
78 	global_s_options = options_create(NULL);
79 	global_w_options = options_create(NULL);
80 	for (oe = options_table; oe->name != NULL; oe++) {
81 		if (oe->scope & OPTIONS_TABLE_SERVER)
82 			options_default(global_options, oe);
83 		if (oe->scope & OPTIONS_TABLE_SESSION)
84 			options_default(global_s_options, oe);
85 		if (oe->scope & OPTIONS_TABLE_WINDOW)
86 			options_default(global_w_options, oe);
87 	}
88 	libevent = osdep_event_init();
89 
90 	options_set_number(global_w_options, "monitor-bell", 0);
91 	options_set_number(global_w_options, "allow-rename", 1);
92 	options_set_number(global_options, "set-clipboard", 2);
93 	socket_path = xstrdup("dummy");
94 
95 	return 0;
96 }
97