generate_message.c 2.3 KB

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