1*c8d645caSAndroid Build Coastguard Worker /* Generates a random, valid protobuf message. Useful to seed
2*c8d645caSAndroid Build Coastguard Worker * external fuzzers such as afl-fuzz.
3*c8d645caSAndroid Build Coastguard Worker */
4*c8d645caSAndroid Build Coastguard Worker
5*c8d645caSAndroid Build Coastguard Worker #include <pb_encode.h>
6*c8d645caSAndroid Build Coastguard Worker #include <pb_common.h>
7*c8d645caSAndroid Build Coastguard Worker #include <stdio.h>
8*c8d645caSAndroid Build Coastguard Worker #include <stdlib.h>
9*c8d645caSAndroid Build Coastguard Worker #include <string.h>
10*c8d645caSAndroid Build Coastguard Worker #include <assert.h>
11*c8d645caSAndroid Build Coastguard Worker #include <time.h>
12*c8d645caSAndroid Build Coastguard Worker #include "alltypes_static.pb.h"
13*c8d645caSAndroid Build Coastguard Worker
14*c8d645caSAndroid Build Coastguard Worker static uint64_t random_seed;
15*c8d645caSAndroid Build Coastguard Worker
16*c8d645caSAndroid Build Coastguard Worker /* Uses xorshift64 here instead of rand() for both speed and
17*c8d645caSAndroid Build Coastguard Worker * reproducibility across platforms. */
rand_word()18*c8d645caSAndroid Build Coastguard Worker static uint32_t rand_word()
19*c8d645caSAndroid Build Coastguard Worker {
20*c8d645caSAndroid Build Coastguard Worker random_seed ^= random_seed >> 12;
21*c8d645caSAndroid Build Coastguard Worker random_seed ^= random_seed << 25;
22*c8d645caSAndroid Build Coastguard Worker random_seed ^= random_seed >> 27;
23*c8d645caSAndroid Build Coastguard Worker return random_seed * 2685821657736338717ULL;
24*c8d645caSAndroid Build Coastguard Worker }
25*c8d645caSAndroid Build Coastguard Worker
26*c8d645caSAndroid Build Coastguard Worker /* Fills a buffer with random data. */
rand_fill(uint8_t * buf,size_t count)27*c8d645caSAndroid Build Coastguard Worker static void rand_fill(uint8_t *buf, size_t count)
28*c8d645caSAndroid Build Coastguard Worker {
29*c8d645caSAndroid Build Coastguard Worker while (count--)
30*c8d645caSAndroid Build Coastguard Worker {
31*c8d645caSAndroid Build Coastguard Worker *buf++ = rand_word() & 0xff;
32*c8d645caSAndroid Build Coastguard Worker }
33*c8d645caSAndroid Build Coastguard Worker }
34*c8d645caSAndroid Build Coastguard Worker
35*c8d645caSAndroid Build Coastguard Worker /* Check that size/count fields do not exceed their max size.
36*c8d645caSAndroid Build Coastguard Worker * Otherwise we would have to loop pretty long in generate_message().
37*c8d645caSAndroid Build Coastguard Worker * Note that there may still be a few encoding errors from submessages.
38*c8d645caSAndroid Build Coastguard Worker */
limit_sizes(alltypes_static_AllTypes * msg)39*c8d645caSAndroid Build Coastguard Worker static void limit_sizes(alltypes_static_AllTypes *msg)
40*c8d645caSAndroid Build Coastguard Worker {
41*c8d645caSAndroid Build Coastguard Worker pb_field_iter_t iter;
42*c8d645caSAndroid Build Coastguard Worker pb_field_iter_begin(&iter, alltypes_static_AllTypes_fields, msg);
43*c8d645caSAndroid Build Coastguard Worker while (pb_field_iter_next(&iter))
44*c8d645caSAndroid Build Coastguard Worker {
45*c8d645caSAndroid Build Coastguard Worker if (PB_LTYPE(iter.pos->type) == PB_LTYPE_BYTES)
46*c8d645caSAndroid Build Coastguard Worker {
47*c8d645caSAndroid Build Coastguard Worker ((pb_bytes_array_t*)iter.pData)->size %= iter.pos->data_size - PB_BYTES_ARRAY_T_ALLOCSIZE(0);
48*c8d645caSAndroid Build Coastguard Worker }
49*c8d645caSAndroid Build Coastguard Worker
50*c8d645caSAndroid Build Coastguard Worker if (PB_HTYPE(iter.pos->type) == PB_HTYPE_REPEATED)
51*c8d645caSAndroid Build Coastguard Worker {
52*c8d645caSAndroid Build Coastguard Worker *((pb_size_t*)iter.pSize) %= iter.pos->array_size;
53*c8d645caSAndroid Build Coastguard Worker }
54*c8d645caSAndroid Build Coastguard Worker
55*c8d645caSAndroid Build Coastguard Worker if (PB_HTYPE(iter.pos->type) == PB_HTYPE_ONEOF)
56*c8d645caSAndroid Build Coastguard Worker {
57*c8d645caSAndroid Build Coastguard Worker /* Set the oneof to this message type with 50% chance. */
58*c8d645caSAndroid Build Coastguard Worker if (rand_word() & 1)
59*c8d645caSAndroid Build Coastguard Worker {
60*c8d645caSAndroid Build Coastguard Worker *((pb_size_t*)iter.pSize) = iter.pos->tag;
61*c8d645caSAndroid Build Coastguard Worker }
62*c8d645caSAndroid Build Coastguard Worker }
63*c8d645caSAndroid Build Coastguard Worker }
64*c8d645caSAndroid Build Coastguard Worker }
65*c8d645caSAndroid Build Coastguard Worker
generate_message()66*c8d645caSAndroid Build Coastguard Worker static void generate_message()
67*c8d645caSAndroid Build Coastguard Worker {
68*c8d645caSAndroid Build Coastguard Worker alltypes_static_AllTypes msg;
69*c8d645caSAndroid Build Coastguard Worker uint8_t buf[8192];
70*c8d645caSAndroid Build Coastguard Worker pb_ostream_t stream = {0};
71*c8d645caSAndroid Build Coastguard Worker
72*c8d645caSAndroid Build Coastguard Worker do {
73*c8d645caSAndroid Build Coastguard Worker if (stream.errmsg)
74*c8d645caSAndroid Build Coastguard Worker fprintf(stderr, "Encoder error: %s\n", stream.errmsg);
75*c8d645caSAndroid Build Coastguard Worker
76*c8d645caSAndroid Build Coastguard Worker stream = pb_ostream_from_buffer(buf, sizeof(buf));
77*c8d645caSAndroid Build Coastguard Worker rand_fill((void*)&msg, sizeof(msg));
78*c8d645caSAndroid Build Coastguard Worker limit_sizes(&msg);
79*c8d645caSAndroid Build Coastguard Worker } while (!pb_encode(&stream, alltypes_static_AllTypes_fields, &msg));
80*c8d645caSAndroid Build Coastguard Worker
81*c8d645caSAndroid Build Coastguard Worker fwrite(buf, 1, stream.bytes_written, stdout);
82*c8d645caSAndroid Build Coastguard Worker }
83*c8d645caSAndroid Build Coastguard Worker
main(int argc,char ** argv)84*c8d645caSAndroid Build Coastguard Worker int main(int argc, char **argv)
85*c8d645caSAndroid Build Coastguard Worker {
86*c8d645caSAndroid Build Coastguard Worker if (argc > 1)
87*c8d645caSAndroid Build Coastguard Worker {
88*c8d645caSAndroid Build Coastguard Worker random_seed = atol(argv[1]);
89*c8d645caSAndroid Build Coastguard Worker }
90*c8d645caSAndroid Build Coastguard Worker else
91*c8d645caSAndroid Build Coastguard Worker {
92*c8d645caSAndroid Build Coastguard Worker random_seed = time(NULL);
93*c8d645caSAndroid Build Coastguard Worker }
94*c8d645caSAndroid Build Coastguard Worker
95*c8d645caSAndroid Build Coastguard Worker fprintf(stderr, "Random seed: %llu\n", (long long unsigned)random_seed);
96*c8d645caSAndroid Build Coastguard Worker
97*c8d645caSAndroid Build Coastguard Worker generate_message();
98*c8d645caSAndroid Build Coastguard Worker
99*c8d645caSAndroid Build Coastguard Worker return 0;
100*c8d645caSAndroid Build Coastguard Worker }
101*c8d645caSAndroid Build Coastguard Worker
102