Skip to content
Snippets Groups Projects
Commit 6448f5d4 authored by Petteri Aimonen's avatar Petteri Aimonen
Browse files

Add random message generator to help with fuzz testing

parent be9c9bb5
No related branches found
No related tags found
No related merge requests found
......@@ -36,4 +36,8 @@ fuzzstub = malloc_env.Program(["fuzzstub.c",
"$COMMON/pb_common_with_malloc.o",
"$COMMON/malloc_wrappers.o"])
generate_message = malloc_env.Program(["generate_message.c",
"alltypes_static.pb.c",
"$COMMON/pb_encode.o",
"$COMMON/pb_common.o"])
/* Generates a random, valid protobuf message. Useful to seed
* external fuzzers such as afl-fuzz.
*/
#include <pb_encode.h>
#include <pb_common.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <time.h>
#include "alltypes_static.pb.h"
static uint64_t random_seed;
/* Uses xorshift64 here instead of rand() for both speed and
* reproducibility across platforms. */
static uint32_t rand_word()
{
random_seed ^= random_seed >> 12;
random_seed ^= random_seed << 25;
random_seed ^= random_seed >> 27;
return random_seed * 2685821657736338717ULL;
}
/* Fills a buffer with random data. */
static void rand_fill(uint8_t *buf, size_t count)
{
while (count--)
{
*buf++ = rand_word() & 0xff;
}
}
/* Check that size/count fields do not exceed their max size.
* Otherwise we would have to loop pretty long in generate_message().
* Note that there may still be a few encoding errors from submessages.
*/
static void limit_sizes(alltypes_static_AllTypes *msg)
{
pb_field_iter_t iter;
pb_field_iter_begin(&iter, alltypes_static_AllTypes_fields, msg);
while (pb_field_iter_next(&iter))
{
if (PB_LTYPE(iter.pos->type) == PB_LTYPE_BYTES)
{
((pb_bytes_array_t*)iter.pData)->size %= iter.pos->data_size - PB_BYTES_ARRAY_T_ALLOCSIZE(0);
}
if (PB_HTYPE(iter.pos->type) == PB_HTYPE_REPEATED)
{
*((pb_size_t*)iter.pSize) %= iter.pos->array_size;
}
if (PB_HTYPE(iter.pos->type) == PB_HTYPE_ONEOF)
{
/* Set the oneof to this message type with 50% chance. */
if (rand_word() & 1)
{
*((pb_size_t*)iter.pSize) = iter.pos->tag;
}
}
}
}
static void generate_message()
{
alltypes_static_AllTypes msg;
uint8_t buf[8192];
pb_ostream_t stream = {0};
do {
if (stream.errmsg)
fprintf(stderr, "Encoder error: %s\n", stream.errmsg);
stream = pb_ostream_from_buffer(buf, sizeof(buf));
rand_fill((void*)&msg, sizeof(msg));
limit_sizes(&msg);
} while (!pb_encode(&stream, alltypes_static_AllTypes_fields, &msg));
fwrite(buf, 1, stream.bytes_written, stdout);
}
int main(int argc, char **argv)
{
if (argc > 1)
{
random_seed = atol(argv[1]);
}
else
{
random_seed = time(NULL);
}
fprintf(stderr, "Random seed: %llu\n", (long long unsigned)random_seed);
generate_message();
return 0;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment