[sfnt] Streamline POST format 2.0 handing. To reduce memory allocations, we read an entire Pascal-string buffer and convert it to a C-string buffer. We also reject tables with Postscript glyph names exceeding 63 bytes. * src/sfnt/ttpost.c (load_format20): Implement it. (load_post_names): Check the minimal POST table size. (load_format25, tt_face_free_ps_names): Updated accordingly.
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 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
diff --git a/ChangeLog b/ChangeLog
index 122fc56..998155a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,16 @@
-2021-04-25 Alexei Podtelezhnikov <apodtele@gmail.com>
+2021-05-03 Alexei Podtelezhnikov <apodtele@gmail.com>
+
+ [sfnt] Streamline POST format 2.0 handing.
+
+ To reduce memory allocations, we read an entire Pascal-string buffer
+ and convert it to a C-string buffer. We also reject tables with
+ Postscript glyph names exceeding 63 bytes.
+
+ * src/sfnt/ttpost.c (load_format20): Implement it.
+ (load_post_names): Check the minimal POST table size.
+ (load_format25, tt_face_free_ps_names): Updated accordingly.
+
+2021-05-02 Alexei Podtelezhnikov <apodtele@gmail.com>
[bdf,pcf] Avoid memory zeroing (contd.).
diff --git a/src/sfnt/ttpost.c b/src/sfnt/ttpost.c
index 6d34ce4..5ce7706 100644
--- a/src/sfnt/ttpost.c
+++ b/src/sfnt/ttpost.c
@@ -158,7 +158,7 @@
static FT_Error
load_format_20( TT_Face face,
FT_Stream stream,
- FT_ULong post_limit )
+ FT_ULong post_len )
{
FT_Memory memory = stream->memory;
FT_Error error;
@@ -168,6 +168,7 @@
FT_UShort* glyph_indices = NULL;
FT_Char** name_strings = NULL;
+ FT_Byte* strings = NULL;
if ( FT_READ_USHORT( num_glyphs ) )
@@ -179,7 +180,8 @@
/* There already exist fonts which have more than 32768 glyph names */
/* in this table, so the test for this threshold has been dropped. */
- if ( num_glyphs > face->max_profile.numGlyphs )
+ if ( num_glyphs > face->max_profile.numGlyphs ||
+ num_glyphs * 2UL > post_len - 2 )
{
error = FT_THROW( Invalid_File_Format );
goto Exit;
@@ -190,8 +192,8 @@
FT_Int n;
- if ( FT_QNEW_ARRAY ( glyph_indices, num_glyphs ) ||
- FT_FRAME_ENTER( num_glyphs * 2L ) )
+ if ( FT_QNEW_ARRAY( glyph_indices, num_glyphs ) ||
+ FT_FRAME_ENTER( num_glyphs * 2L ) )
goto Fail;
for ( n = 0; n < num_glyphs; n++ )
@@ -223,60 +225,56 @@
}
/* now load the name strings */
+ if ( num_names )
{
FT_UShort n;
+ FT_ULong p;
+
+ post_len -= num_glyphs * 2UL + 2;
- if ( FT_QNEW_ARRAY( name_strings, num_names ) )
+ if ( FT_QALLOC( strings, post_len + 1 ) ||
+ FT_STREAM_READ( strings, post_len ) ||
+ FT_QNEW_ARRAY( name_strings, num_names ) )
goto Fail;
- for ( n = 0; n < num_names; n++ )
+ /* convert from Pascal- to C-strings and set pointers */
+ for ( p = 0, n = 0; p < post_len && n < num_names; n++ )
{
- FT_UInt len;
+ FT_UInt len = strings[p];
- if ( FT_STREAM_POS() >= post_limit )
- break;
- else
- {
- FT_TRACE6(( "load_format_20: %ld byte left in post table\n",
- post_limit - FT_STREAM_POS() ));
-
- if ( FT_READ_BYTE( len ) )
- goto Fail1;
- }
-
- if ( len > post_limit ||
- FT_STREAM_POS() > post_limit - len )
+ if ( len > 63U )
{
- FT_Int d = (FT_Int)post_limit - (FT_Int)FT_STREAM_POS();
-
-
- FT_ERROR(( "load_format_20:"
- " exceeding string length (%d),"
- " truncating at end of post table (%d byte left)\n",
- len, d ));
- len = (FT_UInt)FT_MAX( 0, d );
+ error = FT_THROW( Invalid_File_Format );
+ goto Fail;
}
- if ( FT_QNEW_ARRAY( name_strings[n], len + 1 ) ||
- FT_STREAM_READ( name_strings[n], len ) )
- goto Fail1;
-
- name_strings[n][len] = '\0';
+ strings[p] = 0;
+ name_strings[n] = (FT_Char*)strings + p + 1;
+ p += len + 1;
}
+ strings[post_len] = 0;
+ /* deal with missing or insufficient string data */
if ( n < num_names )
{
+ if ( post_len == 0 )
+ {
+ /* fake empty string */
+ if ( FT_QREALLOC( strings, 1, 2 ) )
+ goto Fail;
+
+ post_len = 1;
+ strings[post_len] = 0;
+ }
+
FT_ERROR(( "load_format_20:"
" all entries in post table are already parsed,"
" using NULL names for gid %d - %d\n",
n, num_names - 1 ));
for ( ; n < num_names; n++ )
- if ( FT_QNEW_ARRAY( name_strings[n], 1 ) )
- goto Fail1;
- else
- name_strings[n][0] = '\0';
+ name_strings[n] = (FT_Char*)strings + post_len;
}
}
@@ -292,17 +290,9 @@
}
return FT_Err_Ok;
- Fail1:
- {
- FT_UShort n;
-
-
- for ( n = 0; n < num_names; n++ )
- FT_FREE( name_strings[n] );
- }
-
Fail:
FT_FREE( name_strings );
+ FT_FREE( strings );
FT_FREE( glyph_indices );
Exit:
@@ -313,7 +303,7 @@
static FT_Error
load_format_25( TT_Face face,
FT_Stream stream,
- FT_ULong post_limit )
+ FT_ULong post_len )
{
FT_Memory memory = stream->memory;
FT_Error error;
@@ -321,7 +311,7 @@
FT_Int num_glyphs;
FT_Char* offset_table = NULL;
- FT_UNUSED( post_limit );
+ FT_UNUSED( post_len );
if ( FT_READ_USHORT( num_glyphs ) )
@@ -384,7 +374,6 @@
FT_Error error;
FT_Fixed format;
FT_ULong post_len;
- FT_ULong post_limit;
/* get a stream for the face's resource */
@@ -395,8 +384,6 @@
if ( error )
goto Exit;
- post_limit = FT_STREAM_POS() + post_len;
-
format = face->postscript.FormatType;
/* go to beginning of subtable */
@@ -404,10 +391,10 @@
goto Exit;
/* now read postscript table */
- if ( format == 0x00020000L )
- error = load_format_20( face, stream, post_limit );
- else if ( format == 0x00025000L )
- error = load_format_25( face, stream, post_limit );
+ if ( format == 0x00020000L && post_len >= 34 )
+ error = load_format_20( face, stream, post_len - 32 );
+ else if ( format == 0x00025000L && post_len >= 34 )
+ error = load_format_25( face, stream, post_len - 32 );
else
error = FT_THROW( Invalid_File_Format );
@@ -433,17 +420,19 @@
if ( format == 0x00020000L )
{
TT_Post_20 table = &names->names.format_20;
- FT_UShort n;
FT_FREE( table->glyph_indices );
table->num_glyphs = 0;
- for ( n = 0; n < table->num_names; n++ )
- FT_FREE( table->glyph_names[n] );
+ if ( table->num_names )
+ {
+ table->glyph_names[0]--;
+ FT_FREE( table->glyph_names[0] );
- FT_FREE( table->glyph_names );
- table->num_names = 0;
+ FT_FREE( table->glyph_names );
+ table->num_names = 0;
+ }
}
else if ( format == 0x00025000L )
{