diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c index 054da2523..acb712174 100644 --- a/src/cairo-ft-font.c +++ b/src/cairo-ft-font.c @@ -2370,6 +2370,11 @@ _cairo_ft_load_truetype_table (void *abstract_font, FT_Face face; cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; + /* We don't support the FreeType feature of loading a table + * without specifying the size since this may overflow our + * buffer. */ + assert (length != NULL); + if (_cairo_ft_scaled_font_is_vertical (&scaled_font->base)) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -2378,9 +2383,13 @@ _cairo_ft_load_truetype_table (void *abstract_font, if (!face) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - if (FT_IS_SFNT (face) && - FT_Load_Sfnt_Table (face, tag, offset, buffer, length) == 0) - status = CAIRO_STATUS_SUCCESS; + if (FT_IS_SFNT (face)) { + if (buffer == NULL) + *length = 0; + + if (FT_Load_Sfnt_Table (face, tag, offset, buffer, length) == 0) + status = CAIRO_STATUS_SUCCESS; + } _cairo_ft_unscaled_font_unlock_face (unscaled); #endif diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c index fcd7b5601..d0c29bbda 100644 --- a/src/cairo-win32-font.c +++ b/src/cairo-win32-font.c @@ -1514,6 +1514,7 @@ _cairo_win32_scaled_font_load_truetype_table (void *abstract_font, cairo_win32_scaled_font_t *scaled_font = abstract_font; HDC hdc; cairo_status_t status; + DWORD ret; hdc = _get_global_font_dc (); assert (hdc != NULL); @@ -1523,9 +1524,11 @@ _cairo_win32_scaled_font_load_truetype_table (void *abstract_font, if (status) return status; - *length = GetFontData (hdc, tag, offset, buffer, *length); - if (*length == GDI_ERROR) + ret = GetFontData (hdc, tag, offset, buffer, *length); + if (ret == GDI_ERROR || (buffer && ret != *length)) status = CAIRO_INT_STATUS_UNSUPPORTED; + else + *length = ret; cairo_win32_scaled_font_done_font (&scaled_font->base); diff --git a/src/cairoint.h b/src/cairoint.h index 5a435618f..1510f8ec4 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -502,6 +502,24 @@ struct _cairo_scaled_font_backend { cairo_region_t *clip_region, int *remaining_glyphs); + /* Read data from a sfnt font table. + * @scaled_font: font + * @tag: 4 byte table name specifying the table to read. + * @offset: offset into the table + * @buffer: buffer to write data into. Caller must ensure there is sufficient space. + * If NULL, return the size of the table in @length. + * @length: If @buffer is NULL, the size of the table will be returned in @length. + * If @buffer is not null, @length specifies the number of bytes to read. + * + * If less than @length bytes are available to read this function + * returns CAIRO_INT_STATUS_UNSUPPORTED. Note that requesting more + * bytes than are available in the table may continue reading data + * from the following table and return success. If this is + * undesirable the caller should first query the table size. If an + * error occurs the output value of @length is undefined. + * + * Returns CAIRO_INT_STATUS_UNSUPPORTED if not a sfnt style font or table not found. + */ cairo_warn cairo_int_status_t (*load_truetype_table)(void *scaled_font, unsigned long tag,