1 #include "hb-fuzzer.hh"
2
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include <assert.h>
7
8 #include "hb.h"
9
10 // Only allow ~5,000 set values between the two input sets.
11 // Arbitarily long input sets do not trigger any meaningful
12 // differences in behaviour so there's no benefit from allowing
13 // the fuzzer to create super large sets.
14 #define MAX_INPUT_SIZE 20000
15
16 enum set_operation_t : uint8_t
17 {
18 INTERSECT = 0,
19 UNION = 1,
20 SUBTRACT = 2,
21 SYMMETRIC_DIFFERENCE = 3
22 };
23
24 struct instructions_t
25 {
26 set_operation_t operation;
27 uint32_t first_set_size;
28 };
29
create_set(const uint32_t * value_array,int count)30 static hb_set_t *create_set (const uint32_t *value_array, int count)
31 {
32 hb_set_t *set = hb_set_create ();
33 for (int i = 0; i < count; i++)
34 hb_set_add (set, value_array[i]);
35 return set;
36 }
37
38
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)39 extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
40 {
41 alloc_state = size; /* see src/failing-alloc.c */
42
43 if (size < sizeof (instructions_t))
44 return 0;
45
46 if (size > MAX_INPUT_SIZE)
47 return 0;
48
49 #pragma GCC diagnostic push
50 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
51 const instructions_t &instructions = reinterpret_cast<const instructions_t &> (data);
52 #pragma GCC diagnostic pop
53 data += sizeof (instructions_t);
54 size -= sizeof (instructions_t);
55
56 const uint32_t *values = reinterpret_cast<const uint32_t *> (data);
57 size = size / sizeof (uint32_t);
58
59 if (size < instructions.first_set_size)
60 return 0;
61
62 hb_set_t *set_a = create_set (values, instructions.first_set_size);
63
64 values += instructions.first_set_size;
65 size -= instructions.first_set_size;
66 hb_set_t *set_b = create_set (values, size);
67
68 switch (instructions.operation)
69 {
70 case INTERSECT:
71 hb_set_intersect (set_a, set_b);
72 break;
73 case UNION:
74 hb_set_union (set_a, set_b);
75 break;
76 case SUBTRACT:
77 hb_set_subtract (set_a, set_b);
78 break;
79 case SYMMETRIC_DIFFERENCE:
80 hb_set_symmetric_difference (set_a, set_b);
81 break;
82 default:
83 break;
84 }
85
86 hb_set_destroy (set_a);
87 hb_set_destroy (set_b);
88
89 return 0;
90 }
91