Fix state of `FT_Face' for buggy `gvar' tables (#57923). By resetting the blend as implemented with this commit fonts with invalid `gvar' tables may keep calling into `ft_var_load_gvar' from `tt_set_mm_blend' and failing, but the font was invalid anyway and we want to keep seeing the failure in `tt_set_mm_blend'. * src/truetype/ttgxvar.c (ft_var_load_gvar): Calculate length of offset array once. Allocate arrays after `FT_FRAME_ENTER' (extra check before allocating and avoid needing to free array later if error entering frame). Always call `FT_FRAME_EXIT'. Consistently set counts immediately after array initialized. Reset the blend (particularly `blend->glyphoffsets') on failure.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
diff --git a/ChangeLog b/ChangeLog
index 2886b70..6bbb957 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2020-02-29 Ben Wagner <bungeman@google.com>
+
+ [truetype] Fix state of `FT_Face' for buggy `gvar' tables (#57923).
+
+ By resetting the blend as implemented with this commit fonts with
+ invalid `gvar' tables may keep calling into `ft_var_load_gvar' from
+ `tt_set_mm_blend' and failing, but the font was invalid anyway and
+ we want to keep seeing the failure in `tt_set_mm_blend'.
+
+ * src/truetype/ttgxvar.c (ft_var_load_gvar): Calculate length of
+ offset array once.
+ Allocate arrays after `FT_FRAME_ENTER' (extra check before
+ allocating and avoid needing to free array later if error entering
+ frame).
+ Always call `FT_FRAME_EXIT'.
+ Consistently set counts immediately after array initialized.
+ Reset the blend (particularly `blend->glyphoffsets') on failure.
+
2020-03-01 Nikhil Ramakrishnan <ramakrishnan.nikhil@gmail.com>
[docs] Update docwriter stylesheet.
diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c
index ce6b62e..110f24a 100644
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -1470,6 +1470,7 @@
FT_ULong table_len;
FT_ULong gvar_start;
FT_ULong offsetToData;
+ FT_ULong offsets_len;
GX_GVar_Head gvar_head;
static const FT_Frame_Field gvar_fields[] =
@@ -1530,9 +1531,13 @@
goto Exit;
}
- /* rough sanity check: offsets can be either 2 or 4 bytes */
- if ( (FT_ULong)gvar_head.glyphCount *
- ( ( gvar_head.flags & 1 ) ? 4 : 2 ) > table_len )
+ /* offsets can be either 2 or 4 bytes */
+ /* (one more offset than glyphs, to mark size of last) */
+ offsets_len = ( gvar_head.glyphCount + 1 ) *
+ ( ( gvar_head.flags & 1 ) ? 4L : 2L );
+
+ /* rough sanity check */
+ if (offsets_len > table_len )
{
FT_TRACE1(( "ft_var_load_gvar: invalid number of glyphs\n" ));
error = FT_THROW( Invalid_Table );
@@ -1549,19 +1554,19 @@
gvar_head.globalCoordCount,
gvar_head.globalCoordCount == 1 ? "" : "s" ));
- if ( FT_NEW_ARRAY( blend->glyphoffsets, gvar_head.glyphCount + 1 ) )
+ if ( FT_FRAME_ENTER( offsets_len ) )
goto Exit;
+ /* offsets (one more offset than glyphs, to mark size of last) */
+ if ( FT_NEW_ARRAY( blend->glyphoffsets, gvar_head.glyphCount + 1 ) )
+ goto Fail2;
+
if ( gvar_head.flags & 1 )
{
FT_ULong limit = gvar_start + table_len;
FT_ULong max_offset = 0;
- /* long offsets (one more offset than glyphs, to mark size of last) */
- if ( FT_FRAME_ENTER( ( gvar_head.glyphCount + 1 ) * 4L ) )
- goto Exit;
-
for ( i = 0; i <= gvar_head.glyphCount; i++ )
{
blend->glyphoffsets[i] = offsetToData + FT_GET_ULONG();
@@ -1592,10 +1597,6 @@
FT_ULong max_offset = 0;
- /* short offsets (one more offset than glyphs, to mark size of last) */
- if ( FT_FRAME_ENTER( ( gvar_head.glyphCount + 1 ) * 2L ) )
- goto Exit;
-
for ( i = 0; i <= gvar_head.glyphCount; i++ )
{
blend->glyphoffsets[i] = offsetToData + FT_GET_USHORT() * 2;
@@ -1621,12 +1622,10 @@
}
}
- FT_FRAME_EXIT();
- if ( error )
- goto Exit;
-
blend->gv_glyphcnt = gvar_head.glyphCount;
+ FT_FRAME_EXIT();
+
if ( gvar_head.globalCoordCount != 0 )
{
if ( FT_STREAM_SEEK( gvar_start + gvar_head.offsetToCoord ) ||
@@ -1635,16 +1634,14 @@
{
FT_TRACE2(( "ft_var_load_gvar:"
" glyph variation shared tuples missing\n" ));
- goto Exit;
+ goto Fail;
}
if ( FT_NEW_ARRAY( blend->tuplecoords,
gvar_head.axisCount * gvar_head.globalCoordCount ) )
- goto Exit;
-
- blend->tuplecount = gvar_head.globalCoordCount;
+ goto Fail2;
- for ( i = 0; i < blend->tuplecount; i++ )
+ for ( i = 0; i < gvar_head.globalCoordCount; i++ )
{
FT_TRACE5(( " [ " ));
for ( j = 0; j < (FT_UInt)gvar_head.axisCount; j++ )
@@ -1657,6 +1654,8 @@
FT_TRACE5(( "]\n" ));
}
+ blend->tuplecount = gvar_head.globalCoordCount;
+
FT_TRACE5(( "\n" ));
FT_FRAME_EXIT();
@@ -1664,6 +1663,14 @@
Exit:
return error;
+
+ Fail2:
+ FT_FRAME_EXIT();
+
+ Fail:
+ FT_FREE( blend->glyphoffsets );
+ blend->gv_glyphcnt = 0;
+ goto Exit;
}