diff options
author | Dominik Röttsches <drott@chromium.org> | 2023-01-04 15:52:41 +0200 |
---|---|---|
committer | Werner Lemberg <wl@gnu.org> | 2023-01-05 09:35:32 +0100 |
commit | 63f371367aeefa73541617edfb1dcef9428796fb (patch) | |
tree | 6fe8fac48c2881ae8c1ad7e75d49792db5950187 /src | |
parent | 81a456b28f195b4d4e48aff03359aaa68ae6e3b4 (diff) | |
download | freetype2-63f371367aeefa73541617edfb1dcef9428796fb.tar.gz |
[sfnt] Fix color stop bounds check calculation at table end.
Fixes https://bugs.chromium.org/p/skia/issues/detail?id=14021
* src/sfnt/ttcolr.c (VAR_IDX_BASE_SIZE): New macro.
(tt_face_get_colorline_stops): Fix off-by-one bounds check calculation, take
`VarColorStop` into account, and hopefully make it easier to read.
Diffstat (limited to 'src')
-rw-r--r-- | src/sfnt/ttcolr.c | 24 |
1 files changed, 17 insertions, 7 deletions
diff --git a/src/sfnt/ttcolr.c b/src/sfnt/ttcolr.c index da808230f..3f8ba3bec 100644 --- a/src/sfnt/ttcolr.c +++ b/src/sfnt/ttcolr.c @@ -56,6 +56,7 @@ #define LAYER_V1_LIST_PAINT_OFFSET_SIZE 4U #define LAYER_V1_LIST_NUM_LAYERS_SIZE 4U #define COLOR_STOP_SIZE 6U +#define VAR_IDX_BASE_SIZE 4U #define LAYER_SIZE 4U /* https://docs.microsoft.com/en-us/typography/opentype/spec/colr#colr-header */ /* 3 * uint16 + 2 * Offset32 */ @@ -1618,20 +1619,29 @@ FT_Byte* p; FT_ULong var_index_base; + FT_Byte* last_entry_p = NULL; + FT_UInt entry_size = COLOR_STOP_SIZE; - if ( !colr || !colr->table ) + if ( !colr || !colr->table || !iterator ) return 0; if ( iterator->current_color_stop >= iterator->num_color_stops ) return 0; - /* Subtract 3 times 2 because we need to succeed in reading */ - /* three 2-byte short values. */ - if ( iterator->p + - ( iterator->num_color_stops - iterator->current_color_stop ) * - COLOR_STOP_SIZE > - (FT_Byte*)colr->table + colr->table_size - 1 - 2 - 2 - 2 ) + if ( iterator->read_variable ) + entry_size += VAR_IDX_BASE_SIZE; + + /* Calculate the start pointer for the last to-be-read (Var)ColorStop */ + /* and check whether we can read a full (Var)ColorStop at that */ + /* position by comparing it to the position that is the size of one */ + /* (Var)ColorStop before the end of the 'COLR' table. */ + last_entry_p = + iterator->p + ( iterator->num_color_stops - 1 - + iterator->current_color_stop ) * entry_size; + if ( iterator->p < colr->paints_start_v1 || + last_entry_p > (FT_Byte*)colr->table + + colr->table_size - entry_size ) return 0; /* Iterator points at first `ColorStop` of `ColorLine`. */ |