hb-repacker-fuzzer.cc 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. #include "hb-fuzzer.hh"
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <assert.h>
  6. #include "hb-subset-repacker.h"
  7. typedef struct
  8. {
  9. uint16_t parent;
  10. uint16_t child;
  11. uint16_t position;
  12. uint8_t width;
  13. } link_t;
  14. /* The fuzzer seed contains a serialized representation of a object graph which forms
  15. * the input graph to the repacker call. The binary format is:
  16. *
  17. * table tag: 4 bytes
  18. * number of objects: 2 bytes
  19. * objects[number of objects]:
  20. * blob size: 2 bytes
  21. * blob: blob size bytes
  22. * num of real links: 2 bytes
  23. * links[number of real links]: link_t struct
  24. *
  25. * TODO(garretrieger): add optional virtual links
  26. */
  27. template <typename T>
  28. bool read(const uint8_t** data, size_t* size, T* out)
  29. {
  30. if (*size < sizeof (T)) return false;
  31. memcpy(out, *data, sizeof (T));
  32. *data += sizeof (T);
  33. *size -= sizeof (T);
  34. return true;
  35. }
  36. void cleanup (hb_object_t* objects, uint16_t num_objects)
  37. {
  38. for (uint32_t i = 0; i < num_objects; i++)
  39. {
  40. free (objects[i].head);
  41. free (objects[i].real_links);
  42. }
  43. }
  44. void add_links_to_objects (hb_object_t* objects, uint16_t num_objects,
  45. link_t* links, uint16_t num_links)
  46. {
  47. unsigned* link_count = (unsigned*) calloc (num_objects, sizeof (unsigned));
  48. for (uint32_t i = 0; i < num_links; i++)
  49. {
  50. uint16_t parent_idx = links[i].parent;
  51. link_count[parent_idx]++;
  52. }
  53. for (uint32_t i = 0; i < num_objects; i++)
  54. {
  55. objects[i].num_real_links = link_count[i];
  56. objects[i].real_links = (hb_link_t*) calloc (link_count[i], sizeof (hb_link_t));
  57. objects[i].num_virtual_links = 0;
  58. objects[i].virtual_links = nullptr;
  59. }
  60. for (uint32_t i = 0; i < num_links; i++)
  61. {
  62. uint16_t parent_idx = links[i].parent;
  63. uint16_t child_idx = links[i].child + 1; // All indices are shifted by 1 by the null object.
  64. hb_link_t* link = &(objects[parent_idx].real_links[link_count[parent_idx] - 1]);
  65. link->width = links[i].width;
  66. link->position = links[i].position;
  67. link->objidx = child_idx;
  68. link_count[parent_idx]--;
  69. }
  70. free (link_count);
  71. }
  72. extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
  73. {
  74. // TODO(garretrieger): move graph validity checks into repacker graph creation.
  75. alloc_state = _fuzzing_alloc_state (data, size);
  76. uint16_t num_objects = 0;
  77. hb_object_t* objects = nullptr;
  78. uint16_t num_real_links = 0;
  79. link_t* links = nullptr;
  80. hb_tag_t table_tag;
  81. if (!read<hb_tag_t> (&data, &size, &table_tag)) goto end;
  82. if (!read<uint16_t> (&data, &size, &num_objects)) goto end;
  83. objects = (hb_object_t*) calloc (num_objects, sizeof (hb_object_t));
  84. for (uint32_t i = 0; i < num_objects; i++)
  85. {
  86. uint16_t blob_size;
  87. if (!read<uint16_t> (&data, &size, &blob_size)) goto end;
  88. if (size < blob_size) goto end;
  89. char* copy = (char*) calloc (1, blob_size);
  90. memcpy (copy, data, blob_size);
  91. objects[i].head = (char*) copy;
  92. objects[i].tail = (char*) (copy + blob_size);
  93. size -= blob_size;
  94. data += blob_size;
  95. }
  96. if (!read<uint16_t> (&data, &size, &num_real_links)) goto end;
  97. links = (link_t*) calloc (num_real_links, sizeof (link_t));
  98. for (uint32_t i = 0; i < num_real_links; i++)
  99. {
  100. if (!read<link_t> (&data, &size, &links[i])) goto end;
  101. if (links[i].parent >= num_objects)
  102. goto end;
  103. }
  104. add_links_to_objects (objects, num_objects,
  105. links, num_real_links);
  106. hb_blob_destroy (hb_subset_repack_or_fail (table_tag,
  107. objects,
  108. num_objects));
  109. end:
  110. if (objects)
  111. {
  112. cleanup (objects, num_objects);
  113. free (objects);
  114. }
  115. free (links);
  116. return 0;
  117. }