diff --git a/src/dump-emoji.cc b/src/dump-emoji.cc index b5ec30ead..f45bc3106 100644 --- a/src/dump-emoji.cc +++ b/src/dump-emoji.cc @@ -211,10 +211,29 @@ static void dump_glyphs (cairo_font_face_t *cairo_face, unsigned int upem, int main (int argc, char **argv) { if (argc != 2) { - fprintf (stderr, "usage: %s font-file.ttf\n", argv[0]); + fprintf (stderr, "usage: %s font-file.ttf\n" + "run it like `rm -rf out && mkdir out && %s font-file.ttf`\n", + argv[0], argv[0]); exit (1); } + + FILE *font_name_file = fopen ("out/_font_name_file.txt", "r"); + if (font_name_file != nullptr) + { + fprintf (stderr, "Purge or move ./out folder in order to run a new dump\n"); + exit (1); + } + + font_name_file = fopen ("out/_font_name_file.txt", "w"); + if (font_name_file == nullptr) + { + fprintf (stderr, "./out is not accessible, create it please\n"); + exit (1); + } + fwrite (argv[1], 1, strlen (argv[1]), font_name_file); + fclose (font_name_file); + hb_blob_t *blob = hb_blob_create_from_file (argv[1]); hb_face_t *face = hb_face_create (blob, 0); hb_font_t *font = hb_font_create (face); diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh index 4e3e4d17b..432b9e854 100644 --- a/src/hb-aat-layout-common.hh +++ b/src/hb-aat-layout-common.hh @@ -224,7 +224,8 @@ struct LookupFormat8 private: inline const T* get_value (hb_codepoint_t glyph_id) const { - return firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount ? &valueArrayZ[glyph_id - firstGlyph] : nullptr; + return firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount ? + &valueArrayZ[glyph_id - firstGlyph] : nullptr; } inline bool sanitize (hb_sanitize_context_t *c) const @@ -234,7 +235,7 @@ struct LookupFormat8 } protected: - HBUINT16 format; /* Format identifier--format = 6 */ + HBUINT16 format; /* Format identifier--format = 8 */ GlyphID firstGlyph; /* First glyph index included in the trimmed array. */ HBUINT16 glyphCount; /* Total number of glyphs (equivalent to the last * glyph minus the value of firstGlyph plus 1). */ @@ -506,9 +507,10 @@ struct StateTableDriver if (!c->in_place) { - for (; buffer->idx < buffer->len;) - buffer->next_glyph (); - buffer->swap_buffers (); + for (; buffer->successful && buffer->idx < buffer->len;) + buffer->next_glyph (); + if (likely (buffer->successful)) + buffer->swap_buffers (); } } diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh index 52923a8da..aa8039771 100644 --- a/src/hb-aat-layout-kerx-table.hh +++ b/src/hb-aat-layout-kerx-table.hh @@ -172,7 +172,7 @@ struct KerxSubTableFormat1 * list. Discovered by testing. */ unsigned int idx = stack[i]; int v = *actions++; - if (buffer->info[idx].mask & kern_mask) + if (idx < buffer->len && buffer->info[idx].mask & kern_mask) { /* XXX Non-forward direction... */ if (HB_DIRECTION_IS_HORIZONTAL (buffer->props.direction)) @@ -212,7 +212,9 @@ struct KerxSubTableFormat1 inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - return_trace (likely (machine.sanitize (c))); + /* The rest of array sanitizations are done at run-time. */ + return_trace (likely (c->check_struct (this) && + machine.sanitize (c))); } protected: @@ -338,7 +340,7 @@ struct KerxSubTableFormat4 hb_buffer_t *buffer = driver->buffer; unsigned int flags = entry->flags; - if (mark_set && entry->data.ankrActionIndex != 0xFFFF) + if (mark_set && entry->data.ankrActionIndex != 0xFFFF && buffer->idx < buffer->len) { hb_glyph_position_t &o = buffer->cur_pos(); switch (action_type) @@ -444,11 +446,9 @@ struct KerxSubTableFormat4 inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); - /* The rest of array sanitizations are done at run-time. */ - return_trace (c->check_struct (this) && - machine.sanitize (c) && - flags.sanitize (c)); + return_trace (likely (c->check_struct (this) && + machine.sanitize (c))); } protected: diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh index b902fd79b..c88e7a720 100644 --- a/src/hb-aat-layout-morx-table.hh +++ b/src/hb-aat-layout-morx-table.hh @@ -391,6 +391,12 @@ struct LigatureSubtable unsigned int action_idx = entry->data.ligActionIndex; unsigned int action; unsigned int ligature_idx = 0; + + if (unlikely (!match_length)) + return false; + + buffer->merge_out_clusters (match_positions[0], buffer->out_len); + do { if (unlikely (!match_length)) @@ -406,6 +412,8 @@ struct LigatureSubtable if (uoffset & 0x20000000) uoffset += 0xC0000000; int32_t offset = (int32_t) uoffset; + if (buffer->idx >= buffer->len) + return false; // TODO Work on previous instead? unsigned int component_idx = buffer->cur().codepoint + offset; const HBUINT16 &componentData = component[component_idx]; @@ -428,7 +436,6 @@ struct LigatureSubtable buffer->skip_glyph (); end--; } - /* TODO merge_clusters / unsafe_to_break */ action_idx++; } @@ -620,12 +627,12 @@ struct InsertionSubtable unsigned int end = buffer->out_len; buffer->move_to (mark); - if (!before) + if (buffer->idx < buffer->len && !before) buffer->copy_glyph (); /* TODO We ignore KashidaLike setting. */ for (unsigned int i = 0; i < count; i++) buffer->output_glyph (glyphs[i]); - if (!before) + if (buffer->idx < buffer->len && !before) buffer->skip_glyph (); buffer->move_to (end + count); @@ -644,12 +651,12 @@ struct InsertionSubtable unsigned int end = buffer->out_len; - if (!before) + if (buffer->idx < buffer->len && !before) buffer->copy_glyph (); /* TODO We ignore KashidaLike setting. */ for (unsigned int i = 0; i < count; i++) buffer->output_glyph (glyphs[i]); - if (!before) + if (buffer->idx < buffer->len && !before) buffer->skip_glyph (); /* Humm. Not sure where to move to. There's this wording under diff --git a/src/hb-blob.cc b/src/hb-blob.cc index c1ed0f2a7..edee67300 100644 --- a/src/hb-blob.cc +++ b/src/hb-blob.cc @@ -507,8 +507,9 @@ struct hb_mapped_file_t #if (defined(HAVE_MMAP) || defined(_WIN32) || defined(__CYGWIN__)) && !defined(HB_NO_MMAP) static void -_hb_mapped_file_destroy (hb_mapped_file_t *file) +_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__) diff --git a/src/hb-buffer.hh b/src/hb-buffer.hh index 9628ddae0..0d888e1e0 100644 --- a/src/hb-buffer.hh +++ b/src/hb-buffer.hh @@ -229,7 +229,10 @@ struct hb_buffer_t { if (unlikely (!make_room_for (0, 1))) return Crap(hb_glyph_info_t); - out_info[out_len] = info[idx]; + if (unlikely (idx == len && !out_len)) + return Crap(hb_glyph_info_t); + + out_info[out_len] = idx < len ? info[idx] : out_info[out_len - 1]; out_info[out_len].codepoint = glyph_index; out_len++; diff --git a/src/hb-ot-color-cbdt-table.hh b/src/hb-ot-color-cbdt-table.hh index 561c59900..304596840 100644 --- a/src/hb-ot-color-cbdt-table.hh +++ b/src/hb-ot-color-cbdt-table.hh @@ -128,7 +128,7 @@ struct IndexSubtableFormat1Or3 { TRACE_SANITIZE (this); return_trace (c->check_struct (this) && - c->check_array (offsetArrayZ.arrayZ, glyph_count + 1)); + offsetArrayZ.sanitize (c, glyph_count + 1)); } bool get_image_data (unsigned int idx, @@ -206,7 +206,7 @@ struct IndexSubtableRecord TRACE_SANITIZE (this); return_trace (c->check_struct (this) && firstGlyphIndex <= lastGlyphIndex && - offsetToSubtable.sanitize (c, this, lastGlyphIndex - firstGlyphIndex + 1)); + offsetToSubtable.sanitize (c, base, lastGlyphIndex - firstGlyphIndex + 1)); } inline bool get_extents (hb_glyph_extents_t *extents) const @@ -214,16 +214,14 @@ struct IndexSubtableRecord return (this+offsetToSubtable).get_extents (extents); } - bool get_image_data (unsigned int gid, + bool get_image_data (unsigned int gid, + const void *base, unsigned int *offset, unsigned int *length, unsigned int *format) const { - if (gid < firstGlyphIndex || gid > lastGlyphIndex) - { - return false; - } - return (this+offsetToSubtable).get_image_data (gid - firstGlyphIndex, + if (gid < firstGlyphIndex || gid > lastGlyphIndex) return false; + return (base+offsetToSubtable).get_image_data (gid - firstGlyphIndex, offset, length, format); } @@ -241,12 +239,7 @@ struct IndexSubtableArray inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const { TRACE_SANITIZE (this); - if (unlikely (!c->check_array (indexSubtablesZ.arrayZ, count))) - return_trace (false); - for (unsigned int i = 0; i < count; i++) - if (unlikely (!indexSubtablesZ[i].sanitize (c, this))) - return_trace (false); - return_trace (true); + return_trace (indexSubtablesZ.sanitize (c, count, this)); } public: @@ -276,13 +269,15 @@ struct BitmapSizeTable TRACE_SANITIZE (this); return_trace (c->check_struct (this) && indexSubtableArrayOffset.sanitize (c, base, numberOfIndexSubtables) && - c->check_range (&(base+indexSubtableArrayOffset), indexTablesSize) && horizontal.sanitize (c) && vertical.sanitize (c)); } - const IndexSubtableRecord *find_table (hb_codepoint_t glyph, const void *base) const + const IndexSubtableRecord *find_table (hb_codepoint_t glyph, + const void *base, + const void **out_base) const { + *out_base = &(base+indexSubtableArrayOffset); return (base+indexSubtableArrayOffset).find_table (glyph, numberOfIndexSubtables); } @@ -348,7 +343,8 @@ struct CBLC protected: const IndexSubtableRecord *find_table (hb_codepoint_t glyph, - unsigned int *x_ppem, unsigned int *y_ppem) const + unsigned int *x_ppem, unsigned int *y_ppem, + const void **base) const { /* TODO: Make it possible to select strike. */ @@ -361,7 +357,7 @@ struct CBLC { *x_ppem = sizeTables[i].ppemX; *y_ppem = sizeTables[i].ppemY; - return sizeTables[i].find_table (glyph, this); + return sizeTables[i].find_table (glyph, this, base); } } @@ -419,7 +415,8 @@ struct CBDT if (!cblc) return false; // Not a color bitmap font. - const IndexSubtableRecord *subtable_record = this->cblc->find_table(glyph, &x_ppem, &y_ppem); + const void *base; + const IndexSubtableRecord *subtable_record = this->cblc->find_table (glyph, &x_ppem, &y_ppem, &base); if (!subtable_record || !x_ppem || !y_ppem) return false; @@ -427,7 +424,7 @@ struct CBDT return true; unsigned int image_offset = 0, image_length = 0, image_format = 0; - if (!subtable_record->get_image_data (glyph, &image_offset, &image_length, &image_format)) + if (!subtable_record->get_image_data (glyph, base, &image_offset, &image_length, &image_format)) return false; { @@ -478,7 +475,7 @@ struct CBDT { unsigned int image_offset = 0, image_length = 0, image_format = 0; - if (!subtable_record.get_image_data (gid, + if (!subtable_record.get_image_data (gid, &subtable_array, &image_offset, &image_length, &image_format)) continue; diff --git a/src/hb-ot-font.cc b/src/hb-ot-font.cc index 5fa9d3f7e..43e9b661f 100644 --- a/src/hb-ot-font.cc +++ b/src/hb-ot-font.cc @@ -128,6 +128,35 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data, } } +static hb_bool_t +hb_ot_get_glyph_v_origin (hb_font_t *font, + void *font_data, + hb_codepoint_t glyph, + hb_position_t *x, + hb_position_t *y, + void *user_data HB_UNUSED) +{ + const hb_ot_face_data_t *ot_face = (const hb_ot_face_data_t *) font_data; + + *x = font->get_glyph_h_advance (glyph) / 2; + + hb_glyph_extents_t extents = {0}; + bool ret = ot_face->glyf->get_extents (glyph, &extents); + if (ret) + { + const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx.get (); + hb_position_t tsb = vmtx.get_side_bearing (glyph); + *y = font->em_scale_y (extents.y_bearing + tsb); + return true; + } + + hb_font_extents_t font_extents; + font->get_h_extents_with_fallback (&font_extents); + *y = font_extents.ascender; + + return true; +} + static hb_bool_t hb_ot_get_glyph_extents (hb_font_t *font, void *font_data, @@ -223,7 +252,7 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_tlsb; + /* dest just sb */ + *((FWORD *) dest_pos) = src_metric->sb; } } else @@ -147,18 +147,18 @@ struct hmtxvmtx failed = true; break; } - FWORD src_lsb = *(lsbs + gids[i] - _mtx.num_advances); + FWORD src_sb = *(lsbs + gids[i] - _mtx.num_advances); if (i < num_advances) { /* dest needs a full LongMetric */ LongMetric *metric = (LongMetric *)dest_pos; metric->advance = src_metric->advance; - metric->lsb = src_lsb; + metric->sb = src_sb; } else { - /* dest just needs an lsb */ - *((FWORD *) dest_pos) = src_lsb; + /* dest just needs an sb */ + *((FWORD *) dest_pos) = src_sb; } } dest_pos += (i < num_advances ? 4 : 2); @@ -249,17 +249,30 @@ struct hmtxvmtx hb_blob_destroy (var_blob); } - inline unsigned int get_advance (hb_codepoint_t glyph) const + /* TODO Add variations version. */ + inline unsigned int get_side_bearing (hb_codepoint_t glyph) const + { + if (glyph < num_advances) + return table->longMetricZ[glyph].sb; + + if (unlikely (glyph > num_metrics)) + return 0; + + const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_advances]; + return bearings[glyph - num_advances]; + } + + inline unsigned int get_advance (hb_codepoint_t glyph) const { if (unlikely (glyph >= num_metrics)) { - /* If num_metrics is zero, it means we don't have the metrics table - * for this direction: return default advance. Otherwise, it means that the - * glyph index is out of bound: return zero. */ - if (num_metrics) - return 0; - else - return default_advance; + /* If num_metrics is zero, it means we don't have the metrics table + * for this direction: return default advance. Otherwise, it means that the + * glyph index is out of bound: return zero. */ + if (num_metrics) + return 0; + else + return default_advance; } return table->longMetricZ[MIN (glyph, (uint32_t) num_advances - 1)].advance; @@ -271,7 +284,7 @@ struct hmtxvmtx unsigned int advance = get_advance (glyph); if (likely(glyph < num_metrics)) { - advance += (font->num_coords ? var_table->get_advance_var (glyph, font->coords, font->num_coords) : 0); // TODO Optimize?! + advance += (font->num_coords ? var_table->get_advance_var (glyph, font->coords, font->num_coords) : 0); // TODO Optimize?! } return advance; } diff --git a/src/hb-ot-kern-table.hh b/src/hb-ot-kern-table.hh index dab7a805f..3cc11d100 100644 --- a/src/hb-ot-kern-table.hh +++ b/src/hb-ot-kern-table.hh @@ -37,6 +37,7 @@ struct hb_kern_machine_t { hb_kern_machine_t (const Driver &driver_) : driver (driver_) {} + HB_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW inline void kern (hb_font_t *font, hb_buffer_t *buffer, hb_mask_t kern_mask) const diff --git a/src/hb.hh b/src/hb.hh index 5d0396a67..098b56604 100644 --- a/src/hb.hh +++ b/src/hb.hh @@ -237,6 +237,15 @@ struct _hb_alignof # define HB_FALLTHROUGH /* FALLTHROUGH */ #endif +#if defined(__clang__) +/* Disable certain sanitizer errors. */ +/* https://github.com/harfbuzz/harfbuzz/issues/1247 */ +#define HB_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW __attribute__((no_sanitize("signed-integer-overflow"))) +#else +#define HB_NO_SANITIZE_SIGNED_INTEGER_OVERFLOW +#endif + + #if defined(_WIN32) || defined(__CYGWIN__) /* We need Windows Vista for both Uniscribe backend and for * MemoryBarrier. We don't support compiling on Windows XP, diff --git a/test/shaping/data/in-house/tests/vertical.tests b/test/shaping/data/in-house/tests/vertical.tests index a16a7a002..b18119225 100644 --- a/test/shaping/data/in-house/tests/vertical.tests +++ b/test/shaping/data/in-house/tests/vertical.tests @@ -1,3 +1,3 @@ ../fonts/191826b9643e3f124d865d617ae609db6a2ce203.ttf:--direction=t --font-funcs=ft:U+300C:[uni300C.vert=0@-512,-578+0,-1024] ../fonts/f9b1dd4dcb515e757789a22cb4241107746fd3d0.ttf:--direction=t --font-funcs=ft:U+0041,U+0042:[gid1=0@-654,-2128+0,-2789|gid2=1@-665,-2125+0,-2789] -../fonts/f9b1dd4dcb515e757789a22cb4241107746fd3d0.ttf:--direction=t --font-funcs=ot:U+0041,U+0042:[gid1=0@-654,-2189+0,-2048|gid2=1@-665,-2189+0,-2048] +../fonts/f9b1dd4dcb515e757789a22cb4241107746fd3d0.ttf:--direction=t --font-funcs=ot:U+0041,U+0042:[gid1=0@-654,-1468+0,-2048|gid2=1@-665,-1462+0,-2048]