.circleci/config.yml | 4 - src/dump-emoji.cc | 1 src/dump-fon.cc | 1 src/hb-coretext.cc | 3 src/hb-open-type-private.hh | 11 ++ src/hb-ot-layout.cc | 1 src/hb-ot-post-table.hh | 3 src/hb-private.hh | 167 +++++++++++++++++++++++++++++--------------- src/hb-subset-plan.cc | 12 +-- src/hb-subset.cc | 1 src/hb-uniscribe.cc | 8 -- src/main.cc | 1 12 files changed, 139 insertions(+), 74 deletions(-)
New commits: commit 31c4236d9643063e518289b28c3e17cedd8401e0 Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu May 24 13:38:46 2018 -0700 Underflow protection in hb_vector_t diff --git a/src/hb-private.hh b/src/hb-private.hh index 45f69904..0d1cc0ef 100644 --- a/src/hb-private.hh +++ b/src/hb-private.hh @@ -685,8 +685,9 @@ struct hb_vector_t return true; } - inline bool resize (unsigned int size) + inline bool resize (int size_) { + unsigned int size = size_ < 0 ? 0u : (unsigned int) size_; if (!alloc (size)) return false; @@ -696,6 +697,7 @@ struct hb_vector_t inline void pop (void) { + if (!len) return; len--; } @@ -709,10 +711,11 @@ struct hb_vector_t len--; } - inline void shrink (unsigned int l) + inline void shrink (int size_) { - if (l < len) - len = l; + unsigned int size = size_ < 0 ? 0u : (unsigned int) size_; + if (size < len) + len = size; } template <typename T> commit f83e992c8b27111ab802fd7e5678592a0c717518 Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu May 24 11:46:57 2018 -0700 Mark CrapPool thread_local Not sure if I like to keep it. For now, aim for correctness. diff --git a/src/dump-emoji.cc b/src/dump-emoji.cc index 50a929be..280c5c9b 100644 --- a/src/dump-emoji.cc +++ b/src/dump-emoji.cc @@ -48,7 +48,7 @@ #ifndef HB_NO_VISIBILITY const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; -void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; +thread_local void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; #endif void cbdt_callback (const uint8_t* data, unsigned int length, diff --git a/src/dump-fon.cc b/src/dump-fon.cc index 827de4a3..748de1ab 100644 --- a/src/dump-fon.cc +++ b/src/dump-fon.cc @@ -28,7 +28,7 @@ #ifndef HB_NO_VISIBILITY const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; -void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; +thread_local void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; #endif template <typename Type, int Bytes> struct LEInt; diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 67049545..7f9b6be8 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -48,7 +48,7 @@ #ifndef HB_NO_VISIBILITY const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; -void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; +thread_local void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; #endif diff --git a/src/hb-private.hh b/src/hb-private.hh index 4318eb97..45f69904 100644 --- a/src/hb-private.hh +++ b/src/hb-private.hh @@ -90,6 +90,14 @@ extern "C" void hb_free_impl(void *ptr); HB_UNUSED typedef int HB_PASTE(static_assertion_failed_at_line_, __LINE__) [(e) ? 1 : -1] #endif // static_assert +#ifdef __GNUC__ +#if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 8)) +#define thread_local __thread +#endif +#else +#define thread_local +#endif + #endif // __cplusplus < 201103L #if (defined(__GNUC__) || defined(__clang__)) && defined(__OPTIMIZE__) @@ -570,12 +578,16 @@ static_assert (Namespace::Type::min_size + 1 <= sizeof (_Null##Type), "Null pool /* Global writable pool. Enlarge as necessary. */ +/* To be fully correct, CrapPool must be thread_local. However, we do not rely on CrapPool + * for correct operation. It only exist to catch and divert program logic bugs instead of + * causing bad memory access. So, races there are not actually introducing incorrectness + * in the code. So maybe disable? Has ~12kb binary size overhead to have it. */ #ifdef HB_NO_VISIBILITY static #else extern HB_INTERNAL #endif -void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] +thread_local void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] #ifdef HB_NO_VISIBILITY = {} #endif diff --git a/src/hb-subset.cc b/src/hb-subset.cc index ad273d04..e974d0f4 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -46,7 +46,7 @@ #if !defined(HB_NO_VISIBILITY) && !defined(HB_SUBSET_BUILTIN) const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; -void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; +thread_local void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; #endif diff --git a/src/main.cc b/src/main.cc index f32490e7..2fec52f9 100644 --- a/src/main.cc +++ b/src/main.cc @@ -39,7 +39,7 @@ using namespace OT; #ifndef HB_NO_VISIBILITY const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; -void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; +thread_local void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; #endif int commit 5d80129891107c7f629c6950b5d257f2a867eee0 Author: Behdad Esfahbod <beh...@behdad.org> Date: Thu May 24 11:33:15 2018 -0700 Add CrapPool Common Regoin for Access Protection. Like the NullPool, but writable. diff --git a/src/dump-emoji.cc b/src/dump-emoji.cc index 63af4a6a..50a929be 100644 --- a/src/dump-emoji.cc +++ b/src/dump-emoji.cc @@ -48,6 +48,7 @@ #ifndef HB_NO_VISIBILITY const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; +void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; #endif void cbdt_callback (const uint8_t* data, unsigned int length, diff --git a/src/dump-fon.cc b/src/dump-fon.cc index 81525f42..827de4a3 100644 --- a/src/dump-fon.cc +++ b/src/dump-fon.cc @@ -28,6 +28,7 @@ #ifndef HB_NO_VISIBILITY const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; +void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; #endif template <typename Type, int Bytes> struct LEInt; diff --git a/src/hb-open-type-private.hh b/src/hb-open-type-private.hh index 1c771b09..6f639dca 100644 --- a/src/hb-open-type-private.hh +++ b/src/hb-open-type-private.hh @@ -932,6 +932,7 @@ struct ArrayOf } inline Type& operator [] (unsigned int i) { + if (unlikely (i >= len)) return Crap(Type); return arrayZ[i]; } inline unsigned int get_size (void) const @@ -1040,6 +1041,11 @@ struct OffsetListOf : OffsetArrayOf<Type> if (unlikely (i >= this->len)) return Null(Type); return this+this->arrayZ[i]; } + inline const Type& operator [] (unsigned int i) + { + if (unlikely (i >= this->len)) return Crap(Type); + return this+this->arrayZ[i]; + } inline bool sanitize (hb_sanitize_context_t *c) const { @@ -1064,6 +1070,11 @@ struct HeadlessArrayOf if (unlikely (i >= len || !i)) return Null(Type); return arrayZ[i-1]; } + inline Type& operator [] (unsigned int i) + { + if (unlikely (i >= len || !i)) return Crap(Type); + return arrayZ[i-1]; + } inline unsigned int get_size (void) const { return len.static_size + (len ? len - 1 : 0) * Type::static_size; } diff --git a/src/hb-ot-layout.cc b/src/hb-ot-layout.cc index 368a8465..67049545 100644 --- a/src/hb-ot-layout.cc +++ b/src/hb-ot-layout.cc @@ -48,6 +48,7 @@ #ifndef HB_NO_VISIBILITY const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; +void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; #endif diff --git a/src/hb-private.hh b/src/hb-private.hh index 4b9668e0..4318eb97 100644 --- a/src/hb-private.hh +++ b/src/hb-private.hh @@ -529,7 +529,7 @@ _hb_ceil_to_4 (unsigned int v) */ /* - * Null objects + * Static pools */ /* Global nul-content Null pool. Enlarge as necessary. */ @@ -547,7 +547,6 @@ const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {} #endif ; - /* Generic nul-content Null objects. */ template <typename Type> static inline const Type& Null (void) { @@ -569,6 +568,28 @@ namespace Namespace { \ static_assert (Namespace::Type::min_size + 1 <= sizeof (_Null##Type), "Null pool too small. Enlarge.") +/* Global writable pool. Enlarge as necessary. */ + +#ifdef HB_NO_VISIBILITY +static +#else +extern HB_INTERNAL +#endif +void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] +#ifdef HB_NO_VISIBILITY += {} +#endif +; +/* CRAP pool: Common Region for Access Protection. */ +template <typename Type> +static inline Type& Crap (void) { + static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE."); + Type *obj = reinterpret_cast<Type *> (_hb_CrapPool); + *obj = Null(Type); + return *obj; +} +#define Crap(Type) Crap<Type>() + /* arrays and maps */ @@ -589,8 +610,18 @@ struct hb_vector_t arrayZ = static_array; } - inline Type& operator [] (unsigned int i) { return arrayZ[i]; } - inline const Type& operator [] (unsigned int i) const { return arrayZ[i]; } + inline Type& operator [] (unsigned int i) + { + if (unlikely (i >= len)) + return Crap (Type); + return arrayZ[i]; + } + inline const Type& operator [] (unsigned int i) const + { + if (unlikely (i >= len)) + return Null (Type); + return arrayZ[i]; + } inline Type *push (void) { diff --git a/src/hb-subset.cc b/src/hb-subset.cc index 98f95e02..ad273d04 100644 --- a/src/hb-subset.cc +++ b/src/hb-subset.cc @@ -46,6 +46,7 @@ #if !defined(HB_NO_VISIBILITY) && !defined(HB_SUBSET_BUILTIN) const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; +void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; #endif diff --git a/src/main.cc b/src/main.cc index 9a187366..f32490e7 100644 --- a/src/main.cc +++ b/src/main.cc @@ -39,6 +39,7 @@ using namespace OT; #ifndef HB_NO_VISIBILITY const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; +void * _hb_CrapPool[HB_NULL_POOL_SIZE / sizeof (void *)] = {}; #endif int commit 673b764de050957b2d3b9972d9e55b3a2e5615f4 Author: Behdad Esfahbod <beh...@behdad.org> Date: Wed May 23 20:12:23 2018 -0700 Move code around diff --git a/src/hb-private.hh b/src/hb-private.hh index d3381eb5..4b9668e0 100644 --- a/src/hb-private.hh +++ b/src/hb-private.hh @@ -315,7 +315,7 @@ static_assert ((sizeof (hb_var_int_t) == 4), ""); -/* Misc */ +/* Tiny functions */ /* * Void! @@ -522,6 +522,54 @@ _hb_ceil_to_4 (unsigned int v) +/* + * + * Utility types + * + */ + +/* + * Null objects + */ + +/* Global nul-content Null pool. Enlarge as necessary. */ + +#define HB_NULL_POOL_SIZE 264 +static_assert (HB_NULL_POOL_SIZE % sizeof (void *) == 0, "Align HB_NULL_POOL_SIZE."); + +#ifdef HB_NO_VISIBILITY +static +#else +extern HB_INTERNAL +#endif +const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] +#ifdef HB_NO_VISIBILITY += {} +#endif +; + +/* Generic nul-content Null objects. */ +template <typename Type> +static inline const Type& Null (void) { + static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE."); + return *reinterpret_cast<const Type *> (_hb_NullPool); +} +#define Null(Type) Null<Type>() + +/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */ +#define DEFINE_NULL_DATA(Namespace, Type, data) \ +} /* Close namespace. */ \ +static const char _Null##Type[sizeof (Namespace::Type) + 1] = data; /* +1 is for nul-termination in data */ \ +template <> \ +/*static*/ inline const Namespace::Type& Null<Namespace::Type> (void) { \ + return *reinterpret_cast<const Namespace::Type *> (_Null##Type); \ +} \ +namespace Namespace { \ +/* The following line really exists such that we end in a place needing semicolon */ \ +static_assert (Namespace::Type::min_size + 1 <= sizeof (_Null##Type), "Null pool too small. Enlarge.") + + + /* arrays and maps */ @@ -1116,46 +1164,5 @@ round (double x) #endif -/* - * Null objects - */ - -/* Global nul-content Null pool. Enlarge as necessary. */ - -#define HB_NULL_POOL_SIZE 264 -static_assert (HB_NULL_POOL_SIZE % sizeof (void *) == 0, "Align HB_NULL_POOL_SIZE."); - -#ifdef HB_NO_VISIBILITY -static -#else -extern HB_INTERNAL -#endif -const void * const _hb_NullPool[HB_NULL_POOL_SIZE / sizeof (void *)] -#ifdef HB_NO_VISIBILITY -= {} -#endif -; - -/* Generic nul-content Null objects. */ -template <typename Type> -static inline const Type& Null (void) { - static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE."); - return *reinterpret_cast<const Type *> (_hb_NullPool); -} -#define Null(Type) Null<Type>() - -/* Specializaiton for arbitrary-content arbitrary-sized Null objects. */ -#define DEFINE_NULL_DATA(Namespace, Type, data) \ -} /* Close namespace. */ \ -static const char _Null##Type[sizeof (Namespace::Type) + 1] = data; /* +1 is for nul-termination in data */ \ -template <> \ -/*static*/ inline const Namespace::Type& Null<Namespace::Type> (void) { \ - return *reinterpret_cast<const Namespace::Type *> (_Null##Type); \ -} \ -namespace Namespace { \ -/* The following line really exists such that we end in a place needing semicolon */ \ -static_assert (Namespace::Type::min_size + 1 <= sizeof (_Null##Type), "Null pool too small. Enlarge.") - - #endif /* HB_PRIVATE_HH */ commit 65aeabd62275b37c6bb6715f3341e45625f4ba6e Author: Behdad Esfahbod <beh...@behdad.org> Date: Wed May 23 16:15:28 2018 -0700 Add hb_vector_t::push(const Type &v) Makes for cleaner code. diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc index 3924c8eb..84cc22fd 100644 --- a/src/hb-coretext.cc +++ b/src/hb-coretext.cc @@ -770,10 +770,9 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan, } if (event->start) { - active_feature_t *feature = active_features.push (); + active_feature_t *feature = active_features.push (event->feature); if (unlikely (!feature)) goto fail_features; - *feature = event->feature; } else { active_feature_t *feature = active_features.find (&event->feature); if (feature) diff --git a/src/hb-ot-post-table.hh b/src/hb-ot-post-table.hh index bec508c0..9a1edea6 100644 --- a/src/hb-ot-post-table.hh +++ b/src/hb-ot-post-table.hh @@ -126,10 +126,9 @@ struct post const uint8_t *end = (uint8_t *) table + table_length; for (const uint8_t *data = pool; data < end && data + *data <= end; data += 1 + *data) { - uint32_t *offset = index_to_offset.push (); + uint32_t *offset = index_to_offset.push (data - pool); if (unlikely (!offset)) break; - *offset = data - pool; } } inline void fini (void) diff --git a/src/hb-private.hh b/src/hb-private.hh index 183f2a41..d3381eb5 100644 --- a/src/hb-private.hh +++ b/src/hb-private.hh @@ -551,9 +551,17 @@ struct hb_vector_t return &arrayZ[len - 1]; } + inline Type *push (const Type& v) + { + if (unlikely (!resize (len + 1))) + return nullptr; + + arrayZ[len - 1] = v; + return &arrayZ[len - 1]; + } /* Allocate for size but don't adjust len. */ - inline bool alloc(unsigned int size) + inline bool alloc (unsigned int size) { if (likely (size <= allocated)) return true; @@ -738,9 +746,7 @@ struct hb_lockable_set_t l.unlock (); } } else { - item = items.push (); - if (likely (item)) - *item = v; + item = items.push (v); l.unlock (); } return item; @@ -779,9 +785,7 @@ struct hb_lockable_set_t l.lock (); item_t *item = items.find (v); if (!item) { - item = items.push (); - if (likely (item)) - *item = v; + item = items.push (v); } l.unlock (); return item; diff --git a/src/hb-subset-plan.cc b/src/hb-subset-plan.cc index d70215b0..3e53e842 100644 --- a/src/hb-subset-plan.cc +++ b/src/hb-subset-plan.cc @@ -91,10 +91,8 @@ _populate_codepoints (hb_set_t *input_codepoints, { plan_codepoints.alloc (hb_set_get_population (input_codepoints)); hb_codepoint_t cp = -1; - while (hb_set_next (input_codepoints, &cp)) { - hb_codepoint_t *wr = plan_codepoints.push(); - *wr = cp; - } + while (hb_set_next (input_codepoints, &cp)) + plan_codepoints.push(cp); plan_codepoints.qsort (_hb_codepoint_t_cmp); } @@ -139,9 +137,9 @@ _populate_gids_to_retain (hb_face_t *face, if (!cmap.get_nominal_glyph (codepoints[i], &gid)) { gid = -1; - *(bad_indices.push ()) = i; + bad_indices.push (i); } - *(old_gids.push ()) = gid; + old_gids.push (gid); } /* Generally there shouldn't be any */ @@ -166,7 +164,7 @@ _populate_gids_to_retain (hb_face_t *face, old_gids_sorted.alloc (hb_set_get_population (all_gids_to_retain)); hb_codepoint_t gid = HB_SET_VALUE_INVALID; while (hb_set_next (all_gids_to_retain, &gid)) - *(old_gids_sorted.push ()) = gid; + old_gids_sorted.push (gid); hb_set_destroy (all_gids_to_retain); glyf.fini (); diff --git a/src/hb-uniscribe.cc b/src/hb-uniscribe.cc index 3cd419e8..3b52ad3f 100644 --- a/src/hb-uniscribe.cc +++ b/src/hb-uniscribe.cc @@ -696,10 +696,8 @@ _hb_uniscribe_shape (hb_shape_plan_t *shape_plan, { if (!j || active_features[j].rec.tagFeature != feature_records[feature_records.len - 1].tagFeature) { - OPENTYPE_FEATURE_RECORD *feature = feature_records.push (); - if (unlikely (!feature)) + if (unlikely (!feature_records.push (active_features[j].rec))) goto fail_features; - *feature = active_features[j].rec; } else { @@ -719,10 +717,8 @@ _hb_uniscribe_shape (hb_shape_plan_t *shape_plan, } if (event->start) { - active_feature_t *feature = active_features.push (); - if (unlikely (!feature)) + if (unlikely (!active_features.push (event->feature))) goto fail_features; - *feature = event->feature; } else { active_feature_t *feature = active_features.find (&event->feature); if (feature) commit 38ae0add7001c4db506d3a2c18b9960a2cae7b5d Author: Ebrahim Byagowi <ebra...@gnu.org> Date: Wed May 23 13:37:57 2018 +0430 [ci] Revive the SunCC bot * Adds libnsl to the bot as it is now needed apparently * Disables hb-icu, apparently the newer ICU itself is not compatible with SunCC diff --git a/.circleci/config.yml b/.circleci/config.yml index 73d33271..55820005 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -104,9 +104,9 @@ jobs: - image: fedora steps: - checkout - - run: dnf install -y gcc ragel cmake make which glib2-devel freetype-devel cairo-devel libicu-devel graphite2-devel wget tar bzip2 python || true + - run: dnf install -y gcc ragel cmake make which glib2-devel freetype-devel cairo-devel libicu-devel graphite2-devel wget tar bzip2 python libnsl || true - run: wget http://$ODSUSER:$odsp...@behdad.org/harfbuzz-private/OracleDeveloperStudio12.6-linux-x86-bin.tar.bz2 && tar xf OracleDeveloperStudio12.6-linux-x86-bin.tar.bz2 --owner root --group root --no-same-owner - - run: CC=/root/project/OracleDeveloperStudio12.6-linux-x86-bin/developerstudio12.6/bin/suncc CXX=/root/project/OracleDeveloperStudio12.6-linux-x86-bin/developerstudio12.6/bin/sunCC cmake -DHB_HAVE_GRAPHITE2=ON -DHB_BUILTIN_UCDN=ON -DHB_HAVE_GLIB=ON -DHB_HAVE_ICU=ON -DHB_HAVE_FREETYPE=ON -Bbuild -H. + - run: CC=/root/project/OracleDeveloperStudio12.6-linux-x86-bin/developerstudio12.6/bin/suncc CXX=/root/project/OracleDeveloperStudio12.6-linux-x86-bin/developerstudio12.6/bin/sunCC cmake -DHB_HAVE_GRAPHITE2=ON -DHB_BUILTIN_UCDN=ON -DHB_HAVE_GLIB=ON -DHB_HAVE_FREETYPE=ON -Bbuild -H. - run: make -Cbuild - run: CTEST_OUTPUT_ON_FAILURE=1 make -Cbuild test - run: make -Cbuild install _______________________________________________ HarfBuzz mailing list HarfBuzz@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/harfbuzz