1 /* Copyright 2021 Google LLC
2 Licensed under the Apache License, Version 2.0 (the "License");
3 you may not use this file except in compliance with the License.
4 You may obtain a copy of the License at
5 http://www.apache.org/licenses/LICENSE-2.0
6 Unless required by applicable law or agreed to in writing, software
7 distributed under the License is distributed on an "AS IS" BASIS,
8 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9 See the License for the specific language governing permissions and
10 limitations under the License.
11 */
12 #include "apr.h"
13 #include "apr_file_io.h"
14 #include "apr_poll.h"
15 #include "apr_portable.h"
16 #include "apr_proc_mutex.h"
17 #include "apr_signal.h"
18 #include "apr_strings.h"
19 #include "apr_thread_mutex.h"
20 #include "apr_thread_proc.h"
21
22 #define APR_WANT_STRFUNC
23 #include "apr_file_io.h"
24 #include "apr_fnmatch.h"
25 #include "apr_want.h"
26
27 #include "apr_poll.h"
28 #include "apr_want.h"
29
30 #include "ap_config.h"
31 #include "ap_expr.h"
32 #include "ap_listen.h"
33 #include "ap_provider.h"
34 #include "ap_regex.h"
35
36 #include "ada_fuzz_header.h"
37
38
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)39 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
40 // Initialize fuzzing garbage collector. We use this to easily
41 // get data types seeded with random input from the fuzzer.
42 af_gb_init();
43
44 const uint8_t *data2 = data;
45 size_t size2 = size;
46
47 char *new_str = af_gb_get_null_terminated(&data2, &size2);
48 char *new_dst = af_gb_get_null_terminated(&data2, &size2);
49 if (new_str != NULL && new_dst != NULL) {
50
51 // Targets that do not require a pool
52 ap_cstr_casecmp(new_str, new_str);
53 ap_getparents(new_str);
54 ap_unescape_url(new_str);
55 ap_unescape_urlencoded(new_str);
56 ap_strcmp_match(new_str, new_dst);
57
58 char *ns3 = af_gb_get_null_terminated(&data2, &size2);
59 if (ns3 != NULL) {
60 ap_no2slash(ns3);
61 }
62
63 char *ns11 = af_gb_get_null_terminated(&data2, &size2);
64 if (ns11) {
65 char *ns10 = malloc(strlen(ns11)*3+1); // big enough for worst-case URL-escaped input.
66 ap_escape_path_segment_buffer(ns10, ns11);
67 free(ns10);
68 }
69
70 // Pool initialisation
71 if (apr_pool_initialize() == APR_SUCCESS) {
72 apr_pool_t *pool = NULL;
73 apr_pool_create(&pool, NULL);
74
75 // Targets that require a pool
76 ns3 = af_gb_get_null_terminated(&data2, &size2);
77 if (ns3 != NULL) {
78 ap_make_dirstr_parent(pool, ns3);
79 }
80
81 ap_field_noparam(pool, new_str);
82
83 ap_escape_shell_cmd(pool, new_str);
84 ap_os_escape_path(pool, new_str, 0);
85 ap_escape_html2(pool, new_str, 0);
86 ap_escape_logitem(pool, new_str);
87
88 // This line causes some issues if something bad is allocated
89 ap_escape_quotes(pool, new_str);
90
91 if (size > 2) {
92 ap_cstr_casecmpn(new_str, new_str + 2, size - 2);
93 }
94
95 char *d = malloc(size * 2);
96 ap_escape_errorlog_item(d, new_str, size * 2);
97 free(d);
98
99 // base64
100 char *decoded = NULL;
101 decoded = ap_pbase64decode(pool, new_str);
102 ap_pbase64encode(pool, new_str);
103
104 char *ns12 = af_gb_get_null_terminated(&data2, &size2);
105 if (ns12 != NULL) {
106 char *d;
107 apr_size_t dlen;
108 ap_pbase64decode_strict(pool, ns12, &d, &dlen);
109 }
110
111 char *tmp_s = new_str;
112 ap_getword_conf2(pool, &tmp_s);
113
114 // str functions
115 ap_strcasecmp_match(tmp_s, new_dst);
116 ap_strcasestr(tmp_s, new_dst);
117
118 // List functions
119 tmp_s = new_str;
120 ap_get_list_item(pool, &tmp_s);
121 tmp_s = new_str;
122 ap_find_list_item(pool, &tmp_s, "kjahsdfkj");
123 ap_find_token(pool, tmp_s, "klsjdfk");
124 ap_find_last_token(pool, tmp_s, "sdadf");
125 ap_is_chunked(pool, tmp_s);
126
127 apr_array_header_t *offers = NULL;
128 ap_parse_token_list_strict(pool, new_str, &offers, 0);
129
130 char *tmp_null = NULL;
131 ap_pstr2_alnum(pool, new_str, &tmp_null);
132
133 // Word functions
134 tmp_s = new_str;
135 ap_getword(pool, &tmp_s, 0);
136
137 tmp_s = new_str;
138 ap_getword_white_nc(pool, &tmp_s);
139
140 tmp_s = new_str;
141 ap_get_token(pool, &tmp_s, 1);
142
143 tmp_s = new_str;
144 ap_escape_urlencoded(pool, tmp_s);
145
146 apr_interval_time_t timeout;
147 ap_timeout_parameter_parse(new_str, &timeout, "ms");
148
149 tmp_s = new_str;
150 ap_content_type_tolower(tmp_s);
151
152
153 char filename[256];
154 sprintf(filename, "/tmp/libfuzzer.%d", getpid());
155 FILE *fp = fopen(filename, "wb");
156 fwrite(data, size, 1, fp);
157 fclose(fp);
158
159 // Fuzzer logic here
160 ap_configfile_t *cfg;
161 ap_pcfg_openfile(&cfg, pool, filename);
162 char tmp_line[100];
163 if ((af_get_short(&data2, &size2) % 2) == 0) {
164 ap_cfg_getline(tmp_line, 100, cfg);
165 }
166 else {
167 cfg->getstr = NULL;
168 ap_cfg_getline(tmp_line, 100, cfg);
169 }
170 // Fuzzer logic end
171
172 unlink(filename);
173
174 // Cleanup
175 apr_pool_terminate();
176 }
177 }
178
179 // Cleanup all of the memory allocated by the fuzz headers.
180 af_gb_cleanup();
181 return 0;
182 }
183