1 /* Copyright (c) 2018-2021, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
6 * \brief Fuzzers for various string encoding/decoding operations
11 #include "lib/cc/torint.h"
12 #include "lib/ctime/di_ops.h"
13 #include "lib/encoding/binascii.h"
14 #include "lib/encoding/cstring.h"
15 #include "lib/encoding/kvline.h"
16 #include "lib/encoding/confline.h"
17 #include "lib/malloc/malloc.h"
18 #include "lib/log/escape.h"
19 #include "lib/log/util_bug.h"
20 #include "lib/intmath/muldiv.h"
22 #include "test/fuzz/fuzzing.h"
39 typedef struct chunk_t
{
44 #define chunk_free(ch) \
45 FREE_AND_NULL(chunk_t, chunk_free_, (ch))
50 chunk_t
*ch
= tor_malloc(sizeof(chunk_t
));
51 ch
->buf
= tor_malloc(len
);
56 chunk_free_(chunk_t
*ch
)
64 chunk_eq(const chunk_t
*a
, const chunk_t
*b
)
66 return a
->len
== b
->len
&& fast_memeq(a
->buf
, b
->buf
, a
->len
);
70 b16_dec(const chunk_t
*inp
)
72 chunk_t
*ch
= chunk_new(CEIL_DIV(inp
->len
, 2));
73 int r
= base16_decode((char *)ch
->buf
, ch
->len
, (char *)inp
->buf
, inp
->len
);
82 b16_enc(const chunk_t
*inp
)
84 chunk_t
*ch
= chunk_new(inp
->len
* 2 + 1);
85 base16_encode((char *)ch
->buf
, ch
->len
, (char*)inp
->buf
, inp
->len
);
90 b32_dec(const chunk_t
*inp
)
92 chunk_t
*ch
= chunk_new(inp
->len
);//XXXX
93 int r
= base32_decode((char *)ch
->buf
, ch
->len
, (char *)inp
->buf
, inp
->len
);
102 b32_enc(const chunk_t
*inp
)
104 chunk_t
*ch
= chunk_new(base32_encoded_size(inp
->len
));
105 base32_encode((char *)ch
->buf
, ch
->len
, (char*)inp
->buf
, inp
->len
);
106 ch
->len
= strlen((char *) ch
->buf
);
111 b64_dec(const chunk_t
*inp
)
113 chunk_t
*ch
= chunk_new(inp
->len
);//XXXX This could be shorter.
114 int r
= base64_decode((char *)ch
->buf
, ch
->len
, (char *)inp
->buf
, inp
->len
);
123 b64_enc(const chunk_t
*inp
)
125 chunk_t
*ch
= chunk_new(BASE64_BUFSIZE(inp
->len
));
126 base64_encode((char *)ch
->buf
, ch
->len
, (char *)inp
->buf
, inp
->len
, 0);
127 ch
->len
= strlen((char *) ch
->buf
);
132 c_dec(const chunk_t
*inp
)
134 char *s
= tor_memdup_nulterm(inp
->buf
, inp
->len
);
135 chunk_t
*ch
= tor_malloc(sizeof(chunk_t
));
137 (void) unescape_string(s
, &r
, &ch
->len
);
139 ch
->buf
= (uint8_t*) r
;
146 c_enc(const chunk_t
*inp
)
148 char *s
= tor_memdup_nulterm(inp
->buf
, inp
->len
);
149 chunk_t
*ch
= tor_malloc(sizeof(chunk_t
));
150 ch
->buf
= (uint8_t*)esc_for_log(s
);
152 ch
->len
= strlen((char*)ch
->buf
);
156 static int kv_flags
= 0;
157 static config_line_t
*
158 kv_dec(const chunk_t
*inp
)
160 char *s
= tor_memdup_nulterm(inp
->buf
, inp
->len
);
161 config_line_t
*res
= kvline_parse(s
, kv_flags
);
166 kv_enc(const config_line_t
*inp
)
168 char *s
= kvline_encode(inp
, kv_flags
);
171 chunk_t
*res
= tor_malloc(sizeof(chunk_t
));
172 res
->buf
= (uint8_t*)s
;
173 res
->len
= strlen(s
);
177 /* Given an encoder function, a decoder function, and a function to free
178 * the decoded object, check whether any string that successfully decoded
179 * will then survive an encode-decode-encode round-trip unchanged.
181 #define ENCODE_ROUNDTRIP(E,D,FREE) \
193 if (!chunk_eq(b,d)) { \
194 printf("Unequal chunks: %s\n", \
195 hex_str((char*)b->buf, b->len)); \
197 hex_str((char*)d->buf, d->len)); \
208 fuzz_main(const uint8_t *stdin_buf
, size_t data_size
)
213 chunk_t inp
= { (uint8_t*)stdin_buf
, data_size
};
214 chunk_t
*b
=NULL
,*d
=NULL
;
215 void *a
=NULL
,*c
=NULL
;
217 switch (stdin_buf
[0]) {
219 ENCODE_ROUNDTRIP(b16_enc
, b16_dec
, chunk_free_
);
222 ENCODE_ROUNDTRIP(b32_enc
, b32_dec
, chunk_free_
);
225 ENCODE_ROUNDTRIP(b64_enc
, b64_dec
, chunk_free_
);
228 ENCODE_ROUNDTRIP(c_enc
, c_dec
, chunk_free_
);
231 kv_flags
= KV_QUOTED
|KV_OMIT_KEYS
;
232 ENCODE_ROUNDTRIP(kv_enc
, kv_dec
, config_free_lines_
);
236 ENCODE_ROUNDTRIP(kv_enc
, kv_dec
, config_free_lines_
);
239 kv_flags
= KV_OMIT_VALS
;
240 ENCODE_ROUNDTRIP(kv_enc
, kv_dec
, config_free_lines_
);
243 kv_flags
= KV_QUOTED
;
244 ENCODE_ROUNDTRIP(kv_enc
, kv_dec
, config_free_lines_
);
247 kv_flags
= KV_QUOTED
|KV_OMIT_VALS
;
248 ENCODE_ROUNDTRIP(kv_enc
, kv_dec
, config_free_lines_
);