| #include "hb-fuzzer.hh" |
| |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <string.h> |
| |
| #include "hb-subset.h" |
| |
| extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size) |
| { |
| alloc_state = _fuzzing_alloc_state (data, size); |
| |
| hb_blob_t *blob = hb_blob_create ((const char *) data, size, |
| HB_MEMORY_MODE_READONLY, nullptr, nullptr); |
| hb_face_t *face = hb_face_create (blob, 0); |
| |
| hb_subset_depend_t *depend = hb_subset_depend_from_face_or_fail (face); |
| |
| if (depend) |
| { |
| // Iterate through dependency data and exercise full API |
| unsigned int num_glyphs = hb_face_get_glyph_count (face); |
| hb_set_t *temp_set = hb_set_create (); |
| |
| for (unsigned int gid = 0; gid < num_glyphs && gid < 100; gid++) |
| { |
| // Iterate through up to 10 entries per glyph |
| unsigned int total = hb_subset_depend_lookup_glyph (depend, gid, 0, nullptr, nullptr); |
| unsigned int limit = total < 10u ? total : 10u; |
| for (unsigned int index = 0; index < limit; index++) |
| { |
| hb_subset_depend_entry_t entry; |
| unsigned int count = 1; |
| hb_subset_depend_lookup_glyph (depend, gid, index, &count, &entry); |
| // Access basic edge data |
| (void) entry.table_tag; |
| (void) entry.dependent; |
| (void) entry.layout_tag; |
| (void) entry.flags; |
| |
| // If this edge has a ligature set, retrieve and check it |
| if (entry.ligature_set_index != HB_CODEPOINT_INVALID) |
| { |
| if (hb_subset_depend_lookup_set (depend, entry.ligature_set_index, temp_set)) |
| { |
| unsigned pop = hb_set_get_population (temp_set); |
| // Ligature sets should be non-empty |
| if (pop == 0) |
| fprintf (stderr, "Warning: Empty ligature set at index %u\n", entry.ligature_set_index); |
| } |
| } |
| |
| // If this edge has a context set, retrieve and check it |
| if (entry.context_set_index != HB_CODEPOINT_INVALID) |
| { |
| if (hb_subset_depend_lookup_set (depend, entry.context_set_index, temp_set)) |
| { |
| unsigned pop = hb_set_get_population (temp_set); |
| // Context sets should be non-empty |
| if (pop == 0) |
| fprintf (stderr, "Warning: Empty context set at index %u\n", entry.context_set_index); |
| |
| // Check for nested context sets (indirect references with 0x80000000 bit) |
| hb_codepoint_t elem = HB_SET_VALUE_INVALID; |
| while (hb_set_next (temp_set, &elem)) |
| { |
| if (elem >= 0x80000000) |
| { |
| // Indirect reference - retrieve the nested set |
| hb_codepoint_t nested_idx = elem & 0x7FFFFFFF; |
| hb_set_t *nested_set = hb_set_create (); |
| if (hb_subset_depend_lookup_set (depend, nested_idx, nested_set)) |
| { |
| unsigned nested_pop = hb_set_get_population (nested_set); |
| // Nested sets should also be non-empty |
| if (nested_pop == 0) |
| fprintf (stderr, "Warning: Empty nested context set at index %u\n", nested_idx); |
| } |
| hb_set_destroy (nested_set); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| hb_set_destroy (temp_set); |
| hb_subset_depend_destroy (depend); |
| } |
| |
| hb_face_destroy (face); |
| hb_blob_destroy (blob); |
| |
| return 0; |
| } |