[HarfBuzz] harfbuzz: Branch 'master' - 6 commits
Behdad Esfahbod
behdad at kemper.freedesktop.org
Wed Mar 28 17:45:32 UTC 2018
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 <behdad at 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 <ebrahim at 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 <grieger at 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 <ebrahim at 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 <ebrahim at 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 <grieger at 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();
More information about the HarfBuzz
mailing list