mirror of https://github.com/grpc/grpc.git
The C based gRPC (C++, Python, Ruby, Objective-C, PHP, C#)
https://grpc.io/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
101 lines
2.5 KiB
101 lines
2.5 KiB
/* 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; |
|
} |
|
|
|
|