diff --git a/src/Makefile.am b/src/Makefile.am index 9632b4df6..b3cc42f3f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -15,7 +15,6 @@ check_PROGRAMS = # Convenience targets: lib: $(BUILT_SOURCES) libharfbuzz.la libs: $(BUILT_SOURCES) $(lib_LTLIBRARIES) -fuzzing: $(BUILT_SOURCES) libharfbuzz-fuzzing.la libharfbuzz-subset-fuzzing.la lib_LTLIBRARIES = libharfbuzz.la @@ -169,36 +168,6 @@ pkginclude_HEADERS += $(HB_SUBSET_headers) pkgconfig_DATA += harfbuzz-subset.pc EXTRA_DIST += harfbuzz-subset.pc.in -FUZZING_CPPFLAGS = \ - -DHB_MAX_NESTING_LEVEL=3 \ - -DHB_SANITIZE_MAX_EDITS=3 \ - -DHB_SANITIZE_MAX_OPS_FACTOR=3 \ - -DHB_SANITIZE_MAX_OPS_MIN=128 \ - -DHB_BUFFER_MAX_LEN_FACTOR=3 \ - -DHB_BUFFER_MAX_LEN_MIN=8 \ - -DHB_BUFFER_MAX_LEN_DEFAULT=128 \ - -DHB_BUFFER_MAX_OPS_FACTOR=8 \ - -DHB_BUFFER_MAX_OPS_MIN=64 \ - -DHB_BUFFER_MAX_OPS_DEFAULT=1024 \ - $(NULL) -EXTRA_LTLIBRARIES = libharfbuzz-fuzzing.la libharfbuzz-subset-fuzzing.la - -libharfbuzz_fuzzing_la_LINK = $(chosen_linker) $(libharfbuzz_fuzzing_la_LDFLAGS) -libharfbuzz_fuzzing_la_SOURCES = $(libharfbuzz_la_SOURCES) -libharfbuzz_fuzzing_la_CPPFLAGS = $(HBCFLAGS) $(FUZZING_CPPFLAGS) -libharfbuzz_fuzzing_la_LDFLAGS = $(AM_LDFLAGS) -libharfbuzz_fuzzing_la_LIBADD = $(libharfbuzz_la_LIBADD) -EXTRA_libharfbuzz_fuzzing_la_DEPENDENCIES = $(EXTRA_libharfbuzz_la_DEPENDENCIES) -CLEANFILES += libharfbuzz-fuzzing.la - -libharfbuzz_subset_fuzzing_la_LINK = $(chosen_linker) $(libharfbuzz_subset_fuzzing_la_LDFLAGS) -libharfbuzz_subset_fuzzing_la_SOURCES = $(libharfbuzz_subset_la_SOURCES) -libharfbuzz_subset_fuzzing_la_CPPFLAGS = $(HBCFLAGS) $(FUZZING_CPPFLAGS) -libharfbuzz_subset_fuzzing_la_LDFLAGS = $(AM_LDFLAGS) -libharfbuzz_subset_fuzzing_la_LIBADD = libharfbuzz-fuzzing.la -EXTRA_libharfbuzz_subset_fuzzing_la_DEPENDENCIES = $(EXTRA_libharfbuzz_subset_la_DEPENDENCIES) -CLEANFILES += libharfbuzz-subset-fuzzing.la - if HAVE_ICU if HAVE_ICU_BUILTIN HBCFLAGS += $(ICU_CFLAGS) diff --git a/src/Makefile.sources b/src/Makefile.sources index b58848e04..b15aeea48 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -163,6 +163,7 @@ HB_OT_sources = \ hb-ot-shape-fallback.hh \ hb-ot-shape-fallback.cc \ hb-ot-shape.hh \ + hb-ot-stat-table.hh \ hb-ot-var.cc \ hb-ot-var-avar-table.hh \ hb-ot-var-fvar-table.hh \ diff --git a/src/gen-use-table.py b/src/gen-use-table.py index ebfae6fab..a8a7a2326 100755 --- a/src/gen-use-table.py +++ b/src/gen-use-table.py @@ -200,7 +200,8 @@ def is_HALANT(U, UISC, UGC): return UISC in [Virama, Invisible_Stacker] and not is_HALANT_OR_VOWEL_MODIFIER(U, UISC, UGC) def is_HALANT_OR_VOWEL_MODIFIER(U, UISC, UGC): # https://github.com/harfbuzz/harfbuzz/issues/1102 - return U == 0x11046 + # https://github.com/harfbuzz/harfbuzz/issues/1379 + return U in [0x11046, 0x1134D] def is_HALANT_NUM(U, UISC, UGC): return UISC == Number_Joiner def is_ZWNJ(U, UISC, UGC): diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh index 8191df4ca..adc7538c9 100644 --- a/src/hb-aat-layout-common.hh +++ b/src/hb-aat-layout-common.hh @@ -557,7 +557,9 @@ struct StateTable /* Negative states. */ if (unlikely (hb_unsigned_mul_overflows (min_state, num_classes))) return_trace (false); - if (unlikely (!c->check_array (&states[min_state * num_classes], -min_state, row_stride))) + if (unlikely (!c->check_range (&states[min_state * num_classes], + -min_state, + row_stride))) return_trace (false); if ((c->max_ops -= state_neg - min_state) < 0) return_trace (false); @@ -574,7 +576,9 @@ struct StateTable if (state_pos <= max_state) { /* Positive states. */ - if (unlikely (!c->check_array (states, max_state + 1, row_stride))) + if (unlikely (!c->check_range (states, + max_state + 1, + row_stride))) return_trace (false); if ((c->max_ops -= max_state - state_pos + 1) < 0) return_trace (false); diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh index 6b61186a9..f075a270a 100644 --- a/src/hb-aat-layout-kerx-table.hh +++ b/src/hb-aat-layout-kerx-table.hh @@ -260,14 +260,14 @@ struct KerxSubTableFormat1 depth = 0; /* Probably not what CoreText does, but better? */ } - if (Format1EntryT::performAction (entry)) + if (Format1EntryT::performAction (entry) && depth) { unsigned int tuple_count = MAX (1u, table->header.tuple_count ()); unsigned int kern_idx = Format1EntryT::kernActionIndex (entry); kern_idx = Types::offsetToIndex (kern_idx, &table->machine, kernAction.arrayZ); const FWORD *actions = &kernAction[kern_idx]; - if (!c->sanitizer.check_array (actions, depth * tuple_count)) + if (!c->sanitizer.check_array (actions, depth, tuple_count)) { depth = 0; return false; @@ -279,9 +279,9 @@ struct KerxSubTableFormat1 * "Each pops one glyph from the kerning stack and applies the kerning value to it. * The end of the list is marked by an odd value... */ bool last = false; - while (!last && depth--) + while (!last && depth) { - unsigned int idx = stack[depth]; + unsigned int idx = stack[--depth]; int v = *actions; actions += tuple_count; if (idx >= buffer->len) continue; diff --git a/src/hb-aat-layout-lcar-table.hh b/src/hb-aat-layout-lcar-table.hh index e57836a08..43ac74f9c 100644 --- a/src/hb-aat-layout-lcar-table.hh +++ b/src/hb-aat-layout-lcar-table.hh @@ -49,7 +49,8 @@ struct lcar unsigned int *caret_count /* IN/OUT */, hb_position_t *caret_array /* OUT */) const { - const OffsetTo* entry_offset = lookup.get_value (glyph, font->face->num_glyphs); + const OffsetTo* entry_offset = lookup.get_value (glyph, + font->face->get_num_glyphs ()); const LigCaretClassEntry& array = entry_offset ? this+*entry_offset : Null (LigCaretClassEntry); if (caret_count && *caret_count) { diff --git a/src/hb-aat-map.cc b/src/hb-aat-map.cc index 1ce1b12b0..8bc1a0c61 100644 --- a/src/hb-aat-map.cc +++ b/src/hb-aat-map.cc @@ -51,9 +51,7 @@ void hb_aat_map_builder_t::add_feature (hb_tag_t tag, } void -hb_aat_map_builder_t::compile (hb_aat_map_t &m, - const int *coords HB_UNUSED, - unsigned int num_coords HB_UNUSED) +hb_aat_map_builder_t::compile (hb_aat_map_t &m) { /* Sort features and merge duplicates */ if (features.len) diff --git a/src/hb-aat-map.hh b/src/hb-aat-map.hh index 6fd3fa1ea..07454b2c1 100644 --- a/src/hb-aat-map.hh +++ b/src/hb-aat-map.hh @@ -60,9 +60,7 @@ struct hb_aat_map_builder_t HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value=1); - HB_INTERNAL void compile (hb_aat_map_t &m, - const int *coords, - unsigned int num_coords); + HB_INTERNAL void compile (hb_aat_map_t &m); public: struct feature_info_t diff --git a/src/hb-atomic.hh b/src/hb-atomic.hh index 49c2809e2..64ed257bd 100644 --- a/src/hb-atomic.hh +++ b/src/hb-atomic.hh @@ -100,7 +100,7 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N) #define hb_atomic_ptr_impl_cmpexch(P,O,N) _hb_atomic_ptr_impl_cmplexch ((const void **) (P), (O), (N)) -#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__)) +#elif !defined(HB_NO_MT) && defined(_WIN32) #include @@ -257,24 +257,24 @@ static_assert ((sizeof (long) == sizeof (void *)), ""); inline void hb_atomic_int_impl_set (int *AI, int v) { _hb_memory_w_barrier (); *AI = v; } #endif #ifndef hb_atomic_int_impl_get -inline int hb_atomic_int_impl_get (int *AI) { int v = *AI; _hb_memory_r_barrier (); return v; } +inline int hb_atomic_int_impl_get (const int *AI) { int v = *AI; _hb_memory_r_barrier (); return v; } #endif #ifndef hb_atomic_ptr_impl_get -inline void *hb_atomic_ptr_impl_get (void **P) { void *v = *P; _hb_memory_r_barrier (); return v; } +inline void *hb_atomic_ptr_impl_get (void ** const P) { void *v = *P; _hb_memory_r_barrier (); return v; } #endif #define HB_ATOMIC_INT_INIT(V) {V} struct hb_atomic_int_t { - inline void set_relaxed (int v_) const { hb_atomic_int_impl_set_relaxed (&v, v_); } - inline void set (int v_) const { hb_atomic_int_impl_set (&v, v_); } + inline void set_relaxed (int v_) { hb_atomic_int_impl_set_relaxed (&v, v_); } + inline void set (int v_) { hb_atomic_int_impl_set (&v, v_); } inline int get_relaxed (void) const { return hb_atomic_int_impl_get_relaxed (&v); } inline int get (void) const { return hb_atomic_int_impl_get (&v); } inline int inc (void) { return hb_atomic_int_impl_add (&v, 1); } inline int dec (void) { return hb_atomic_int_impl_add (&v, -1); } - mutable int v; + int v; }; @@ -285,7 +285,7 @@ struct hb_atomic_ptr_t typedef typename hb_remove_pointer

::value T; inline void init (T* v_ = nullptr) { set_relaxed (v_); } - inline void set_relaxed (T* v_) const { hb_atomic_ptr_impl_set_relaxed (&v, v_); } + inline void set_relaxed (T* v_) { hb_atomic_ptr_impl_set_relaxed (&v, v_); } inline T *get_relaxed (void) const { return (T *) hb_atomic_ptr_impl_get_relaxed (&v); } inline T *get (void) const { return (T *) hb_atomic_ptr_impl_get ((void **) &v); } inline bool cmpexch (const T *old, T *new_) const { return hb_atomic_ptr_impl_cmpexch ((void **) &v, (void *) old, (void *) new_); } @@ -293,7 +293,7 @@ struct hb_atomic_ptr_t inline T * operator -> (void) const { return get (); } template inline operator C * (void) const { return get (); } - mutable T *v; + T *v; }; diff --git a/src/hb-blob.cc b/src/hb-blob.cc index 26c0d143e..8ebedca78 100644 --- a/src/hb-blob.cc +++ b/src/hb-blob.cc @@ -481,7 +481,7 @@ hb_blob_t::try_make_writable (void) # include #endif -#if defined(_WIN32) || defined(__CYGWIN__) +#ifdef _WIN32 # include #else # ifndef O_BINARY @@ -497,19 +497,19 @@ struct hb_mapped_file_t { char *contents; unsigned long length; -#if defined(_WIN32) || defined(__CYGWIN__) +#ifdef _WIN32 HANDLE mapping; #endif }; -#if (defined(HAVE_MMAP) || defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_NO_MMAP) +#if (defined(HAVE_MMAP) || defined(_WIN32)) && !defined(HB_NO_MMAP) static void _hb_mapped_file_destroy (void *file_) { hb_mapped_file_t *file = (hb_mapped_file_t *) file_; #ifdef HAVE_MMAP munmap (file->contents, file->length); -#elif defined(_WIN32) || defined(__CYGWIN__) +#elif defined(_WIN32) UnmapViewOfFile (file->contents); CloseHandle (file->mapping); #else @@ -560,7 +560,7 @@ fail: fail_without_close: free (file); -#elif (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_NO_MMAP) +#elif defined(_WIN32) && !defined(HB_NO_MMAP) hb_mapped_file_t *file = (hb_mapped_file_t *) calloc (1, sizeof (hb_mapped_file_t)); if (unlikely (!file)) return hb_blob_get_empty (); diff --git a/src/hb-dsalgs.hh b/src/hb-dsalgs.hh index 2540d438b..7a207f5d2 100644 --- a/src/hb-dsalgs.hh +++ b/src/hb-dsalgs.hh @@ -264,6 +264,17 @@ static inline unsigned int ARRAY_LENGTH (const Type (&)[n]) { return n; } /* A const version, but does not detect erratically being called on pointers. */ #define ARRAY_LENGTH_CONST(__array) ((signed int) (sizeof (__array) / sizeof (__array[0]))) + +static inline int +hb_memcmp (const void *a, const void *b, unsigned int len) +{ + /* It's illegal to pass NULL to memcmp(), even if len is zero. + * So, wrap it. + * https://sourceware.org/bugzilla/show_bug.cgi?id=23878 */ + if (!len) return 0; + return memcmp (a, b, len); +} + static inline bool hb_unsigned_mul_overflows (unsigned int count, unsigned int size) { @@ -535,11 +546,7 @@ struct hb_bytes_t { if (len != a.len) return (int) a.len - (int) len; - - if (!len) - return 0; /* glibc's memcmp() declares args non-NULL, and UBSan doesn't like that. :( */ - - return memcmp (a.arrayZ, arrayZ, len); + return hb_memcmp (a.arrayZ, arrayZ, len); } static inline int cmp (const void *pa, const void *pb) { diff --git a/src/hb-face.cc b/src/hb-face.cc index da73433cb..3294ed4c4 100644 --- a/src/hb-face.cc +++ b/src/hb-face.cc @@ -87,8 +87,8 @@ DEFINE_NULL_INSTANCE (hb_face_t) = nullptr, /* destroy */ 0, /* index */ - 1000, /* upem */ - 0, /* num_glyphs */ + HB_ATOMIC_INT_INIT (1000), /* upem */ + HB_ATOMIC_INT_INIT (0), /* num_glyphs */ { #define HB_SHAPER_IMPLEMENT(shaper) HB_ATOMIC_PTR_INIT (HB_SHAPER_DATA_INVALID), @@ -129,7 +129,7 @@ hb_face_create_for_tables (hb_reference_table_func_t reference_table_func, face->user_data = user_data; face->destroy = destroy; - face->num_glyphs = (unsigned int) -1; + face->num_glyphs.set_relaxed (-1); face->table.init0 (face); @@ -445,7 +445,7 @@ hb_face_set_upem (hb_face_t *face, if (hb_object_is_immutable (face)) return; - face->upem = upem; + face->upem.set_relaxed (upem); } /** @@ -480,7 +480,7 @@ hb_face_set_glyph_count (hb_face_t *face, if (hb_object_is_immutable (face)) return; - face->num_glyphs = glyph_count; + face->num_glyphs.set_relaxed (glyph_count); } /** diff --git a/src/hb-face.hh b/src/hb-face.hh index 5d22f4ada..002fb2cb7 100644 --- a/src/hb-face.hh +++ b/src/hb-face.hh @@ -49,8 +49,8 @@ struct hb_face_t hb_destroy_func_t destroy; unsigned int index; /* Face index in a collection, zero-based. */ - mutable unsigned int upem; /* Units-per-EM. */ - mutable unsigned int num_glyphs; /* Number of glyphs. */ + mutable hb_atomic_int_t upem; /* Units-per-EM. */ + mutable hb_atomic_int_t num_glyphs; /* Number of glyphs. */ struct hb_shaper_data_t shaper_data; /* Various shaper data. */ @@ -80,21 +80,25 @@ struct hb_face_t inline HB_PURE_FUNC unsigned int get_upem (void) const { - if (unlikely (!upem)) - load_upem (); - return upem; + unsigned int ret = upem.get_relaxed (); + if (unlikely (!ret)) + { + return load_upem (); + } + return ret; } inline unsigned int get_num_glyphs (void) const { - if (unlikely (num_glyphs == (unsigned int) -1)) - load_num_glyphs (); - return num_glyphs; + unsigned int ret = num_glyphs.get_relaxed (); + if (unlikely (ret == (unsigned int) -1)) + return load_num_glyphs (); + return ret; } private: - HB_INTERNAL void load_upem (void) const; - HB_INTERNAL void load_num_glyphs (void) const; + HB_INTERNAL unsigned int load_upem (void) const; + HB_INTERNAL unsigned int load_num_glyphs (void) const; }; DECLARE_NULL_INSTANCE (hb_face_t); diff --git a/src/hb-machinery.hh b/src/hb-machinery.hh index 9e4c16d81..ffc9627fd 100644 --- a/src/hb-machinery.hh +++ b/src/hb-machinery.hh @@ -298,7 +298,8 @@ struct hb_sanitize_context_t : this->start = this->end = nullptr; } - inline bool check_range (const void *base, unsigned int len) const + inline bool check_range (const void *base, + unsigned int len) const { const char *p = (const char *) base; bool ok = this->start <= p && @@ -316,20 +317,37 @@ struct hb_sanitize_context_t : } template - inline bool check_array (const T *base, unsigned int len, unsigned int record_size = T::static_size) const + inline bool check_range (const T *base, + unsigned int a, + unsigned int b) const { - const char *p = (const char *) base; - bool overflows = hb_unsigned_mul_overflows (len, record_size); - unsigned int array_size = record_size * len; - bool ok = !overflows && this->check_range (base, array_size); + return !hb_unsigned_mul_overflows (a, b) && + this->check_range (base, a * b); + } - DEBUG_MSG_LEVEL (SANITIZE, p, this->debug_depth+1, 0, - "check_array [%p..%p] (%d*%d=%d bytes) in [%p..%p] -> %s", - p, p + (record_size * len), record_size, len, (unsigned int) array_size, - this->start, this->end, - overflows ? "OVERFLOWS" : ok ? "OK" : "OUT-OF-RANGE"); + template + inline bool check_range (const T *base, + unsigned int a, + unsigned int b, + unsigned int c) const + { + return !hb_unsigned_mul_overflows (a, b) && + this->check_range (base, a * b, c); + } - return likely (ok); + template + inline bool check_array (const T *base, + unsigned int len) const + { + return this->check_range (base, len, T::static_size); + } + + template + inline bool check_array (const T *base, + unsigned int a, + unsigned int b) const + { + return this->check_range (base, a, b, T::static_size); } template @@ -734,16 +752,19 @@ struct hb_data_wrapper_t return *(((Data **) (void *) this) - WheresData); } + inline bool is_inert (void) const { return !get_data (); } + template inline Stored * call_create (void) const { - Data *data = this->get_data (); - return likely (data) ? Subclass::create (data) : nullptr; + return Subclass::create (this->get_data ()); } }; template <> struct hb_data_wrapper_t { + inline bool is_inert (void) const { return false; } + template inline Stored * call_create (void) const { @@ -782,7 +803,7 @@ struct hb_lazy_loader_t : hb_data_wrapper_t static inline void do_destroy (Stored *p) { - if (p) + if (p && p != const_cast (Funcs::get_null ())) Funcs::destroy (p); } @@ -796,9 +817,12 @@ struct hb_lazy_loader_t : hb_data_wrapper_t Stored *p = this->instance.get (); if (unlikely (!p)) { + if (unlikely (this->is_inert ())) + return const_cast (Funcs::get_null ()); + p = this->template call_create (); if (unlikely (!p)) - return const_cast (Funcs::get_null ()); + p = const_cast (Funcs::get_null ()); if (unlikely (!this->instance.cmpexch (nullptr, p))) { diff --git a/src/hb-mutex.hh b/src/hb-mutex.hh index 75b89addb..b529091d4 100644 --- a/src/hb-mutex.hh +++ b/src/hb-mutex.hh @@ -48,7 +48,7 @@ /* Defined externally, i.e. in config.h; must have typedef'ed hb_mutex_impl_t as well. */ -#elif !defined(HB_NO_MT) && (defined(_WIN32) || defined(__CYGWIN__)) +#elif !defined(HB_NO_MT) && defined(_WIN32) #include typedef CRITICAL_SECTION hb_mutex_impl_t; diff --git a/src/hb-object.hh b/src/hb-object.hh index 74340c555..cdacf49f4 100644 --- a/src/hb-object.hh +++ b/src/hb-object.hh @@ -194,7 +194,7 @@ struct hb_user_data_array_t struct hb_object_header_t { hb_reference_count_t ref_count; - hb_atomic_int_t writable; + mutable hb_atomic_int_t writable; hb_atomic_ptr_t user_data; }; #define HB_OBJECT_HEADER_STATIC \ diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh index 14506180f..3f8e2c08a 100644 --- a/src/hb-open-type.hh +++ b/src/hb-open-type.hh @@ -887,7 +887,9 @@ struct VarSizedBinSearchArrayOf TRACE_SANITIZE (this); return_trace (header.sanitize (c) && Type::static_size <= header.unitSize && - c->check_array (bytesZ.arrayZ, header.nUnits, header.unitSize)); + c->check_range (bytesZ.arrayZ, + header.nUnits, + header.unitSize)); } protected: diff --git a/src/hb-ot-cff-common.hh b/src/hb-ot-cff-common.hh index f9f7fdeb5..db4b46dfa 100644 --- a/src/hb-ot-cff-common.hh +++ b/src/hb-ot-cff-common.hh @@ -91,7 +91,7 @@ struct CFFIndex return_trace (likely ((count.sanitize (c) && count == 0) || /* empty INDEX */ (c->check_struct (this) && offSize >= 1 && offSize <= 4 && c->check_array (offsets, offSize, count + 1) && - c->check_array (data_base (), 1, max_offset () - 1)))); + c->check_array ((const HBUINT8*)data_base (), 1, max_offset () - 1)))); } inline static unsigned int calculate_offset_array_size (unsigned int offSize, unsigned int count) diff --git a/src/hb-ot-color-sbix-table.hh b/src/hb-ot-color-sbix-table.hh index 80d65022c..08dee2a0c 100644 --- a/src/hb-ot-color-sbix-table.hh +++ b/src/hb-ot-color-sbix-table.hh @@ -249,7 +249,7 @@ struct sbix /* Convert to font units. */ if (strike_ppem) { - double scale = font->face->upem / (double) strike_ppem; + double scale = font->face->get_upem () / (double) strike_ppem; extents->x_bearing = round (extents->x_bearing * scale); extents->y_bearing = round (extents->y_bearing * scale); extents->width = round (extents->width * scale); diff --git a/src/hb-ot-color.cc b/src/hb-ot-color.cc index cac289b27..791135b10 100644 --- a/src/hb-ot-color.cc +++ b/src/hb-ot-color.cc @@ -238,7 +238,7 @@ hb_ot_color_has_svg (hb_face_t *face) * @face: a font face. * @glyph: a svg glyph index. * - * Get SVG document for a glyph. + * Get SVG document for a glyph. The blob may be either plain text or gzip-encoded. * * Returns: (transfer full): respective svg blob of the glyph, if available. * diff --git a/src/hb-ot-face.hh b/src/hb-ot-face.hh index 61f85e1c9..7cefdb765 100644 --- a/src/hb-ot-face.hh +++ b/src/hb-ot-face.hh @@ -40,6 +40,7 @@ #define HB_OT_TABLES \ /* OpenType fundamentals. */ \ + HB_OT_TABLE(OT, head) \ HB_OT_ACCELERATOR(OT, cmap) \ HB_OT_ACCELERATOR(OT, hmtx) \ HB_OT_ACCELERATOR(OT, vmtx) \ @@ -50,6 +51,8 @@ HB_OT_ACCELERATOR(OT, cff2) \ HB_OT_TABLE(OT, VORG) \ HB_OT_ACCELERATOR(OT, name) \ + HB_OT_TABLE(OT, OS2) \ + HB_OT_TABLE(OT, STAT) \ /* OpenType shaping. */ \ HB_OT_ACCELERATOR(OT, GDEF) \ HB_OT_ACCELERATOR(OT, GSUB) \ diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 44b5a48c1..4ddee4f86 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -33,12 +33,14 @@ #include "hb-ot-face.hh" #include "hb-ot-cmap-table.hh" -#include "hb-ot-hmtx-table.hh" -#include "hb-ot-kern-table.hh" -#include "hb-ot-post-table.hh" #include "hb-ot-glyf-table.hh" #include "hb-ot-cff1-table.hh" #include "hb-ot-cff2-table.hh" +#include "hb-ot-hmtx-table.hh" +#include "hb-ot-kern-table.hh" +#include "hb-ot-os2-table.hh" +#include "hb-ot-post-table.hh" +#include "hb-ot-stat-table.hh" // Just so we compile it; unused otherwise. #include "hb-ot-vorg-table.hh" #include "hb-ot-color-cbdt-table.hh" #include "hb-ot-color-sbix-table.hh" diff --git a/src/hb-ot-glyf-table.hh b/src/hb-ot-glyf-table.hh index 42bb03ff8..4fdbced4a 100644 --- a/src/hb-ot-glyf-table.hh +++ b/src/hb-ot-glyf-table.hh @@ -235,16 +235,11 @@ struct glyf { memset (this, 0, sizeof (accelerator_t)); - hb_blob_t *head_blob = hb_sanitize_context_t().reference_table (face); - const head *head_table = head_blob->as (); - if (head_table->indexToLocFormat > 1 || head_table->glyphDataFormat != 0) - { + const OT::head &head = *face->table.head; + if (head.indexToLocFormat > 1 || head.glyphDataFormat != 0) /* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */ - hb_blob_destroy (head_blob); return; - } - short_offset = 0 == head_table->indexToLocFormat; - hb_blob_destroy (head_blob); + short_offset = 0 == head.indexToLocFormat; loca_table = hb_sanitize_context_t().reference_table (face); glyf_table = hb_sanitize_context_t().reference_table (face); diff --git a/src/hb-ot-hmtx-table.hh b/src/hb-ot-hmtx-table.hh index 20948edbf..e2f55579e 100644 --- a/src/hb-ot-hmtx-table.hh +++ b/src/hb-ot-hmtx-table.hh @@ -194,17 +194,14 @@ struct hmtxvmtx bool got_font_extents = false; if (T::os2Tag) { - hb_blob_t *os2_blob = hb_sanitize_context_t().reference_table (face); - const OS2 *os2_table = os2_blob->as (); #define USE_TYPO_METRICS (1u<<7) - if (0 != (os2_table->fsSelection & USE_TYPO_METRICS)) + if (0 != (face->table.OS2->fsSelection & USE_TYPO_METRICS)) { - ascender = abs (os2_table->sTypoAscender); - descender = -abs (os2_table->sTypoDescender); - line_gap = os2_table->sTypoLineGap; + ascender = abs (face->table.OS2->sTypoAscender); + descender = -abs (face->table.OS2->sTypoDescender); + line_gap = face->table.OS2->sTypoLineGap; got_font_extents = (ascender | descender) != 0; } - hb_blob_destroy (os2_blob); } hb_blob_t *_hea_blob = hb_sanitize_context_t().reference_table (face); @@ -289,9 +286,9 @@ struct hmtxvmtx public: bool has_font_extents; - unsigned short ascender; - unsigned short descender; - unsigned short line_gap; + int ascender; + int descender; + int line_gap; protected: unsigned int num_metrics; diff --git a/src/hb-ot-layout-common.hh b/src/hb-ot-layout-common.hh index ef4a9bf21..828bd8a7e 100644 --- a/src/hb-ot-layout-common.hh +++ b/src/hb-ot-layout-common.hh @@ -1584,8 +1584,9 @@ struct VarData return_trace (c->check_struct (this) && regionIndices.sanitize(c) && shortCount <= regionIndices.len && - c->check_array (&StructAfter (regionIndices), - itemCount, get_row_size ())); + c->check_range (&StructAfter (regionIndices), + itemCount, + get_row_size ())); } protected: diff --git a/src/hb-ot-layout-gpos-table.hh b/src/hb-ot-layout-gpos-table.hh index cf735c301..fb6f6d0f6 100644 --- a/src/hb-ot-layout-gpos-table.hh +++ b/src/hb-ot-layout-gpos-table.hh @@ -207,7 +207,7 @@ struct ValueFormat : HBUINT16 TRACE_SANITIZE (this); unsigned int len = get_len (); - if (!c->check_array (values, count, get_size ())) return_trace (false); + if (!c->check_range (values, count, get_size ())) return_trace (false); if (!has_device ()) return_trace (true); @@ -706,7 +706,10 @@ struct PairSet { TRACE_SANITIZE (this); if (!(c->check_struct (this) - && c->check_array (&firstPairValueRecord, len, HBUINT16::static_size * closure->stride))) return_trace (false); + && c->check_range (&firstPairValueRecord, + len, + HBUINT16::static_size, + closure->stride))) return_trace (false); unsigned int count = len; const PairValueRecord *record = &firstPairValueRecord; @@ -879,7 +882,9 @@ struct PairPosFormat2 unsigned int stride = len1 + len2; unsigned int record_size = valueFormat1.get_size () + valueFormat2.get_size (); unsigned int count = (unsigned int) class1Count * (unsigned int) class2Count; - return_trace (c->check_array ((const void *) values, count, record_size) && + return_trace (c->check_range ((const void *) values, + count, + record_size) && valueFormat1.sanitize_values_stride_unsafe (c, this, &values[0], count, stride) && valueFormat2.sanitize_values_stride_unsafe (c, this, &values[len1], count, stride)); } diff --git a/src/hb-ot-map.cc b/src/hb-ot-map.cc index fd8109950..95f794ab4 100644 --- a/src/hb-ot-map.cc +++ b/src/hb-ot-map.cc @@ -27,7 +27,7 @@ */ #include "hb-ot-map.hh" - +#include "hb-ot-shape.hh" #include "hb-ot-layout.hh" @@ -143,9 +143,8 @@ void hb_ot_map_builder_t::add_pause (unsigned int table_index, hb_ot_map_t::paus } void -hb_ot_map_builder_t::compile (hb_ot_map_t &m, - const int *coords, - unsigned int num_coords) +hb_ot_map_builder_t::compile (hb_ot_map_t &m, + const hb_ot_shape_plan_key_t &key) { static_assert ((!(HB_GLYPH_FLAG_DEFINED & (HB_GLYPH_FLAG_DEFINED + 1))), ""); unsigned int global_bit_mask = HB_GLYPH_FLAG_DEFINED + 1; @@ -282,13 +281,6 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, { /* Collect lookup indices for features */ - unsigned int variations_index; - hb_ot_layout_table_find_feature_variations (face, - table_tags[table_index], - coords, - num_coords, - &variations_index); - unsigned int stage_index = 0; unsigned int last_num_lookups = 0; for (unsigned stage = 0; stage < current_stage[table_index]; stage++) @@ -297,14 +289,14 @@ hb_ot_map_builder_t::compile (hb_ot_map_t &m, required_feature_stage[table_index] == stage) add_lookups (m, table_index, required_feature_index[table_index], - variations_index, + key.variations_index[table_index], global_bit_mask); for (unsigned i = 0; i < m.features.len; i++) if (m.features[i].stage[table_index] == stage) add_lookups (m, table_index, m.features[i].index[table_index], - variations_index, + key.variations_index[table_index], m.features[i].mask, m.features[i].auto_zwnj, m.features[i].auto_zwj, diff --git a/src/hb-ot-map.hh b/src/hb-ot-map.hh index fde85b1dd..8e1f5aa8c 100644 --- a/src/hb-ot-map.hh +++ b/src/hb-ot-map.hh @@ -188,6 +188,7 @@ struct hb_ot_map_feature_t hb_ot_map_feature_flags_t flags; }; +struct hb_ot_shape_plan_key_t; struct hb_ot_map_builder_t { @@ -218,9 +219,8 @@ struct hb_ot_map_builder_t inline void add_gpos_pause (hb_ot_map_t::pause_func_t pause_func) { add_pause (1, pause_func); } - HB_INTERNAL void compile (hb_ot_map_t &m, - const int *coords, - unsigned int num_coords); + HB_INTERNAL void compile (hb_ot_map_t &m, + const hb_ot_shape_plan_key_t &key); private: diff --git a/src/hb-ot-shape-complex-arabic-fallback.hh b/src/hb-ot-shape-complex-arabic-fallback.hh index 0fb3793e2..5be6f8d69 100644 --- a/src/hb-ot-shape-complex-arabic-fallback.hh +++ b/src/hb-ot-shape-complex-arabic-fallback.hh @@ -202,7 +202,7 @@ struct arabic_fallback_plan_t OT::hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS]; }; -#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_NO_WIN1256) +#if defined(_WIN32) && !defined(HB_NO_WIN1256) #define HB_WITH_WIN1256 #endif diff --git a/src/hb-ot-shape-complex-use-table.cc b/src/hb-ot-shape-complex-use-table.cc index e9c88aec4..bfc92d3b5 100644 --- a/src/hb-ot-shape-complex-use-table.cc +++ b/src/hb-ot-shape-complex-use-table.cc @@ -582,7 +582,7 @@ static const USE_TABLE_ELEMENT_TYPE use_table[] = { /* 11310 */ B, O, O, B, B, B, B, B, B, B, B, B, B, B, B, B, /* 11320 */ B, B, B, B, B, B, B, B, B, O, B, B, B, B, B, B, /* 11330 */ B, O, B, B, O, B, B, B, B, B, O, CMBlw, CMBlw, B, VPst, VPst, - /* 11340 */ VAbv, VPst, VPst, VPst, VPst, O, O, VPre, VPre, O, O, VPst, VPst, H, O, O, + /* 11340 */ VAbv, VPst, VPst, VPst, VPst, O, O, VPre, VPre, O, O, VPst, VPst, HVM, O, O, /* 11350 */ O, O, O, O, O, O, O, VPst, O, O, O, O, O, O, B, B, /* 11360 */ B, B, VPst, VPst, O, O, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, /* 11370 */ VMAbv, VMAbv, VMAbv, VMAbv, VMAbv, O, O, O, diff --git a/src/hb-ot-shape.cc b/src/hb-ot-shape.cc index 44cf39078..a383b7823 100644 --- a/src/hb-ot-shape.cc +++ b/src/hb-ot-shape.cc @@ -53,7 +53,6 @@ static void hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, - const hb_segment_properties_t *props, const hb_feature_t *user_features, unsigned int num_user_features); @@ -68,26 +67,26 @@ _hb_apply_morx (hb_face_t *face) hb_aat_layout_has_substitution (face); } -hb_ot_shape_planner_t::hb_ot_shape_planner_t (const hb_shape_plan_t *master_plan) : - face (master_plan->face_unsafe), - props (master_plan->props), - map (face, &props), - aat_map (face, &props), +hb_ot_shape_planner_t::hb_ot_shape_planner_t (hb_face_t *face, + const hb_segment_properties_t *props) : + face (face), + props (*props), + map (face, props), + aat_map (face, props), apply_morx (_hb_apply_morx (face)), shaper (apply_morx ? &_hb_ot_complex_shaper_default : hb_ot_shape_complex_categorize (this)) {} void -hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, - const int *coords, - unsigned int num_coords) +hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, + const hb_ot_shape_plan_key_t &key) { plan.props = props; plan.shaper = shaper; - map.compile (plan.map, coords, num_coords); + map.compile (plan.map, key); if (apply_morx) - aat_map.compile (plan.aat_map, coords, num_coords); + aat_map.compile (plan.aat_map); plan.frac_mask = plan.map.get_1_mask (HB_TAG ('f','r','a','c')); plan.numr_mask = plan.map.get_1_mask (HB_TAG ('n','u','m','r')); @@ -139,30 +138,28 @@ hb_ot_shape_planner_t::compile (hb_ot_shape_plan_t &plan, } bool has_kern_mark = plan.apply_kern && hb_ot_layout_has_cross_kerning (face); - plan.zero_marks = !plan.apply_kerx && !has_kern_mark; + plan.zero_marks = !plan.apply_morx && !plan.apply_kerx && !has_kern_mark; plan.has_gpos_mark = !!plan.map.get_1_mask (HB_TAG ('m','a','r','k')); - plan.fallback_mark_positioning = !plan.apply_gpos && !plan.apply_kerx && !has_kern_mark; + plan.fallback_mark_positioning = !plan.apply_gpos && plan.zero_marks; /* Currently we always apply trak. */ plan.apply_trak = plan.requested_tracking && hb_aat_layout_has_tracking (face); } bool -hb_ot_shape_plan_t::init0 (hb_shape_plan_t *shape_plan, - const hb_feature_t *user_features, - unsigned int num_user_features, - const int *coords, - unsigned int num_coords) +hb_ot_shape_plan_t::init0 (hb_face_t *face, + const hb_shape_plan_key_t *key) { map.init (); aat_map.init (); - hb_ot_shape_planner_t planner (shape_plan); + hb_ot_shape_planner_t planner (face, + &key->props); + hb_ot_shape_collect_features (&planner, + key->user_features, + key->num_user_features); - hb_ot_shape_collect_features (&planner, &shape_plan->props, - user_features, num_user_features); - - planner.compile (*this, coords, num_coords); + planner.compile (*this, key->ot); if (shaper->data_create) { @@ -209,7 +206,6 @@ horizontal_features[] = static void hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, - const hb_segment_properties_t *props, const hb_feature_t *user_features, unsigned int num_user_features) { @@ -218,7 +214,7 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, map->enable_feature (HB_TAG('r','v','r','n')); map->add_gsub_pause (nullptr); - switch (props->direction) { + switch (planner->props.direction) { case HB_DIRECTION_LTR: map->enable_feature (HB_TAG ('l','t','r','a')); map->enable_feature (HB_TAG ('l','t','r','m')); @@ -257,7 +253,7 @@ hb_ot_shape_collect_features (hb_ot_shape_planner_t *planner, for (unsigned int i = 0; i < ARRAY_LENGTH (common_features); i++) map->add_feature (common_features[i]); - if (HB_DIRECTION_IS_HORIZONTAL (props->direction)) + if (HB_DIRECTION_IS_HORIZONTAL (planner->props.direction)) for (unsigned int i = 0; i < ARRAY_LENGTH (horizontal_features); i++) map->add_feature (horizontal_features[i]); else diff --git a/src/hb-ot-shape.hh b/src/hb-ot-shape.hh index 049830a66..b35f243ef 100644 --- a/src/hb-ot-shape.hh +++ b/src/hb-ot-shape.hh @@ -33,6 +33,31 @@ #include "hb-aat-map.hh" +struct hb_ot_shape_plan_key_t +{ + unsigned int variations_index[2]; + + inline void init (hb_face_t *face, + const int *coords, + unsigned int num_coords) + { + for (unsigned int table_index = 0; table_index < 2; table_index++) + hb_ot_layout_table_find_feature_variations (face, + table_tags[table_index], + coords, + num_coords, + &variations_index[table_index]); + } + + inline bool equal (const hb_ot_shape_plan_key_t *other) + { + return 0 == memcmp (this, other, sizeof (*this)); + } +}; + + +struct hb_shape_plan_key_t; + struct hb_ot_shape_plan_t { hb_segment_properties_t props; @@ -73,12 +98,8 @@ struct hb_ot_shape_plan_t inline void substitute (hb_font_t *font, hb_buffer_t *buffer) const { map.substitute (this, font, buffer); } inline void position (hb_font_t *font, hb_buffer_t *buffer) const { map.position (this, font, buffer); } - HB_INTERNAL bool init0 (hb_shape_plan_t *shape_plan, - const hb_feature_t *user_features, - unsigned int num_user_features, - const int *coords, - unsigned int num_coords); - + HB_INTERNAL bool init0 (hb_face_t *face, + const hb_shape_plan_key_t *key); HB_INTERNAL void fini (void); }; @@ -94,11 +115,11 @@ struct hb_ot_shape_planner_t bool apply_morx : 1; const struct hb_ot_complex_shaper_t *shaper; - HB_INTERNAL hb_ot_shape_planner_t (const hb_shape_plan_t *master_plan); + HB_INTERNAL hb_ot_shape_planner_t (hb_face_t *face, + const hb_segment_properties_t *props); - HB_INTERNAL void compile (hb_ot_shape_plan_t &plan, - const int *coords, - unsigned int num_coords); + HB_INTERNAL void compile (hb_ot_shape_plan_t &plan, + const hb_ot_shape_plan_key_t &key); }; diff --git a/src/hb-ot-stat-table.hh b/src/hb-ot-stat-table.hh new file mode 100644 index 000000000..02c376e5d --- /dev/null +++ b/src/hb-ot-stat-table.hh @@ -0,0 +1,280 @@ +/* + * 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. + */ + +#ifndef HB_OT_STAT_TABLE_HH +#define HB_OT_STAT_TABLE_HH + +#include "hb-open-type.hh" +#include "hb-ot-layout-common.hh" + +/* + * STAT -- Style Attributes + * https://docs.microsoft.com/en-us/typography/opentype/spec/stat + */ +#define HB_OT_TAG_STAT HB_TAG('S','T','A','T') + + +namespace OT { + +enum +{ + OLDER_SIBLING_FONT_ATTRIBUTE = 0x0001, /* If set, this axis value table + * provides axis value information + * that is applicable to other fonts + * within the same font family. This + * is used if the other fonts were + * released earlier and did not include + * information about values for some axis. + * If newer versions of the other + * fonts include the information + * themselves and are present, + * then this record is ignored. */ + ELIDABLE_AXIS_VALUE_NAME = 0x0002 /* If set, it indicates that the axis + * value represents the “normal” value + * for the axis and may be omitted when + * composing name strings. */ + // Reserved = 0xFFFC /* Reserved for future use — set to zero. */ +}; + +struct StatAxisRecord +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this))); + } + + protected: + Tag axisTag; /* A tag identifying the axis of design variation. */ + NameID axisNameID; /* The name ID for entries in the 'name' table that + * provide a display string for this axis. */ + HBUINT16 axisOrdering; /* A value that applications can use to determine + * primary sorting of face names, or for ordering + * of descriptors when composing family or face names. */ + public: + DEFINE_SIZE_STATIC (8); +}; + +struct AxisValueFormat1 +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this))); + } + + protected: + HBUINT16 format; /* Format identifier — set to 1. */ + HBUINT16 axisIndex; /* Zero-base index into the axis record array + * identifying the axis of design variation + * to which the axis value record applies. + * Must be less than designAxisCount. */ + HBUINT16 flags; /* Flags — see below for details. */ + NameID valueNameID; /* The name ID for entries in the 'name' table + * that provide a display string for this + * attribute value. */ + Fixed value; /* A numeric value for this attribute value. */ + public: + DEFINE_SIZE_STATIC (12); +}; + +struct AxisValueFormat2 +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this))); + } + + protected: + HBUINT16 format; /* Format identifier — set to 2. */ + HBUINT16 axisIndex; /* Zero-base index into the axis record array + * identifying the axis of design variation + * to which the axis value record applies. + * Must be less than designAxisCount. */ + HBUINT16 flags; /* Flags — see below for details. */ + NameID valueNameID; /* The name ID for entries in the 'name' table + * that provide a display string for this + * attribute value. */ + Fixed nominalValue; /* A numeric value for this attribute value. */ + Fixed rangeMinValue; /* The minimum value for a range associated + * with the specified name ID. */ + Fixed rangeMaxValue; /* The maximum value for a range associated + * with the specified name ID. */ + public: + DEFINE_SIZE_STATIC (20); +}; + +struct AxisValueFormat3 +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this))); + } + + protected: + HBUINT16 format; /* Format identifier — set to 3. */ + HBUINT16 axisIndex; /* Zero-base index into the axis record array + * identifying the axis of design variation + * to which the axis value record applies. + * Must be less than designAxisCount. */ + HBUINT16 flags; /* Flags — see below for details. */ + NameID valueNameID; /* The name ID for entries in the 'name' table + * that provide a display string for this + * attribute value. */ + Fixed value; /* A numeric value for this attribute value. */ + Fixed linkedValue; /* The numeric value for a style-linked mapping + * from this value. */ + public: + DEFINE_SIZE_STATIC (16); +}; + +struct AxisValueRecord +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this))); + } + + protected: + HBUINT16 axisIndex; /* Zero-base index into the axis record array + * identifying the axis to which this value + * applies. Must be less than designAxisCount. */ + Fixed value; /* A numeric value for this attribute value. */ + public: + DEFINE_SIZE_STATIC (6); +}; + +struct AxisValueFormat4 +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this))); + } + + protected: + HBUINT16 format; /* Format identifier — set to 4. */ + HBUINT16 axisCount; /* The total number of axes contributing to + * this axis-values combination. */ + HBUINT16 flags; /* Flags — see below for details. */ + NameID valueNameID; /* The name ID for entries in the 'name' table + * that provide a display string for this + * attribute value. */ + UnsizedArrayOf + axisValues; /* Array of AxisValue records that provide the + * combination of axis values, one for each + * contributing axis. */ + public: + DEFINE_SIZE_ARRAY (8, axisValues); +}; + +struct AxisValue +{ + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + if (unlikely (c->check_struct (this))) + return_trace (false); + + switch (u.format) + { + case 1: return_trace (likely (u.format1.sanitize (c))); + case 2: return_trace (likely (u.format2.sanitize (c))); + case 3: return_trace (likely (u.format3.sanitize (c))); + case 4: return_trace (likely (u.format4.sanitize (c))); + default: return_trace (true); + } + } + + protected: + union + { + HBUINT16 format; + AxisValueFormat1 format1; + AxisValueFormat2 format2; + AxisValueFormat3 format3; + AxisValueFormat4 format4; + } u; + public: + DEFINE_SIZE_UNION (2, format); +}; + +struct STAT +{ + static const hb_tag_t tableTag = HB_OT_TAG_STAT; + + inline bool sanitize (hb_sanitize_context_t *c) const + { + TRACE_SANITIZE (this); + return_trace (likely (c->check_struct (this) && + majorVersion == 1 && + minorVersion > 0 && + designAxesOffset.sanitize (c, this, designAxisCount) && + offsetToAxisValueOffsets.sanitize (c, this, axisValueCount, &(this+offsetToAxisValueOffsets)))); + } + + protected: + HBUINT16 majorVersion; /* Major version number of the style attributes + * table — set to 1. */ + HBUINT16 minorVersion; /* Minor version number of the style attributes + * table — set to 2. */ + HBUINT16 designAxisSize; /* The size in bytes of each axis record. */ + HBUINT16 designAxisCount;/* The number of design axis records. In a + * font with an 'fvar' table, this value must be + * greater than or equal to the axisCount value + * in the 'fvar' table. In all fonts, must + * be greater than zero if axisValueCount + * is greater than zero. */ + LOffsetTo, false> + designAxesOffset; + /* Offset in bytes from the beginning of + * the STAT table to the start of the design + * axes array. If designAxisCount is zero, + * set to zero; if designAxisCount is greater + * than zero, must be greater than zero. */ + HBUINT16 axisValueCount; /* The number of axis value tables. */ + LOffsetTo >, false> + offsetToAxisValueOffsets; + /* Offset in bytes from the beginning of + * the STAT table to the start of the design + * axes value offsets array. If axisValueCount + * is zero, set to zero; if axisValueCount is + * greater than zero, must be greater than zero. */ + NameID elidedFallbackNameID; + /* Name ID used as fallback when projection of + * names into a particular font model produces + * a subfamily name containing only elidable + * elements. */ + public: + DEFINE_SIZE_STATIC (20); +}; + + +} /* namespace OT */ + + +#endif /* HB_OT_STAT_TABLE_HH */ diff --git a/src/hb-ot-var-hvar-table.hh b/src/hb-ot-var-hvar-table.hh index 66e086e1d..62a6547b5 100644 --- a/src/hb-ot-var-hvar-table.hh +++ b/src/hb-ot-var-hvar-table.hh @@ -39,7 +39,9 @@ struct DeltaSetIndexMap { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - c->check_array (mapDataZ.arrayZ, mapCount, get_width ())); + c->check_range (mapDataZ.arrayZ, + mapCount, + get_width ())); } unsigned int map (unsigned int v) const /* Returns 16.16 outer.inner. */ diff --git a/src/hb-ot-var-mvar-table.hh b/src/hb-ot-var-mvar-table.hh index 5d6b55954..b16a09b3d 100644 --- a/src/hb-ot-var-mvar-table.hh +++ b/src/hb-ot-var-mvar-table.hh @@ -68,7 +68,9 @@ struct MVAR c->check_struct (this) && valueRecordSize >= VariationValueRecord::static_size && varStore.sanitize (c, this) && - c->check_array (valuesZ.arrayZ, valueRecordCount, valueRecordSize)); + c->check_range (valuesZ.arrayZ, + valueRecordCount, + valueRecordSize)); } inline float get_var (hb_tag_t tag, diff --git a/src/hb-set.hh b/src/hb-set.hh index c47f77b70..bc26ed3c0 100644 --- a/src/hb-set.hh +++ b/src/hb-set.hh @@ -90,7 +90,7 @@ struct hb_set_t inline bool is_equal (const page_t *other) const { - return 0 == memcmp (&v, &other->v, sizeof (v)); + return 0 == hb_memcmp (&v, &other->v, sizeof (v)); } inline unsigned int get_population (void) const diff --git a/src/hb-shape-plan.cc b/src/hb-shape-plan.cc index 2a2e0e39c..acb589ad3 100644 --- a/src/hb-shape-plan.cc +++ b/src/hb-shape-plan.cc @@ -44,42 +44,59 @@ **/ -static void -hb_shape_plan_plan (hb_shape_plan_t *shape_plan, - const hb_feature_t *user_features, - unsigned int num_user_features, - const int *coords, - unsigned int num_coords, - const char * const *shaper_list) -{ - DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan, - "num_features=%d num_coords=%d shaper_list=%p", - num_user_features, - num_coords, - shaper_list); +/* + * hb_shape_plan_key_t + */ - const hb_shaper_pair_t *shapers = _hb_shapers_get (); +bool +hb_shape_plan_key_t::init (bool copy, + hb_face_t *face, + const hb_segment_properties_t *props, + const hb_feature_t *user_features, + unsigned int num_user_features, + const int *coords, + unsigned int num_coords, + const char * const *shaper_list) +{ + hb_feature_t *features = nullptr; + if (copy && num_user_features && !(features = (hb_feature_t *) calloc (num_user_features, sizeof (hb_feature_t)))) + goto bail; + + this->props = *props; + this->num_user_features = num_user_features; + this->user_features = copy ? features : user_features; + if (copy && num_user_features) + { + memcpy (features, user_features, num_user_features * sizeof (hb_feature_t)); + /* Make start/end uniform to easier catch bugs. */ + for (unsigned int i = 0; i < num_user_features; i++) + { + if (features[0].start != HB_FEATURE_GLOBAL_START) + features[0].start = 1; + if (features[0].end != HB_FEATURE_GLOBAL_END) + features[0].end = 2; + } + } + this->shaper_func = nullptr; + this->shaper_name = nullptr; + this->ot.init (face, coords, num_coords); + + /* + * Choose shaper. + */ #define HB_SHAPER_PLAN(shaper) \ HB_STMT_START { \ - if (hb_##shaper##_shaper_face_data_ensure (shape_plan->face_unsafe)) \ + if (hb_##shaper##_shaper_face_data_ensure (face)) \ { \ - shape_plan->shaper_func = _hb_##shaper##_shape; \ - shape_plan->shaper_name = #shaper; \ - return; \ + this->shaper_func = _hb_##shaper##_shape; \ + this->shaper_name = #shaper; \ + return true; \ } \ } HB_STMT_END - if (likely (!shaper_list)) { - for (unsigned int i = 0; i < HB_SHAPERS_COUNT; i++) - if (false) - ; -#define HB_SHAPER_IMPLEMENT(shaper) \ - else if (shapers[i].func == _hb_##shaper##_shape) \ - HB_SHAPER_PLAN (shaper); -#include "hb-shaper-list.hh" -#undef HB_SHAPER_IMPLEMENT - } else { + if (unlikely (shaper_list)) + { for (; *shaper_list; shaper_list++) if (false) ; @@ -89,8 +106,50 @@ hb_shape_plan_plan (hb_shape_plan_t *shape_plan, #include "hb-shaper-list.hh" #undef HB_SHAPER_IMPLEMENT } - + else + { + const hb_shaper_pair_static_t *shapers = _hb_shapers_get (); + for (unsigned int i = 0; i < HB_SHAPERS_COUNT; i++) + if (false) + ; +#define HB_SHAPER_IMPLEMENT(shaper) \ + else if (shapers[i].func == _hb_##shaper##_shape) \ + HB_SHAPER_PLAN (shaper); +#include "hb-shaper-list.hh" +#undef HB_SHAPER_IMPLEMENT + } #undef HB_SHAPER_PLAN + +bail: + ::free (features); + return false; +} + +bool +hb_shape_plan_key_t::user_features_match (const hb_shape_plan_key_t *other) +{ + if (this->num_user_features != other->num_user_features) + return false; + for (unsigned int i = 0; i < num_user_features; i++) + { + if (this->user_features[i].tag != other->user_features[i].tag || + this->user_features[i].value != other->user_features[i].value || + (this->user_features[i].start == HB_FEATURE_GLOBAL_START && + this->user_features[i].end == HB_FEATURE_GLOBAL_END) != + (other->user_features[i].start == HB_FEATURE_GLOBAL_START && + other->user_features[i].end == HB_FEATURE_GLOBAL_END)) + return false; + } + return true; +} + +bool +hb_shape_plan_key_t::equal (const hb_shape_plan_key_t *other) +{ + return hb_segment_properties_equal (&this->props, &other->props) && + this->user_features_match (other) && + this->ot.equal (&other->ot) && + this->shaper_func == other->shaper_func; } @@ -131,7 +190,7 @@ hb_shape_plan_create2 (hb_face_t *face, const hb_segment_properties_t *props, const hb_feature_t *user_features, unsigned int num_user_features, - const int *orig_coords, + const int *coords, unsigned int num_coords, const char * const *shaper_list) { @@ -142,54 +201,39 @@ hb_shape_plan_create2 (hb_face_t *face, num_coords, shaper_list); + assert (props->direction != HB_DIRECTION_INVALID); + hb_shape_plan_t *shape_plan; - hb_feature_t *features = nullptr; - int *coords = nullptr; if (unlikely (!props)) goto bail; - if (num_user_features && !(features = (hb_feature_t *) calloc (num_user_features, sizeof (hb_feature_t)))) - goto bail; - if (num_coords && !(coords = (int *) calloc (num_coords, sizeof (int)))) - goto bail; if (!(shape_plan = hb_object_create ())) goto bail; - assert (props->direction != HB_DIRECTION_INVALID); - if (unlikely (!face)) face = hb_face_get_empty (); hb_face_make_immutable (face); - - shape_plan->custom_shaper_list = shaper_list; shape_plan->face_unsafe = face; - shape_plan->props = *props; - shape_plan->num_user_features = num_user_features; - shape_plan->user_features = features; - if (num_user_features) - memcpy (features, user_features, num_user_features * sizeof (hb_feature_t)); - shape_plan->num_coords = num_coords; - shape_plan->coords = coords; - if (num_coords) - memcpy (coords, orig_coords, num_coords * sizeof (int)); - hb_shape_plan_plan (shape_plan, - user_features, num_user_features, - coords, num_coords, - shaper_list); - - if (unlikely (!shape_plan->ot.init0 (shape_plan, + if (unlikely (!shape_plan->key.init (true, + face, + props, user_features, num_user_features, coords, - num_coords))) - goto bail; + num_coords, + shaper_list))) + goto bail2; + if (unlikely (!shape_plan->ot.init0 (face, &shape_plan->key))) + goto bail3; return shape_plan; +bail3: + shape_plan->key.free (); +bail2: + free (shape_plan); bail: - free (coords); - free (features); return hb_shape_plan_get_empty (); } @@ -238,10 +282,7 @@ hb_shape_plan_destroy (hb_shape_plan_t *shape_plan) if (!hb_object_destroy (shape_plan)) return; shape_plan->ot.fini (); - - free (shape_plan->user_features); - free (shape_plan->coords); - + shape_plan->key.free (); free (shape_plan); } @@ -287,6 +328,22 @@ hb_shape_plan_get_user_data (hb_shape_plan_t *shape_plan, return hb_object_get_user_data (shape_plan, key); } +/** + * hb_shape_plan_get_shaper: + * @shape_plan: a shape plan. + * + * + * + * Return value: (transfer none): + * + * Since: 0.9.7 + **/ +const char * +hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan) +{ + return shape_plan->key.shaper_name; +} + /** * hb_shape_plan_execute: @@ -312,8 +369,8 @@ hb_shape_plan_execute (hb_shape_plan_t *shape_plan, DEBUG_MSG_FUNC (SHAPE_PLAN, shape_plan, "num_features=%d shaper_func=%p, shaper_name=%s", num_features, - shape_plan->shaper_func, - shape_plan->shaper_name); + shape_plan->key.shaper_func, + shape_plan->key.shaper_name); if (unlikely (!buffer->len)) return true; @@ -325,7 +382,7 @@ hb_shape_plan_execute (hb_shape_plan_t *shape_plan, return false; assert (shape_plan->face_unsafe == font->face); - assert (hb_segment_properties_equal (&shape_plan->props, &buffer->props)); + assert (hb_segment_properties_equal (&shape_plan->key.props, &buffer->props)); #define HB_SHAPER_EXECUTE(shaper) \ HB_STMT_START { \ @@ -336,7 +393,7 @@ hb_shape_plan_execute (hb_shape_plan_t *shape_plan, if (false) ; #define HB_SHAPER_IMPLEMENT(shaper) \ - else if (shape_plan->shaper_func == _hb_##shaper##_shape) \ + else if (shape_plan->key.shaper_func == _hb_##shaper##_shape) \ HB_SHAPER_EXECUTE (shaper); #include "hb-shaper-list.hh" #undef HB_SHAPER_IMPLEMENT @@ -348,92 +405,9 @@ hb_shape_plan_execute (hb_shape_plan_t *shape_plan, /* - * caching + * Caching */ -#if 0 -static unsigned int -hb_shape_plan_hash (const hb_shape_plan_t *shape_plan) -{ - return hb_segment_properties_hash (&shape_plan->props) + - shape_plan->custom_shaper_list ? (intptr_t) shape_plan->shaper_func : 0; -} -#endif - -/* User-feature caching is currently somewhat dumb: - * it only finds matches where the feature array is identical, - * not cases where the feature lists would be compatible for plan purposes - * but have different ranges, for example. - */ -struct hb_shape_plan_proposal_t -{ - const hb_segment_properties_t props; - const char * const *shaper_list; - const hb_feature_t *user_features; - unsigned int num_user_features; - const int *coords; - unsigned int num_coords; - hb_shape_func_t *shaper_func; -}; - -static inline hb_bool_t -hb_shape_plan_user_features_match (const hb_shape_plan_t *shape_plan, - const hb_shape_plan_proposal_t *proposal) -{ - if (proposal->num_user_features != shape_plan->num_user_features) - return false; - for (unsigned int i = 0, n = proposal->num_user_features; i < n; i++) - if (proposal->user_features[i].tag != shape_plan->user_features[i].tag || - proposal->user_features[i].value != shape_plan->user_features[i].value || - proposal->user_features[i].start != shape_plan->user_features[i].start || - proposal->user_features[i].end != shape_plan->user_features[i].end) - return false; - return true; -} - -static inline hb_bool_t -hb_shape_plan_coords_match (const hb_shape_plan_t *shape_plan, - const hb_shape_plan_proposal_t *proposal) -{ - if (proposal->num_coords != shape_plan->num_coords) - return false; - for (unsigned int i = 0, n = proposal->num_coords; i < n; i++) - if (proposal->coords[i] != shape_plan->coords[i]) - return false; - return true; -} - -static hb_bool_t -hb_shape_plan_matches (const hb_shape_plan_t *shape_plan, - const hb_shape_plan_proposal_t *proposal) -{ - return hb_segment_properties_equal (&shape_plan->props, &proposal->props) && - hb_shape_plan_user_features_match (shape_plan, proposal) && - hb_shape_plan_coords_match (shape_plan, proposal) && - ((!shape_plan->custom_shaper_list && !proposal->shaper_list) || - (shape_plan->shaper_func == proposal->shaper_func)); -} - -static inline hb_bool_t -hb_non_global_user_features_present (const hb_feature_t *user_features, - unsigned int num_user_features) -{ - while (num_user_features) { - if (user_features->start != 0 || user_features->end != (unsigned int) -1) - return true; - num_user_features--; - user_features++; - } - return false; -} - -static inline hb_bool_t -hb_coords_present (const int *coords HB_UNUSED, - unsigned int num_coords) -{ - return num_coords != 0; -} - /** * hb_shape_plan_create_cached: * @face: @@ -476,64 +450,38 @@ hb_shape_plan_create_cached2 (hb_face_t *face, num_user_features, shaper_list); - hb_shape_plan_proposal_t proposal = { - *props, - shaper_list, - user_features, - num_user_features, - coords, - num_coords, - nullptr - }; - - if (shaper_list) { - /* Choose shaper. Adapted from hb_shape_plan_plan(). - * Must choose shaper exactly the same way as that function. */ - for (const char * const *shaper_item = shaper_list; *shaper_item; shaper_item++) - if (false) - ; -#define HB_SHAPER_IMPLEMENT(shaper) \ - else if (0 == strcmp (*shaper_item, #shaper) && \ - hb_##shaper##_shaper_face_data_ensure (face)) \ - { \ - proposal.shaper_func = _hb_##shaper##_shape; \ - break; \ - } -#include "hb-shaper-list.hh" -#undef HB_SHAPER_IMPLEMENT - - if (unlikely (!proposal.shaper_func)) - return hb_shape_plan_get_empty (); - } - - retry: hb_face_t::plan_node_t *cached_plan_nodes = face->shape_plans; - /* Don't look for plan in the cache if there were variation coordinates XXX Fix me. */ - if (!hb_coords_present (coords, num_coords)) + bool dont_cache = hb_object_is_inert (face); + + if (likely (!dont_cache)) + { + hb_shape_plan_key_t key; + if (!key.init (false, + face, + props, + user_features, + num_user_features, + coords, + num_coords, + shaper_list)) + return hb_shape_plan_get_empty (); + for (hb_face_t::plan_node_t *node = cached_plan_nodes; node; node = node->next) - if (hb_shape_plan_matches (node->shape_plan, &proposal)) + if (node->shape_plan->key.equal (&key)) { DEBUG_MSG_FUNC (SHAPE_PLAN, node->shape_plan, "fulfilled from cache"); return hb_shape_plan_reference (node->shape_plan); } + } - /* Not found. */ hb_shape_plan_t *shape_plan = hb_shape_plan_create2 (face, props, user_features, num_user_features, coords, num_coords, shaper_list); - /* Don't add to the cache if face is inert. */ - if (unlikely (hb_object_is_inert (face))) - return shape_plan; - - /* Don't add the plan to the cache if there were user features with non-global ranges */ - if (hb_non_global_user_features_present (user_features, num_user_features)) - return shape_plan; - /* Don't add the plan to the cache if there were variation coordinates XXX Fix me. */ - if (hb_coords_present (coords, num_coords)) + if (unlikely (dont_cache)) return shape_plan; hb_face_t::plan_node_t *node = (hb_face_t::plan_node_t *) calloc (1, sizeof (hb_face_t::plan_node_t)); @@ -553,19 +501,3 @@ retry: return hb_shape_plan_reference (shape_plan); } - -/** - * hb_shape_plan_get_shaper: - * @shape_plan: a shape plan. - * - * - * - * Return value: (transfer none): - * - * Since: 0.9.7 - **/ -const char * -hb_shape_plan_get_shaper (hb_shape_plan_t *shape_plan) -{ - return shape_plan->shaper_name; -} diff --git a/src/hb-shape-plan.hh b/src/hb-shape-plan.hh index eaa84fd4b..d9aa3ee1a 100644 --- a/src/hb-shape-plan.hh +++ b/src/hb-shape-plan.hh @@ -1,5 +1,5 @@ /* - * Copyright © 2012 Google, Inc. + * Copyright © 2012,2018 Google, Inc. * * This is part of HarfBuzz, a text shaping library. * @@ -32,35 +32,44 @@ #include "hb-ot-shape.hh" +struct hb_shape_plan_key_t +{ + hb_segment_properties_t props; + + const hb_feature_t *user_features; + unsigned int num_user_features; + + hb_ot_shape_plan_key_t ot; + + hb_shape_func_t *shaper_func; + const char *shaper_name; + + HB_INTERNAL inline bool init (bool copy, + hb_face_t *face, + const hb_segment_properties_t *props, + const hb_feature_t *user_features, + unsigned int num_user_features, + const int *coords, + unsigned int num_coords, + const char * const *shaper_list); + + HB_INTERNAL inline void free (void) + { + ::free ((void *) user_features); + } + + HB_INTERNAL bool user_features_match (const hb_shape_plan_key_t *other); + + HB_INTERNAL bool equal (const hb_shape_plan_key_t *other); +}; + struct hb_shape_plan_t { hb_object_header_t header; - hb_face_t *face_unsafe; /* We don't carry a reference to face. */ - bool custom_shaper_list; - hb_segment_properties_t props; - - hb_shape_func_t *shaper_func; - const char *shaper_name; - - hb_feature_t *user_features; - unsigned int num_user_features; - - int *coords; - unsigned int num_coords; - + hb_shape_plan_key_t key; hb_ot_shape_plan_t ot; }; -#define HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS \ - , const hb_feature_t *user_features \ - , unsigned int num_user_features \ - , const int *coords \ - , unsigned int num_coords -#define HB_SHAPER_IMPLEMENT(shaper) HB_SHAPER_DATA_PROTOTYPE(shaper, shape_plan); -#include "hb-shaper-list.hh" -#undef HB_SHAPER_IMPLEMENT -#undef HB_SHAPER_DATA_CREATE_FUNC_EXTRA_ARGS - #endif /* HB_SHAPE_PLAN_HH */ diff --git a/src/hb-shape.cc b/src/hb-shape.cc index f98bc6e51..325be0f12 100644 --- a/src/hb-shape.cc +++ b/src/hb-shape.cc @@ -63,7 +63,7 @@ static struct hb_shaper_list_lazy_loader_t : hb_lazy_loader_t { - static inline hb_shaper_pair_t *create (void) + static inline hb_shaper_pair_static_t *create (void) { char *env = getenv ("HB_SHAPER_LIST"); if (!env || !*env) return nullptr; - hb_shaper_pair_t *shapers = (hb_shaper_pair_t *) calloc (1, sizeof (all_shapers)); + hb_shaper_pair_static_t *shapers = (hb_shaper_pair_static_t *) calloc (1, sizeof (all_shapers)); if (unlikely (!shapers)) return nullptr; @@ -68,7 +68,7 @@ static struct hb_shapers_lazy_loader_t : hb_lazy_loader_t (this); const OT::maxp *maxp_table = maxp_blob->as (); - num_glyphs = maxp_table->get_num_glyphs (); + + unsigned int ret = maxp_table->get_num_glyphs (); + num_glyphs.set_relaxed (ret); hb_blob_destroy (maxp_blob); + return ret; } -void +unsigned int hb_face_t::load_upem (void) const { - hb_blob_t *head_blob = hb_sanitize_context_t ().reference_table (this); - const OT::head *head_table = head_blob->as (); - upem = head_table->get_upem (); - hb_blob_destroy (head_blob); + unsigned int ret = table.head->get_upem (); + upem.set_relaxed (ret); + return ret; } #endif diff --git a/src/hb.hh b/src/hb.hh index e3faf17c9..16ccf87ce 100644 --- a/src/hb.hh +++ b/src/hb.hh @@ -246,7 +246,7 @@ struct _hb_alignof #endif -#if defined(_WIN32) || defined(__CYGWIN__) +#ifdef _WIN32 /* We need Windows Vista for both Uniscribe backend and for * MemoryBarrier. We don't support compiling on Windows XP, * though we run on it fine. */ diff --git a/test/fuzzing/Makefile.am b/test/fuzzing/Makefile.am index ed67eee8c..a77df7061 100644 --- a/test/fuzzing/Makefile.am +++ b/test/fuzzing/Makefile.am @@ -7,13 +7,13 @@ DISTCLEANFILES = MAINTAINERCLEANFILES = # Convenience targets: -lib-only: - @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src fuzzing -lib: lib-only - @$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) +lib: + @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src lib +libs: + @$(MAKE) $(AM_MAKEFLAGS) -C $(top_builddir)/src libs -$(top_builddir)/src/libharfbuzz-fuzzing.la: lib-only -$(top_builddir)/src/libharfbuzz-subset-fuzzing.la: lib-only +$(top_builddir)/src/libharfbuzz.la: lib +$(top_builddir)/src/libharfbuzz-subset.la: libs EXTRA_DIST += \ README \ @@ -33,24 +33,15 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/ \ -I$(top_builddir)/src/ \ $(NULL) -LDADD = \ - $(top_builddir)/src/libharfbuzz-fuzzing.la \ - $(NULL) hb_shape_fuzzer_SOURCES = \ hb-fuzzer.hh \ hb-shape-fuzzer.cc \ main.cc \ $(NULL) -hb_shape_fuzzer_LDADD = \ - $(LDADD) \ - $(NULL) -hb_shape_fuzzer_CPPFLAGS = \ - $(AM_CPPFLAGS) \ - $(NULL) -hb_shape_fuzzer_DEPENDENCIES = \ - $(top_builddir)/src/libharfbuzz-fuzzing.la - $(NULL) +hb_shape_fuzzer_LDADD = $(top_builddir)/src/libharfbuzz.la +hb_shape_fuzzer_CPPFLAGS = $(AM_CPPFLAGS) +hb_shape_fuzzer_DEPENDENCIES = $(top_builddir)/src/libharfbuzz.la hb_subset_fuzzer_SOURCES = \ hb-fuzzer.hh \ @@ -58,14 +49,10 @@ hb_subset_fuzzer_SOURCES = \ main.cc \ $(NULL) hb_subset_fuzzer_LDADD = \ - $(top_builddir)/src/libharfbuzz-subset-fuzzing.la \ - $(NULL) -hb_subset_fuzzer_CPPFLAGS = \ - $(AM_CPPFLAGS) \ - $(NULL) -hb_subset_fuzzer_DEPENDENCIES = \ - $(top_builddir)/src/libharfbuzz-subset-fuzzing.la - $(NULL) + $(top_builddir)/src/libharfbuzz.la \ + $(top_builddir)/src/libharfbuzz-subset.la +hb_subset_fuzzer_CPPFLAGS = $(AM_CPPFLAGS) +hb_subset_fuzzer_DEPENDENCIES = $(top_builddir)/src/libharfbuzz-subset.la check: EXEEXT="$(EXEEXT)" srcdir="$(srcdir)" builddir="$(builddir)" $(srcdir)/run-shape-fuzzer-tests.py diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5691469793329152 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5691469793329152 new file mode 100644 index 000000000..6c7390002 Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5691469793329152 differ diff --git a/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5754863779053568 b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5754863779053568 new file mode 100644 index 000000000..03f240f63 Binary files /dev/null and b/test/fuzzing/fonts/clusterfuzz-testcase-minimized-hb-shape-fuzzer-5754863779053568 differ diff --git a/test/shaping/data/in-house/fonts/dcf774ca21062e7439f98658b18974ea8b956d0c.ttf b/test/shaping/data/in-house/fonts/dcf774ca21062e7439f98658b18974ea8b956d0c.ttf new file mode 100644 index 000000000..4d3e11d52 Binary files /dev/null and b/test/shaping/data/in-house/fonts/dcf774ca21062e7439f98658b18974ea8b956d0c.ttf differ diff --git a/test/shaping/data/in-house/tests/use.tests b/test/shaping/data/in-house/tests/use.tests index 4b46620bb..18d1991e2 100644 --- a/test/shaping/data/in-house/tests/use.tests +++ b/test/shaping/data/in-house/tests/use.tests @@ -8,3 +8,4 @@ ../fonts/2a670df15b73a5dc75a5cc491bde5ac93c5077dc.ttf::U+11124,U+11134,U+11131:[u11124=0+514|u11134=0+0|u11131=0+0] ../fonts/2a670df15b73a5dc75a5cc491bde5ac93c5077dc.ttf::U+11124,U+11131,U+11134:[u11124=0+514|u11131=0+0|uni25CC=0+547|u11134=0+0] ../fonts/573d3a3177c9a8646e94c8a0d7b224334340946a.ttf:--font-funcs=ft:U+11410,U+11442,U+11411,U+11440,U+11443,U+11410,U+11442,U+11411,U+11441,U+11443:[E_dv.alt=0+275|Ga.icd=0+367|Gha.diag=0@100,0+386|AA_dv.alt=0+208|Candrabindu=0@17,-8+0|E_dv.alt=5+275|Ga.icd=5+367|Gha.diag=5@100,0+386|AU_dv_part.alt=5+213|Candrabindu.sm=5@-52,179+0] +../fonts/dcf774ca21062e7439f98658b18974ea8b956d0c.ttf::U+11328,U+1134D,U+1CF4:[gid1=0+793|gid2=0+0|gid3=0+0]