diff --git a/src/hb-graphite2.cc b/src/hb-graphite2.cc index 9588fa4d6..40ac9061f 100644 --- a/src/hb-graphite2.cc +++ b/src/hb-graphite2.cc @@ -106,32 +106,6 @@ retry: return d; } -static void hb_graphite2_release_table(const void *data, const void *table_buffer) -{ - hb_graphite2_face_data_t *face_data = (hb_graphite2_face_data_t *) data; - hb_graphite2_tablelist_t *tlist = face_data->tlist; - - hb_graphite2_tablelist_t *prev = nullptr; - hb_graphite2_tablelist_t *curr = tlist; - while (curr) - { - if (hb_blob_get_data(curr->blob, nullptr) == table_buffer) - { - if (prev == nullptr) - face_data->tlist.cmpexch(tlist, curr->next); - else - prev->next = curr->next; - hb_blob_destroy(curr->blob); - free(curr); - break; - } - prev = curr; - curr = curr->next; - } -} - -static gr_face_ops hb_graphite2_face_ops = { sizeof(gr_face_ops), hb_graphite2_get_table, hb_graphite2_release_table }; - hb_graphite2_face_data_t * _hb_graphite2_shaper_face_data_create (hb_face_t *face) { @@ -150,7 +124,7 @@ _hb_graphite2_shaper_face_data_create (hb_face_t *face) return nullptr; data->face = face; - data->grface = gr_make_face_with_ops (data, &hb_graphite2_face_ops, gr_face_preloadAll); + data->grface = gr_make_face (data, &hb_graphite2_get_table, gr_face_preloadAll); if (unlikely (!data->grface)) { free (data); diff --git a/src/hb-iter.hh b/src/hb-iter.hh index 5df433375..c820c8fb4 100644 --- a/src/hb-iter.hh +++ b/src/hb-iter.hh @@ -480,7 +480,7 @@ struct hb_reduce_t template + typename AccuT = hb_remove_reference> AccuT operator () (Iter it) { diff --git a/src/hb-open-file.hh b/src/hb-open-file.hh index 5318c7fca..f3f4dc07f 100644 --- a/src/hb-open-file.hh +++ b/src/hb-open-file.hh @@ -141,14 +141,15 @@ typedef struct OffsetTable TableRecord &rec = tables.arrayZ[i]; hb_blob_t *blob = items[i].blob; rec.tag = items[i].tag; - rec.length = hb_blob_get_length (blob); + rec.length = blob->length; rec.offset.serialize (c, this); /* Allocate room for the table and copy it. */ char *start = (char *) c->allocate_size (rec.length); - if (unlikely (!start)) {return false;} + if (unlikely (!start)) return false; - memcpy (start, hb_blob_get_data (blob, nullptr), rec.length); + if (likely (rec.length)) + memcpy (start, blob->data, rec.length); /* 4-byte alignment. */ c->align (4); diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh index ac75bd96a..d79b549e6 100644 --- a/src/hb-ot-cmap-table.hh +++ b/src/hb-ot-cmap-table.hh @@ -878,7 +878,7 @@ struct cmap cmap_plan->has_ms_bmp = find_subtable (3, 1); cmap_plan->has_ms_ucs4 = find_subtable (3, 10); cmap_plan->num_enc_records = cmap_plan->has_unicode_bmp + cmap_plan->has_unicode_ucs4 + cmap_plan->has_ms_bmp + cmap_plan->has_ms_ucs4; - + if (unlikely (!CmapSubtableFormat4::create_sub_table_plan (plan, &cmap_plan->format4_segments))) return false; @@ -979,6 +979,14 @@ struct cmap if (unlikely (!format12.serialize (&c, cmap_subset_plan.format12_groups))) return false; } + else + { + // FIXME: Merge this with above or, remove and tweak #final_size + // and rebase all the tests expectations + HBUINT32 empty; + empty = 0; + for (unsigned int i = 0; i < 4; ++i) c.copy (empty); + } c.end_serialize (); diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index f4be42c1d..5c219802c 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -733,7 +733,7 @@ struct PairPosFormat1 + hb_zip (this+coverage, pairSet) | hb_filter (*glyphs, hb_first) | hb_map (hb_second) - | hb_map ([=] (const OffsetTo &_) + | hb_map ([glyphs, this] (const OffsetTo &_) { return (this+_).intersects (glyphs, valueFormat); }) | hb_any ; diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index 6b33c17b6..e244da199 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -179,7 +179,7 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face, unsigned max_glyph = + hb_iter (all_gids_to_retain) - | hb_reduce (hb_max, 0) + | hb_reduce (hb_max, 0u) ; *num_glyphs = max_glyph + 1; } diff --git a/src/hb-unicode.cc b/src/hb-unicode.cc index e2deaa240..9a8184063 100644 --- a/src/hb-unicode.cc +++ b/src/hb-unicode.cc @@ -126,8 +126,12 @@ hb_unicode_decompose_compatibility_nil (hb_unicode_funcs_t *ufuncs HB_UNUSED } #endif -extern "C" hb_unicode_funcs_t *hb_glib_get_unicode_funcs (); -extern "C" hb_unicode_funcs_t *hb_icu_get_unicode_funcs (); +#if !defined(HB_NO_UNICODE_FUNCS) && defined(HAVE_GLIB) +#include "hb-glib.h" +#endif +#if !defined(HB_NO_UNICODE_FUNCS) && defined(HAVE_ICU) && defined(HAVE_ICU_BUILTIN) +#include "hb-icu.h" +#endif hb_unicode_funcs_t * hb_unicode_funcs_get_default () diff --git a/src/hb-uniscribe.cc b/src/hb-uniscribe.cc index 5c7ff8744..b113ed4cf 100644 --- a/src/hb-uniscribe.cc +++ b/src/hb-uniscribe.cc @@ -245,8 +245,9 @@ struct hb_uniscribe_shaper_funcs_t } }; - +#if HB_USE_ATEXIT static void free_static_uniscribe_shaper_funcs (); +#endif static struct hb_uniscribe_shaper_funcs_lazy_loader_t : hb_lazy_loader_t diff --git a/src/hb.hh b/src/hb.hh index bee39cd46..f8b5e70a8 100644 --- a/src/hb.hh +++ b/src/hb.hh @@ -98,6 +98,7 @@ #ifndef HB_NO_PRAGMA_GCC_DIAGNOSTIC_WARNING #pragma GCC diagnostic warning "-Wbuiltin-macro-redefined" #pragma GCC diagnostic warning "-Wdeprecated" +#pragma GCC diagnostic warning "-Wdeprecated-declarations" #pragma GCC diagnostic warning "-Wdisabled-optimization" #pragma GCC diagnostic warning "-Wdouble-promotion" #pragma GCC diagnostic warning "-Wformat=2" diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5738978499624960 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5738978499624960 new file mode 100644 index 000000000..0264a15fb Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5738978499624960 differ diff --git a/test/fuzzing/hb-subset-fuzzer.cc b/test/fuzzing/hb-subset-fuzzer.cc index 73c95b2a6..428765ea3 100644 --- a/test/fuzzing/hb-subset-fuzzer.cc +++ b/test/fuzzing/hb-subset-fuzzer.cc @@ -3,6 +3,7 @@ #include #include #include +#include #include "hb-subset.h" @@ -32,6 +33,19 @@ trySubset (hb_face_t *face, } hb_face_t *result = hb_subset (face, input); + { + hb_blob_t *blob = hb_face_reference_blob (result); + unsigned int length; + const char *data = hb_blob_get_data (blob, &length); + + // Something not optimizable just to access all the blob data + unsigned int bytes_count = 0; + for (unsigned int i = 0; i < length; ++i) + if (data[i]) ++bytes_count; + assert (bytes_count || !length); + + hb_blob_destroy (blob); + } hb_face_destroy (result); hb_subset_input_destroy (input); diff --git a/test/fuzzing/run-subset-fuzzer-tests.py b/test/fuzzing/run-subset-fuzzer-tests.py index 3ac22889e..d431e10a3 100755 --- a/test/fuzzing/run-subset-fuzzer-tests.py +++ b/test/fuzzing/run-subset-fuzzer-tests.py @@ -33,7 +33,7 @@ def cmd(command): def timeout(p, is_killed): is_killed['value'] = True p.kill() - timer = threading.Timer (2, timeout, [p, is_killed]) + timer = threading.Timer (6, timeout, [p, is_killed]) try: timer.start() @@ -82,6 +82,8 @@ def run_dir (parent_path): global fails for file in os.listdir (parent_path): path = os.path.join(parent_path, file) + # TODO: Run on all the fonts not just subset related ones + if "subset" not in path: continue print ("running subset fuzzer against %s" % path) if valgrind: @@ -91,7 +93,7 @@ def run_dir (parent_path): if 'error' in text: returncode = 1 - if not valgrind and text.strip (): + if (not valgrind or returncode) and text.strip (): print (text) if returncode != 0: @@ -100,8 +102,7 @@ def run_dir (parent_path): run_dir (os.path.join (srcdir, "..", "subset", "data", "fonts")) -# TODO running these tests very slow tests. Fix and re-enable -#run_dir (os.path.join (srcdir, "fonts")) +run_dir (os.path.join (srcdir, "fonts")) if fails: print ("%i subset fuzzer related tests failed." % fails) diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.default.retain-all-codepoint.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.retain-all-codepoint.ttf new file mode 100644 index 000000000..5de8d8981 Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.default.retain-all-codepoint.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.retain-all-codepoint.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.retain-all-codepoint.ttf new file mode 100644 index 000000000..e3c072760 Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints-retain-gids.retain-all-codepoint.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.retain-all-codepoint.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.retain-all-codepoint.ttf new file mode 100644 index 000000000..6425ecfd1 Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.drop-hints.retain-all-codepoint.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.retain-all-codepoint.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.retain-all-codepoint.ttf new file mode 100644 index 000000000..fbb8c33ac Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.name-ids.retain-all-codepoint.ttf differ diff --git a/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.retain-all-codepoint.ttf b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.retain-all-codepoint.ttf new file mode 100644 index 000000000..cc2805a01 Binary files /dev/null and b/test/subset/data/expected/basics/Comfortaa-Regular-new.retain-gids.retain-all-codepoint.ttf differ diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.default.retain-all-codepoint.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.default.retain-all-codepoint.ttf new file mode 100644 index 000000000..12d92081b Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.default.retain-all-codepoint.ttf differ diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints-retain-gids.retain-all-codepoint.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints-retain-gids.retain-all-codepoint.ttf new file mode 100644 index 000000000..52dc47457 Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints-retain-gids.retain-all-codepoint.ttf differ diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints.retain-all-codepoint.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints.retain-all-codepoint.ttf new file mode 100644 index 000000000..52dc47457 Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.drop-hints.retain-all-codepoint.ttf differ diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.name-ids.retain-all-codepoint.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.name-ids.retain-all-codepoint.ttf new file mode 100644 index 000000000..12d92081b Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.name-ids.retain-all-codepoint.ttf differ diff --git a/test/subset/data/expected/basics/Roboto-Regular.abc.retain-gids.retain-all-codepoint.ttf b/test/subset/data/expected/basics/Roboto-Regular.abc.retain-gids.retain-all-codepoint.ttf new file mode 100644 index 000000000..12d92081b Binary files /dev/null and b/test/subset/data/expected/basics/Roboto-Regular.abc.retain-gids.retain-all-codepoint.ttf differ diff --git a/test/subset/data/tests/basics.tests b/test/subset/data/tests/basics.tests index c310722b0..772f33cc3 100644 --- a/test/subset/data/tests/basics.tests +++ b/test/subset/data/tests/basics.tests @@ -15,3 +15,4 @@ b c ac a +* diff --git a/test/subset/subset_test_suite.py b/test/subset/subset_test_suite.py index ad438ee2b..47664d0b6 100644 --- a/test/subset/subset_test_suite.py +++ b/test/subset/subset_test_suite.py @@ -12,7 +12,10 @@ class Test: self.subset = subset def unicodes(self): - return ",".join("%X" % ord(c) for (i, c) in enumerate(self.subset)) + if self.subset == '*': + return self.subset[0] + else: + return ",".join("%X" % ord(c) for (i, c) in enumerate(self.subset)) def get_profile_flags(self): with io.open(self.profile_path, mode="r", encoding="utf-8") as f: @@ -23,7 +26,12 @@ class Test: font_base_name_parts = os.path.splitext(font_base_name) profile_name = os.path.splitext(os.path.basename(self.profile_path))[0] - return "%s.%s.%s%s" % (font_base_name_parts[0], + if self.unicodes() == "*": + return "%s.%s.retain-all-codepoint%s" % (font_base_name_parts[0], + profile_name, + font_base_name_parts[1]) + else: + return "%s.%s.%s%s" % (font_base_name_parts[0], profile_name, self.unicodes(), font_base_name_parts[1]) @@ -39,9 +47,9 @@ class SubsetTestSuite: def __init__(self, test_path, definition): self.test_path = test_path - self.fonts = set() - self.profiles = set() - self.subsets = set() + self.fonts = [] + self.profiles = [] + self.subsets = [] self._parse(definition) def get_output_directory(self): @@ -87,6 +95,6 @@ class SubsetTestSuite: if line in destinations: current_destination = destinations[line] elif current_destination is not None: - current_destination.add(line) + current_destination.append(line) else: raise Exception("Failed to parse test suite file.") diff --git a/util/hb-subset.cc b/util/hb-subset.cc index 4b7af8e9a..6d87c563c 100644 --- a/util/hb-subset.cc +++ b/util/hb-subset.cc @@ -53,6 +53,13 @@ struct subset_consumer_t { // TODO(Q1) does this only get called with at least 1 codepoint? hb_set_t *codepoints = hb_subset_input_unicode_set (input); + if (0 == strcmp (text, "*")) + { + hb_face_t *face = hb_font_get_face (font); + hb_face_collect_unicodes (face, codepoints); + return; + } + gchar *c = (gchar *)text; do { gunichar cp = g_utf8_get_char(c); diff --git a/util/options.cc b/util/options.cc index 4e6ca57e7..42dfa956a 100644 --- a/util/options.cc +++ b/util/options.cc @@ -349,28 +349,36 @@ parse_unicodes (const char *name G_GNUC_UNUSED, } GString *gs = g_string_new (nullptr); - char *s = (char *) arg; - char *p; - - while (s && *s) + if (0 == strcmp (arg, "*")) + { + g_string_append_c (gs, '*'); + } + else { - while (*s && strchr (DELIMITERS, *s)) - s++; - if (!*s) - break; - errno = 0; - hb_codepoint_t u = strtoul (s, &p, 16); - if (errno || s == p) + char *s = (char *) arg; + char *p; + + while (s && *s) { - g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, - "Failed parsing Unicode values at: '%s'", s); - return false; + while (*s && strchr (DELIMITERS, *s)) + s++; + if (!*s) + break; + + errno = 0; + hb_codepoint_t u = strtoul (s, &p, 16); + if (errno || s == p) + { + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "Failed parsing Unicode values at: '%s'", s); + return false; + } + + g_string_append_unichar (gs, u); + + s = p; } - - g_string_append_unichar (gs, u); - - s = p; } text_opts->text_len = gs->len;