CMakeLists.txt | 2 src/Makefile.am | 18 - src/dump-emoji.cc | 141 ++++++++++ src/gen-use-table.py | 105 +++---- src/hb-ot-color-cbdt-table.hh | 71 +++++ src/hb-ot-color-sbix-table.hh | 79 +++-- src/hb-ot-color-svg-table.hh | 56 ++- src/hb-ot-hdmx-table.hh | 1 src/hb-subset-glyf.cc | 6 src/hb-subset.cc | 8 src/hb-uniscribe.cc | 2 test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5521982557782016 |binary test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5609911946838016 |binary test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-6651660668502016 |binary test/api/test-subset-hdmx.c | 23 + test/api/test-subset.c | 23 + 16 files changed, 424 insertions(+), 111 deletions(-)
New commits: commit b17e1a40885245df690a14c7528939b3881e1fe4 Author: Behdad Esfahbod <beh...@behdad.org> Date: Wed Mar 28 10:44:52 2018 -0700 [uniscribe] Fix assertion fail in checksum calc Program: Z:\Users\ebrahim\Desktop\harfbuzz\winbuild\util\.libs\hb-shape.exe File: ../../src/hb-open-type-private.hh, Line 769 Expression: 0 == (Length & 3) abnormal program termination diff --git a/src/hb-uniscribe.cc b/src/hb-uniscribe.cc index cd25769d..f027222d 100644 --- a/src/hb-uniscribe.cc +++ b/src/hb-uniscribe.cc @@ -410,7 +410,7 @@ _hb_rename_font (hb_blob_t *blob, wchar_t *new_name) if (face.find_table_index (HB_OT_TAG_name, &index)) { OT::TableRecord &record = const_cast<OT::TableRecord &> (face.get_table (index)); - record.checkSum.set_for_data (&name, name_table_length); + record.checkSum.set_for_data (&name, new_length); record.offset.set (name_table_offset); record.length.set (name_table_length); } commit a48dd6ef235d569d4b6f6f213ba93a54e142458d Author: Ebrahim Byagowi <ebra...@gnu.org> Date: Wed Mar 28 19:08:19 2018 +0430 Make gen-use-table.py py3 compatible (#932) diff --git a/src/gen-use-table.py b/src/gen-use-table.py index 06817255..ecbdfb95 100755 --- a/src/gen-use-table.py +++ b/src/gen-use-table.py @@ -1,9 +1,10 @@ -#!/usr/bin/python +#!/usr/bin/env python +from __future__ import print_function import sys if len (sys.argv) != 5: - print >>sys.stderr, "usage: ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt" + print ("usage: ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt", file=sys.stderr) sys.exit (1) BLACKLISTED_BLOCKS = ["Thai", "Lao", "Tibetan"] @@ -352,21 +353,21 @@ def map_to_use(data): defaults = ('O', 'No_Block') data = map_to_use(data) -print "/* == Start of generated table == */" -print "/*" -print " * The following table is generated by running:" -print " *" -print " * ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt" -print " *" -print " * on files with these headers:" -print " *" +print ("/* == Start of generated table == */") +print ("/*") +print (" * The following table is generated by running:") +print (" *") +print (" * ./gen-use-table.py IndicSyllabicCategory.txt IndicPositionalCategory.txt UnicodeData.txt Blocks.txt") +print (" *") +print (" * on files with these headers:") +print (" *") for h in headers: for l in h: - print " * %s" % (l.strip()) -print " */" -print -print '#include "hb-ot-shape-complex-use-private.hh"' -print + print (" * %s" % (l.strip())) +print (" */") +print () +print ('#include "hb-ot-shape-complex-use-private.hh"') +print () total = 0 used = 0 @@ -374,22 +375,22 @@ last_block = None def print_block (block, start, end, data): global total, used, last_block if block and block != last_block: - print - print - print " /* %s */" % block + print () + print () + print (" /* %s */" % block) if start % 16: - print ' ' * (20 + (start % 16 * 6)), + print (' ' * (20 + (start % 16 * 6)), end='') num = 0 assert start % 8 == 0 assert (end+1) % 8 == 0 for u in range (start, end+1): if u % 16 == 0: - print - print " /* %04X */" % u, + print () + print (" /* %04X */" % u, end='') if u in data: num += 1 d = data.get (u, defaults) - sys.stdout.write ("%6s," % d[0]) + print ("%6s," % d[0], end='') total += end - start + 1 used += num @@ -406,14 +407,14 @@ starts = [] ends = [] for k,v in sorted(use_mapping.items()): if k in use_positions and use_positions[k]: continue - print "#define %s USE_%s /* %s */" % (k, k, v.__name__[3:]) + print ("#define %s USE_%s /* %s */" % (k, k, v.__name__[3:])) for k,v in sorted(use_positions.items()): if not v: continue for suf in v.keys(): tag = k + suf - print "#define %s USE_%s" % (tag, tag) -print "" -print "static const USE_TABLE_ELEMENT_TYPE use_table[] = {" + print ("#define %s USE_%s" % (tag, tag)) +print ("") +print ("static const USE_TABLE_ELEMENT_TYPE use_table[] = {") for u in uu: if u <= last: continue @@ -433,51 +434,51 @@ for u in uu: if last >= 0: ends.append (last + 1) offset += ends[-1] - starts[-1] - print - print - print "#define use_offset_0x%04xu %d" % (start, offset) + print () + print () + print ("#define use_offset_0x%04xu %d" % (start, offset)) starts.append (start) print_block (block, start, end, data) last = end ends.append (last + 1) offset += ends[-1] - starts[-1] -print -print +print () +print () occupancy = used * 100. / total page_bits = 12 -print "}; /* Table items: %d; occupancy: %d%% */" % (offset, occupancy) -print -print "USE_TABLE_ELEMENT_TYPE" -print "hb_use_get_category (hb_codepoint_t u)" -print "{" -print " switch (u >> %d)" % page_bits -print " {" +print ("}; /* Table items: %d; occupancy: %d%% */" % (offset, occupancy)) +print () +print ("USE_TABLE_ELEMENT_TYPE") +print ("hb_use_get_category (hb_codepoint_t u)") +print ("{") +print (" switch (u >> %d)" % page_bits) +print (" {") pages = set([u>>page_bits for u in starts+ends]) for p in sorted(pages): - print " case 0x%0Xu:" % p + print (" case 0x%0Xu:" % p) for (start,end) in zip (starts, ends): if p not in [start>>page_bits, end>>page_bits]: continue offset = "use_offset_0x%04xu" % start - print " if (hb_in_range<hb_codepoint_t> (u, 0x%04Xu, 0x%04Xu)) return use_table[u - 0x%04Xu + %s];" % (start, end-1, start, offset) - print " break;" - print "" -print " default:" -print " break;" -print " }" -print " return USE_O;" -print "}" -print + print (" if (hb_in_range<hb_codepoint_t> (u, 0x%04Xu, 0x%04Xu)) return use_table[u - 0x%04Xu + %s];" % (start, end-1, start, offset)) + print (" break;") + print ("") +print (" default:") +print (" break;") +print (" }") +print (" return USE_O;") +print ("}") +print () for k in sorted(use_mapping.keys()): if k in use_positions and use_positions[k]: continue - print "#undef %s" % k + print ("#undef %s" % k) for k,v in sorted(use_positions.items()): if not v: continue for suf in v.keys(): tag = k + suf - print "#undef %s" % tag -print -print "/* == End of generated table == */" + print ("#undef %s" % tag) +print () +print ("/* == End of generated table == */") # Maintain at least 50% occupancy in the table */ if occupancy < 50: commit 1c3372786c503f3f9108971dfa8956e4cb95f65d Author: Garret Rieger <grie...@google.com> Date: Tue Mar 27 10:42:19 2018 -0700 [subset] fix infinite loop bug in looping through tables for subsetting. diff --git a/src/hb-subset.cc b/src/hb-subset.cc index 2a2f8557..b253817e 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -363,8 +363,8 @@ hb_subset (hb_face_t *source, continue; } success = success && _subset_table (plan, tag); - offset += count; } + offset += count; } while (count == ARRAY_LENGTH (table_tags)); hb_face_t *result = success ? hb_face_reference(plan->dest) : hb_face_get_empty(); diff --git a/test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5521982557782016 b/test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5521982557782016 new file mode 100644 index 00000000..55541f74 Binary files /dev/null and b/test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5521982557782016 differ diff --git a/test/api/test-subset.c b/test/api/test-subset.c index 6bf5c066..6d2bf06e 100644 --- a/test/api/test-subset.c +++ b/test/api/test-subset.c @@ -52,6 +52,28 @@ test_subset_32_tables (void) } static void +test_subset_no_inf_loop (void) +{ + hb_face_t *face = hb_subset_test_open_font("fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5521982557782016"); + + hb_subset_input_t *input = hb_subset_input_create_or_fail (); + hb_set_t *codepoints = hb_subset_input_unicode_set (input); + hb_set_add (codepoints, 'a'); + hb_set_add (codepoints, 'b'); + hb_set_add (codepoints, 'c'); + + hb_subset_profile_t *profile = hb_subset_profile_create(); + hb_face_t *subset = hb_subset (face, profile, input); + g_assert (subset); + g_assert (subset == hb_face_get_empty ()); + + hb_subset_input_destroy (input); + hb_subset_profile_destroy (profile); + hb_face_destroy (subset); + hb_face_destroy (face); +} + +static void test_subset_crash (void) { hb_face_t *face = hb_subset_test_open_font("fonts/crash-4b60576767ee4d9fe1cc10959d89baf73d4e8249"); @@ -79,6 +101,7 @@ main (int argc, char **argv) hb_test_init (&argc, &argv); hb_test_add (test_subset_32_tables); + hb_test_add (test_subset_no_inf_loop); hb_test_add (test_subset_crash); return hb_test_run(); commit 8fd55422c3fa2279991d93875d912fca4ee89cf5 Author: Ebrahim Byagowi <ebra...@gnu.org> Date: Tue Mar 27 16:57:09 2018 +0430 Implement an internal emojis dumper tool (#909) Later to be expanded to a more general tool but for now it only supports CBDT, SVG and CBDT. diff --git a/CMakeLists.txt b/CMakeLists.txt index a41afc4a..da6ae8b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -543,7 +543,7 @@ if (UNIX OR MINGW) check_cxx_compiler_flag(-Bsymbolic-functions CXX_SUPPORTS_FLAG_BSYMB_FUNCS) if(CXX_SUPPORTS_FLAG_BSYMB_FUNCS) link_libraries(-Bsymbolic-functions) - endif() + endif() if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") # Make sure we don't link to libstdc++ diff --git a/src/Makefile.am b/src/Makefile.am index 2aa3dc4f..df45f73b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -368,11 +368,15 @@ dist_check_SCRIPTS += \ endif check_PROGRAMS += \ + dump-emoji \ dump-indic-data \ dump-khmer-data \ dump-myanmar-data \ dump-use-data \ $(NULL) +dump_emoji_SOURCES = dump-emoji.cc +dump_emoji_CPPFLAGS = $(HBCFLAGS) +dump_emoji_LDADD = libharfbuzz.la $(HBLIBS) dump_indic_data_SOURCES = dump-indic-data.cc hb-ot-shape-complex-indic-table.cc dump_indic_data_CPPFLAGS = $(HBCFLAGS) dump_indic_data_LDADD = libharfbuzz.la $(HBLIBS) diff --git a/src/dump-emoji.cc b/src/dump-emoji.cc new file mode 100644 index 00000000..a9595e41 --- /dev/null +++ b/src/dump-emoji.cc @@ -0,0 +1,141 @@ +/* + * Copyright © 2018 Ebrahim Byagowi + * + * This is part of HarfBuzz, a text shaping library. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and its documentation for any purpose, provided that the + * above copyright notice and the following two paragraphs appear in + * all copies of this software. + * + * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR + * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN + * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS + * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + */ + +#include "hb.h" +#include "hb-private.hh" +#include "hb-ot-color-cbdt-table.hh" +#include "hb-ot-color-sbix-table.hh" +#include "hb-ot-color-svg-table.hh" + +#ifdef HAVE_GLIB +#include <glib.h> +#endif +#include <stdlib.h> +#include <stdio.h> + +#ifndef HB_NO_VISIBILITY +const void * const OT::_hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; +#endif + +void cbdt_callback (const uint8_t* data, unsigned int length, + unsigned int group, unsigned int gid) +{ + char outName[255]; + sprintf (outName, "out/cbdt-%d-%d.png", group, gid); + FILE *f = fopen (outName, "wb"); + fwrite (data, 1, length, f); + fclose (f); +} + +void sbix_callback (const uint8_t* data, unsigned int length, + unsigned int group, unsigned int gid) +{ + char outName[255]; + sprintf (outName, "out/sbix-%d-%d.png", group, gid); + FILE *f = fopen (outName, "wb"); + fwrite (data, 1, length, f); + fclose (f); +} + +void svg_callback (const uint8_t* data, unsigned int length, + unsigned int start_glyph, unsigned int end_glyph) +{ + char outName[255]; + if (start_glyph == end_glyph) + sprintf (outName, "out/svg-%d.svg", start_glyph); + else + sprintf (outName, "out/svg-%d-%d.svg", start_glyph, end_glyph); + + // append "z" if the content is gzipped + if ((data[0] == 0x1F) && (data[1] == 0x8B)) + strcat (outName, "z"); + + FILE *f = fopen (outName, "wb"); + fwrite (data, 1, length, f); + fclose (f); +} + +int main(int argc, char **argv) +{ + if (argc != 2) { + fprintf (stderr, "usage: %s font-file.ttf\n", argv[0]); + exit (1); + } + + hb_blob_t *blob = nullptr; + { + const char *font_data; + unsigned int len; + hb_destroy_func_t destroy; + void *user_data; + hb_memory_mode_t mm; + +#ifdef HAVE_GLIB + GMappedFile *mf = g_mapped_file_new (argv[1], false, nullptr); + font_data = g_mapped_file_get_contents (mf); + len = g_mapped_file_get_length (mf); + destroy = (hb_destroy_func_t) g_mapped_file_unref; + user_data = (void *) mf; + mm = HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE; +#else + FILE *f = fopen (argv[1], "rb"); + fseek (f, 0, SEEK_END); + len = ftell (f); + fseek (f, 0, SEEK_SET); + font_data = (const char *) malloc (len); + if (!font_data) len = 0; + len = fread ((char *) font_data, 1, len, f); + destroy = free; + user_data = (void *) font_data; + fclose (f); + mm = HB_MEMORY_MODE_WRITABLE; +#endif + + blob = hb_blob_create (font_data, len, mm, user_data, destroy); + } + + hb_face_t *face = hb_face_create (blob, 0); + hb_font_t *font = hb_font_create (face); + + OT::CBDT::accelerator_t cbdt; + cbdt.init (face); + cbdt.dump (cbdt_callback); + cbdt.fini (); + + OT::sbix::accelerator_t sbix; + sbix.init (face); + sbix.dump (sbix_callback); + sbix.fini (); + + OT::SVG::accelerator_t svg; + svg.init (face); + svg.dump (svg_callback); + svg.fini (); + + hb_font_destroy (font); + hb_face_destroy (face); + hb_blob_destroy (blob); + + return 0; +} diff --git a/src/hb-ot-color-cbdt-table.hh b/src/hb-ot-color-cbdt-table.hh index b4971bda..cf1c69c1 100644 --- a/src/hb-ot-color-cbdt-table.hh +++ b/src/hb-ot-color-cbdt-table.hh @@ -223,6 +223,8 @@ struct IndexSubtableRecord struct IndexSubtableArray { + friend struct CBDT; + inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const { TRACE_SANITIZE (this); @@ -257,6 +259,7 @@ struct IndexSubtableArray struct BitmapSizeTable { friend struct CBLC; + friend struct CBDT; inline bool sanitize (hb_sanitize_context_t *c, const void *base) const { @@ -304,6 +307,21 @@ struct GlyphBitmapDataFormat17 DEFINE_SIZE_ARRAY(9, data); }; +struct GlyphBitmapDataFormat18 +{ + BigGlyphMetrics glyphMetrics; + ArrayOf<HBUINT8, HBUINT32> data; + public: + DEFINE_SIZE_ARRAY(12, data); +}; + +struct GlyphBitmapDataFormat19 +{ + ArrayOf<HBUINT8, HBUINT32> data; + public: + DEFINE_SIZE_ARRAY(4, data); +}; + /* * CBLC -- Color Bitmap Location Table @@ -444,6 +462,59 @@ struct CBDT return true; } + inline void dump (void (*callback) (const uint8_t* data, unsigned int length, + unsigned int group, unsigned int gid)) const + { + if (!cblc) + return; // Not a color bitmap font. + + for (unsigned int i = 0; i < cblc->sizeTables.len; ++i) + { + const BitmapSizeTable &sizeTable = cblc->sizeTables[i]; + const IndexSubtableArray &subtable_array = cblc+sizeTable.indexSubtableArrayOffset; + for (unsigned int j = 0; j < sizeTable.numberOfIndexSubtables; ++j) + { + const IndexSubtableRecord &subtable_record = subtable_array.indexSubtablesZ[j]; + for (unsigned int gid = subtable_record.firstGlyphIndex; + gid <= subtable_record.lastGlyphIndex; ++gid) + { + unsigned int image_offset = 0, image_length = 0, image_format = 0; + + if (!subtable_record.get_image_data (gid, + &image_offset, &image_length, &image_format)) + continue; + + switch (image_format) + { + case 17: { + const GlyphBitmapDataFormat17& glyphFormat17 = + StructAtOffset<GlyphBitmapDataFormat17> (this->cbdt, image_offset); + callback ((const uint8_t *) &glyphFormat17.data.array, + glyphFormat17.data.len, i, gid); + } + break; + case 18: { + const GlyphBitmapDataFormat18& glyphFormat18 = + StructAtOffset<GlyphBitmapDataFormat18> (this->cbdt, image_offset); + callback ((const uint8_t *) &glyphFormat18.data.array, + glyphFormat18.data.len, i, gid); + } + break; + case 19: { + const GlyphBitmapDataFormat19& glyphFormat19 = + StructAtOffset<GlyphBitmapDataFormat19> (this->cbdt, image_offset); + callback ((const uint8_t *) &glyphFormat19.data.array, + glyphFormat19.data.len, i, gid); + } + break; + default: + continue; + } + } + } + } + } + private: hb_blob_t *cblc_blob; hb_blob_t *cbdt_blob; diff --git a/src/hb-ot-color-sbix-table.hh b/src/hb-ot-color-sbix-table.hh index c0d8f9b3..bc3956d8 100644 --- a/src/hb-ot-color-sbix-table.hh +++ b/src/hb-ot-color-sbix-table.hh @@ -27,7 +27,7 @@ #include "hb-open-type-private.hh" -#define HB_OT_TAG_SBIX HB_TAG('s','b','i','x') +#define HB_OT_TAG_sbix HB_TAG('s','b','i','x') namespace OT { @@ -55,6 +55,8 @@ struct SBIXGlyph struct SBIXStrike { + friend struct sbix; + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); @@ -77,22 +79,12 @@ struct SBIXStrike /* * sbix -- Standard Bitmap Graphics Table + * https://docs.microsoft.com/en-us/typography/opentype/spec/sbix */ -// It should be called with something like this so it can have -// access to num_glyph while sanitizing. -// -// static inline const OT::sbix* -// _get_sbix (hb_face_t *face) -// { -// OT::Sanitizer<OT::sbix> sanitizer; -// sanitizer.set_num_glyphs (face->get_num_glyphs ()); -// hb_blob_t *sbix_blob = sanitizer.sanitize (face->reference_table (HB_OT_TAG_SBIX)); -// return OT::Sanitizer<OT::sbix>::lock_instance (sbix_blob); -// } -// + struct sbix { - static const hb_tag_t tableTag = HB_OT_TAG_SBIX; + static const hb_tag_t tableTag = HB_OT_TAG_sbix; inline bool sanitize (hb_sanitize_context_t *c) const { @@ -100,21 +92,50 @@ struct sbix return_trace (c->check_struct (this) && strikes.sanitize (c, this)); } - // inline void dump (unsigned int num_glyphs, unsigned int group) const - // { - // const SBIXStrike &strike = strikes[group](this); - // for (unsigned int i = 0; i < num_glyphs; ++i) - // if (strike.imageOffsetsZ[i + 1] - strike.imageOffsetsZ[i] > 0) - // { - // const SBIXGlyph &sbixGlyph = strike.imageOffsetsZ[i]((const void *) &strike); - // char outName[255]; - // sprintf (outName, "out/%d-%d.png", group, i); - // FILE *f = fopen (outName, "wb"); - // fwrite (sbixGlyph.data, 1, - // strike.imageOffsetsZ[i + 1] - strike.imageOffsetsZ[i] - 8, f); - // fclose (f); - // } - // } + struct accelerator_t + { + inline void init (hb_face_t *face) + { + num_glyphs = hb_face_get_glyph_count (face); + + OT::Sanitizer<OT::sbix> sanitizer; + sanitizer.set_num_glyphs (num_glyphs); + sbix_blob = sanitizer.sanitize (face->reference_table (HB_OT_TAG_sbix)); + sbix_len = hb_blob_get_length (sbix_blob); + sbix_table = OT::Sanitizer<OT::sbix>::lock_instance (sbix_blob); + + } + + inline void fini (void) + { + hb_blob_destroy (sbix_blob); + } + + inline void dump (void (*callback) (const uint8_t* data, unsigned int length, + unsigned int group, unsigned int gid)) const + { + for (unsigned group = 0; group < sbix_table->strikes.len; ++group) + { + const SBIXStrike &strike = sbix_table->strikes[group](sbix_table); + for (unsigned int glyph = 0; glyph < num_glyphs; ++glyph) + if (strike.imageOffsetsZ[glyph + 1] - strike.imageOffsetsZ[glyph] > 0) + { + const SBIXGlyph &sbixGlyph = strike.imageOffsetsZ[glyph]((const void *) &strike); + callback ((const uint8_t*) sbixGlyph.data, + strike.imageOffsetsZ[glyph + 1] - strike.imageOffsetsZ[glyph] - 8, + group, glyph); + } + } + } + + private: + hb_blob_t *sbix_blob; + const sbix *sbix_table; + + unsigned int sbix_len; + unsigned int num_glyphs; + + }; protected: HBUINT16 version; /* Table version number — set to 1 */ diff --git a/src/hb-ot-color-svg-table.hh b/src/hb-ot-color-svg-table.hh index 3dc24e99..6d0d9c4f 100644 --- a/src/hb-ot-color-svg-table.hh +++ b/src/hb-ot-color-svg-table.hh @@ -39,7 +39,7 @@ namespace OT { struct SVGDocumentIndexEntry { - // friend struct SVGDocumentIndex; + friend struct SVG; inline bool sanitize (hb_sanitize_context_t *c, const void* base) const { @@ -64,27 +64,15 @@ struct SVGDocumentIndexEntry struct SVGDocumentIndex { + friend struct SVG; + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - // dump (); return_trace (c->check_struct (this) && entries.sanitize (c, this)); } - // inline void dump () const - // { - // for (unsigned int i = 0; i < entries.len; ++i) - // { - // char outName[255]; - // sprintf (outName, "out/%d.svg", i); - // const SVGDocumentIndexEntry &entry = entries[i]; - // FILE *f = fopen (outName, "wb"); - // fwrite (&entry.svgDoc (this), 1, entry.svgDocLength, f); - // fclose (f); - // } - // } - protected: ArrayOf<SVGDocumentIndexEntry> entries; /* Array of SVG Document Index Entries. */ @@ -100,9 +88,45 @@ struct SVG { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - svgDocIndex(this).sanitize (c)); + svgDocIndex (this).sanitize (c)); } + struct accelerator_t + { + inline void init (hb_face_t *face) + { + OT::Sanitizer<OT::SVG> sanitizer; + svg_blob = sanitizer.sanitize (face->reference_table (HB_OT_TAG_SVG)); + svg_len = hb_blob_get_length (svg_blob); + svg = OT::Sanitizer<OT::SVG>::lock_instance (svg_blob); + + } + + inline void fini (void) + { + hb_blob_destroy (svg_blob); + } + + inline void dump (void (*callback) (const uint8_t* data, unsigned int length, + unsigned int start_glyph, unsigned int end_glyph)) const + { + const SVGDocumentIndex &index = svg->svgDocIndex (svg); + const ArrayOf<SVGDocumentIndexEntry> &entries = index.entries; + for (unsigned int i = 0; i < entries.len; ++i) + { + const SVGDocumentIndexEntry &entry = entries[i]; + callback ((const uint8_t*) &entry.svgDoc (&index), entry.svgDocLength, + entry.startGlyphID, entry.endGlyphID); + } + } + + private: + hb_blob_t *svg_blob; + const SVG *svg; + + unsigned int svg_len; + }; + protected: HBUINT16 version; /* Table version (starting at 0). */ LOffsetTo<SVGDocumentIndex> commit 430f82817d048ac917f1956e07d9089b9fd7e695 Author: Ebrahim Byagowi <ebra...@gnu.org> Date: Tue Mar 27 13:59:56 2018 +0430 [ci] Fix coverage build fail (#925) diff --git a/src/Makefile.am b/src/Makefile.am index af7a4bdd..2aa3dc4f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -141,10 +141,10 @@ endif @CODE_COVERAGE_RULES@ base_link_flags = $(AM_LDFLAGS) -lm -version-info $(HB_LIBTOOL_VERSION_INFO) -no-undefined -libharfbuzz_la_LINK = $(chosen_linker) $(libharfbuzz_la_LDFLAGS) $(CODE_COVERAGE_LDFLAGS) +libharfbuzz_la_LINK = $(chosen_linker) $(libharfbuzz_la_LDFLAGS) libharfbuzz_la_SOURCES = $(HBSOURCES) $(HBHEADERS) libharfbuzz_la_CPPFLAGS = $(HBCFLAGS) $(CODE_COVERAGE_CFLAGS) -libharfbuzz_la_LDFLAGS = $(base_link_flags) $(export_symbols) +libharfbuzz_la_LDFLAGS = $(base_link_flags) $(export_symbols) $(CODE_COVERAGE_LDFLAGS) libharfbuzz_la_LIBADD = $(HBLIBS) EXTRA_libharfbuzz_la_DEPENDENCIES = $(harfbuzz_def_dependency) pkginclude_HEADERS = $(HBHEADERS) @@ -158,7 +158,7 @@ EXTRA_DIST += harfbuzz.pc.in harfbuzz-config.cmake.in lib_LTLIBRARIES += libharfbuzz-subset.la libharfbuzz_subset_la_SOURCES = $(HB_SUBSET_sources) libharfbuzz_subset_la_CPPFLAGS = $(HBCFLAGS) $(CODE_COVERAGE_CFLAGS) -libharfbuzz_subset_la_LDFLAGS = $(base_link_flags) $(export_symbols_subset) +libharfbuzz_subset_la_LDFLAGS = $(base_link_flags) $(export_symbols_subset) $(CODE_COVERAGE_LDFLAGS) libharfbuzz_subset_la_LIBADD = libharfbuzz.la EXTRA_libharfbuzz_subset_la_DEPENDENCIES = $(harfbuzz_subset_def_dependency) pkginclude_HEADERS += $(HB_SUBSET_headers) @@ -205,8 +205,8 @@ HBHEADERS += $(HB_ICU_headers) else lib_LTLIBRARIES += libharfbuzz-icu.la libharfbuzz_icu_la_SOURCES = $(HB_ICU_sources) -libharfbuzz_icu_la_CPPFLAGS = $(HBCFLAGS) $(ICU_CFLAGS) $(CODE_COVERAGE_CFLAGS) -libharfbuzz_icu_la_LDFLAGS = $(base_link_flags) $(export_symbols_icu) +libharfbuzz_icu_la_CPPFLAGS = $(HBCFLAGS) $(ICU_CFLAGS) $(CODE_COVERAGE_CFLAGS) +libharfbuzz_icu_la_LDFLAGS = $(base_link_flags) $(export_symbols_icu) $(CODE_COVERAGE_LDFLAGS) libharfbuzz_icu_la_LIBADD = $(ICU_LIBS) libharfbuzz.la EXTRA_libharfbuzz_icu_la_DEPENDENCIES = $(harfbuzz_icu_def_dependency) pkginclude_HEADERS += $(HB_ICU_headers) @@ -220,8 +220,8 @@ lib_LTLIBRARIES += libharfbuzz-gobject.la libharfbuzz_gobject_la_LINK = $(chosen_linker) $(libharfbuzz_gobject_la_LDFLAGS) libharfbuzz_gobject_la_SOURCES = $(HB_GOBJECT_DIST_sources) nodist_libharfbuzz_gobject_la_SOURCES = $(HB_GOBJECT_NODIST_sources) -libharfbuzz_gobject_la_CPPFLAGS = $(HBCFLAGS) $(GOBJECT_CFLAGS) $(CODE_COVERAGE_LDFLAGS) -libharfbuzz_gobject_la_LDFLAGS = $(base_link_flags) +libharfbuzz_gobject_la_CPPFLAGS = $(HBCFLAGS) $(GOBJECT_CFLAGS) $(CODE_COVERAGE_CFLAGS) +libharfbuzz_gobject_la_LDFLAGS = $(base_link_flags) $(CODE_COVERAGE_LDFLAGS) libharfbuzz_gobject_la_LIBADD = $(GOBJECT_LIBS) libharfbuzz.la EXTRA_libharfbuzz_gobject_la_DEPENDENCIES = $(harfbuzz_gobject_def_dependency) pkginclude_HEADERS += $(HB_GOBJECT_DIST_headers) commit 07851aae9d28fed751663c543799f2b59369f892 Author: Garret Rieger <grie...@google.com> Date: Mon Mar 26 20:56:56 2018 -0600 [subset] Couple of fixes for fuzzer discovered issues. (#924) * [subset] sanitize individual DeviceRecord's as part of hdmx sanitization. * [subset] Fix out of bounds read with non-two byte align glyphs. * [subset] Just use size_device_record >= DeviceRecord::min_size. * [subset] Add TODO. * [subset] Re-order checks in hdmx sanitize. diff --git a/src/hb-ot-hdmx-table.hh b/src/hb-ot-hdmx-table.hh index 6ad57af2..c0b22b28 100644 --- a/src/hb-ot-hdmx-table.hh +++ b/src/hb-ot-hdmx-table.hh @@ -198,6 +198,7 @@ struct hdmx TRACE_SANITIZE (this); return_trace (c->check_struct (this) && version == 0 && !_hb_unsigned_int_mul_overflows (num_records, size_device_record) && + size_device_record >= DeviceRecord::min_size && c->check_range (this, get_size())); } diff --git a/src/hb-subset-glyf.cc b/src/hb-subset-glyf.cc index 1bbcbdcd..b9e6355c 100644 --- a/src/hb-subset-glyf.cc +++ b/src/hb-subset-glyf.cc @@ -121,7 +121,6 @@ static void _update_components (hb_subset_plan_t * plan, char * glyph_start, unsigned int length) - { OT::glyf::CompositeGlyphHeader::Iterator iterator; if (OT::glyf::CompositeGlyphHeader::get_iterator (glyph_start, @@ -176,11 +175,11 @@ _write_glyf_and_loca_prime (hb_subset_plan_t *plan, if (unlikely (!(glyf.get_offsets (glyph_ids[i], &start_offset, &end_offset) && glyf.remove_padding(start_offset, &end_offset)))) end_offset = start_offset = 0; + unsigned int instruction_start = instruction_ranges[i * 2]; unsigned int instruction_end = instruction_ranges[i * 2 + 1]; int length = end_offset - start_offset - (instruction_end - instruction_start); - length += length % 2; if (glyf_prime_data_next + length > glyf_prime_data + glyf_prime_size) { @@ -214,7 +213,8 @@ _write_glyf_and_loca_prime (hb_subset_plan_t *plan, loca_prime_size); _update_components (plan, glyf_prime_data_next, length); - glyf_prime_data_next += length; + // TODO: don't align to two bytes if using long loca. + glyf_prime_data_next += length + (length % 2); // Align to 2 bytes for short loca. } success = success && _write_loca_entry (glyph_ids.len, diff --git a/src/hb-subset.cc b/src/hb-subset.cc index 4062c9b4..2a2f8557 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -89,12 +89,16 @@ _subset (hb_subset_plan_t *plan) hb_blob_t *source_blob = sanitizer.sanitize (plan->source->reference_table (TableType::tableTag)); const TableType *table = OT::Sanitizer<TableType>::lock_instance (source_blob); + hb_tag_t tag = TableType::tableTag; hb_bool_t result = false; if (table != &OT::Null(TableType)) + { result = table->subset(plan); + } else { + DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG(tag)); + } hb_blob_destroy (source_blob); - hb_tag_t tag = TableType::tableTag; DEBUG_MSG(SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG(tag), result ? "success" : "FAILED!"); return result; } diff --git a/test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5609911946838016 b/test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5609911946838016 new file mode 100644 index 00000000..8c647a8a Binary files /dev/null and b/test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5609911946838016 differ diff --git a/test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-6651660668502016 b/test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-6651660668502016 new file mode 100644 index 00000000..6206f077 Binary files /dev/null and b/test/api/fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-6651660668502016 differ diff --git a/test/api/test-subset-hdmx.c b/test/api/test-subset-hdmx.c index dd20b2a2..c78009b6 100644 --- a/test/api/test-subset-hdmx.c +++ b/test/api/test-subset-hdmx.c @@ -73,6 +73,28 @@ test_subset_hdmx_invalid (void) } static void +test_subset_hdmx_fails_sanitize (void) +{ + hb_face_t *face = hb_subset_test_open_font("fonts/clusterfuzz-testcase-minimized-hb-subset-fuzzer-5609911946838016"); + + hb_subset_input_t *input = hb_subset_input_create_or_fail (); + hb_set_t *codepoints = hb_subset_input_unicode_set (input); + hb_set_add (codepoints, 'a'); + hb_set_add (codepoints, 'b'); + hb_set_add (codepoints, 'c'); + + hb_subset_profile_t *profile = hb_subset_profile_create(); + hb_face_t *subset = hb_subset (face, profile, input); + g_assert (subset); + g_assert (subset == hb_face_get_empty ()); + + hb_subset_input_destroy (input); + hb_subset_profile_destroy (profile); + hb_face_destroy (subset); + hb_face_destroy (face); +} + +static void test_subset_hdmx_noop (void) { hb_face_t *face_abc = hb_subset_test_open_font("fonts/Roboto-Regular.abc.ttf"); @@ -98,6 +120,7 @@ main (int argc, char **argv) hb_test_add (test_subset_hdmx_simple_subset); hb_test_add (test_subset_hdmx_invalid); + hb_test_add (test_subset_hdmx_fails_sanitize); hb_test_add (test_subset_hdmx_noop); return hb_test_run(); _______________________________________________ HarfBuzz mailing list HarfBuzz@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/harfbuzz