Line data Source code
1 : /* Generates a random, valid protobuf message. Useful to seed 2 : * external fuzzers such as afl-fuzz. 3 : */ 4 : 5 : #include <pb_encode.h> 6 : #include <pb_common.h> 7 : #include <stdio.h> 8 : #include <stdlib.h> 9 : #include <string.h> 10 : #include <assert.h> 11 : #include "alltypes_static.pb.h" 12 : #include "random_data.h" 13 : 14 : #ifndef FUZZTEST_BUFSIZE 15 : #define FUZZTEST_BUFSIZE 4096 16 : #endif 17 : 18 : /* Check that size/count fields do not exceed their max size. 19 : * Otherwise we would have to loop pretty long in generate_message(). 20 : * Note that there may still be a few encoding errors from submessages. 21 : */ 22 25 : static void limit_sizes(alltypes_static_AllTypes *msg) 23 : { 24 : pb_field_iter_t iter; 25 25 : pb_field_iter_begin(&iter, alltypes_static_AllTypes_fields, msg); 26 1700 : while (pb_field_iter_next(&iter)) 27 : { 28 1675 : if (PB_LTYPE(iter.type) == PB_LTYPE_BYTES) 29 : { 30 75 : ((pb_bytes_array_t*)iter.pData)->size %= iter.data_size - PB_BYTES_ARRAY_T_ALLOCSIZE(0); 31 : } 32 : 33 1675 : if (PB_HTYPE(iter.type) == PB_HTYPE_REPEATED) 34 : { 35 525 : *((pb_size_t*)iter.pSize) %= iter.array_size; 36 : } 37 : 38 1675 : if (PB_HTYPE(iter.type) == PB_HTYPE_ONEOF) 39 : { 40 : /* Set the oneof to this message type with 50% chance. */ 41 75 : if (rand_word() & 1) 42 : { 43 34 : *((pb_size_t*)iter.pSize) = iter.tag; 44 : } 45 : } 46 : } 47 25 : } 48 : 49 1 : static void generate_message() 50 : { 51 : alltypes_static_AllTypes msg; 52 1 : alltypes_static_TestExtension extmsg = alltypes_static_TestExtension_init_zero; 53 1 : pb_extension_t ext = pb_extension_init_zero; 54 : 55 : static uint8_t buf[FUZZTEST_BUFSIZE]; 56 1 : pb_ostream_t stream = {0}; 57 : 58 : do { 59 25 : rand_fill((void*)&msg, sizeof(msg)); 60 25 : limit_sizes(&msg); 61 : 62 25 : rand_fill((void*)&extmsg, sizeof(extmsg)); 63 25 : ext.type = &alltypes_static_TestExtension_testextension; 64 25 : ext.dest = &extmsg; 65 25 : ext.next = NULL; 66 25 : msg.extensions = &ext; 67 : 68 25 : stream = pb_ostream_from_buffer(buf, sizeof(buf)); 69 25 : } while (!pb_encode(&stream, alltypes_static_AllTypes_fields, &msg)); 70 : 71 1 : fwrite(buf, 1, stream.bytes_written, stdout); 72 1 : } 73 : 74 1 : int main(int argc, char **argv) 75 : { 76 1 : if (argc < 2) 77 : { 78 0 : fprintf(stderr, "Usage: generate_message <seed>\n"); 79 0 : return 1; 80 : } 81 : 82 1 : random_set_seed(atol(argv[1])); 83 : 84 1 : generate_message(); 85 : 86 1 : return 0; 87 : } 88 :