[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.
This commit is contained in:
parent
ec95f9c921
commit
66630d882c
14
ChangeLog
14
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.).
|
[bdf,pcf] Avoid memory zeroing (contd.).
|
||||||
|
|
||||||
|
|
|
@ -158,7 +158,7 @@
|
||||||
static FT_Error
|
static FT_Error
|
||||||
load_format_20( TT_Face face,
|
load_format_20( TT_Face face,
|
||||||
FT_Stream stream,
|
FT_Stream stream,
|
||||||
FT_ULong post_limit )
|
FT_ULong post_len )
|
||||||
{
|
{
|
||||||
FT_Memory memory = stream->memory;
|
FT_Memory memory = stream->memory;
|
||||||
FT_Error error;
|
FT_Error error;
|
||||||
|
@ -168,6 +168,7 @@
|
||||||
|
|
||||||
FT_UShort* glyph_indices = NULL;
|
FT_UShort* glyph_indices = NULL;
|
||||||
FT_Char** name_strings = NULL;
|
FT_Char** name_strings = NULL;
|
||||||
|
FT_Byte* strings = NULL;
|
||||||
|
|
||||||
|
|
||||||
if ( FT_READ_USHORT( num_glyphs ) )
|
if ( FT_READ_USHORT( num_glyphs ) )
|
||||||
|
@ -179,7 +180,8 @@
|
||||||
/* There already exist fonts which have more than 32768 glyph names */
|
/* There already exist fonts which have more than 32768 glyph names */
|
||||||
/* in this table, so the test for this threshold has been dropped. */
|
/* 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 );
|
error = FT_THROW( Invalid_File_Format );
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
@ -190,8 +192,8 @@
|
||||||
FT_Int n;
|
FT_Int n;
|
||||||
|
|
||||||
|
|
||||||
if ( FT_QNEW_ARRAY ( glyph_indices, num_glyphs ) ||
|
if ( FT_QNEW_ARRAY( glyph_indices, num_glyphs ) ||
|
||||||
FT_FRAME_ENTER( num_glyphs * 2L ) )
|
FT_FRAME_ENTER( num_glyphs * 2L ) )
|
||||||
goto Fail;
|
goto Fail;
|
||||||
|
|
||||||
for ( n = 0; n < num_glyphs; n++ )
|
for ( n = 0; n < num_glyphs; n++ )
|
||||||
|
@ -223,60 +225,56 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now load the name strings */
|
/* now load the name strings */
|
||||||
|
if ( num_names )
|
||||||
{
|
{
|
||||||
FT_UShort n;
|
FT_UShort n;
|
||||||
|
FT_ULong p;
|
||||||
|
|
||||||
|
|
||||||
if ( FT_QNEW_ARRAY( name_strings, num_names ) )
|
post_len -= num_glyphs * 2UL + 2;
|
||||||
|
|
||||||
|
if ( FT_QALLOC( strings, post_len + 1 ) ||
|
||||||
|
FT_STREAM_READ( strings, post_len ) ||
|
||||||
|
FT_QNEW_ARRAY( name_strings, num_names ) )
|
||||||
goto Fail;
|
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 )
|
if ( len > 63U )
|
||||||
break;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
FT_TRACE6(( "load_format_20: %ld byte left in post table\n",
|
error = FT_THROW( Invalid_File_Format );
|
||||||
post_limit - FT_STREAM_POS() ));
|
goto Fail;
|
||||||
|
|
||||||
if ( FT_READ_BYTE( len ) )
|
|
||||||
goto Fail1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( len > post_limit ||
|
strings[p] = 0;
|
||||||
FT_STREAM_POS() > post_limit - len )
|
name_strings[n] = (FT_Char*)strings + p + 1;
|
||||||
{
|
p += len + 1;
|
||||||
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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( FT_QNEW_ARRAY( name_strings[n], len + 1 ) ||
|
|
||||||
FT_STREAM_READ( name_strings[n], len ) )
|
|
||||||
goto Fail1;
|
|
||||||
|
|
||||||
name_strings[n][len] = '\0';
|
|
||||||
}
|
}
|
||||||
|
strings[post_len] = 0;
|
||||||
|
|
||||||
|
/* deal with missing or insufficient string data */
|
||||||
if ( n < num_names )
|
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:"
|
FT_ERROR(( "load_format_20:"
|
||||||
" all entries in post table are already parsed,"
|
" all entries in post table are already parsed,"
|
||||||
" using NULL names for gid %d - %d\n",
|
" using NULL names for gid %d - %d\n",
|
||||||
n, num_names - 1 ));
|
n, num_names - 1 ));
|
||||||
for ( ; n < num_names; n++ )
|
for ( ; n < num_names; n++ )
|
||||||
if ( FT_QNEW_ARRAY( name_strings[n], 1 ) )
|
name_strings[n] = (FT_Char*)strings + post_len;
|
||||||
goto Fail1;
|
|
||||||
else
|
|
||||||
name_strings[n][0] = '\0';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,17 +290,9 @@
|
||||||
}
|
}
|
||||||
return FT_Err_Ok;
|
return FT_Err_Ok;
|
||||||
|
|
||||||
Fail1:
|
|
||||||
{
|
|
||||||
FT_UShort n;
|
|
||||||
|
|
||||||
|
|
||||||
for ( n = 0; n < num_names; n++ )
|
|
||||||
FT_FREE( name_strings[n] );
|
|
||||||
}
|
|
||||||
|
|
||||||
Fail:
|
Fail:
|
||||||
FT_FREE( name_strings );
|
FT_FREE( name_strings );
|
||||||
|
FT_FREE( strings );
|
||||||
FT_FREE( glyph_indices );
|
FT_FREE( glyph_indices );
|
||||||
|
|
||||||
Exit:
|
Exit:
|
||||||
|
@ -313,7 +303,7 @@
|
||||||
static FT_Error
|
static FT_Error
|
||||||
load_format_25( TT_Face face,
|
load_format_25( TT_Face face,
|
||||||
FT_Stream stream,
|
FT_Stream stream,
|
||||||
FT_ULong post_limit )
|
FT_ULong post_len )
|
||||||
{
|
{
|
||||||
FT_Memory memory = stream->memory;
|
FT_Memory memory = stream->memory;
|
||||||
FT_Error error;
|
FT_Error error;
|
||||||
|
@ -321,7 +311,7 @@
|
||||||
FT_Int num_glyphs;
|
FT_Int num_glyphs;
|
||||||
FT_Char* offset_table = NULL;
|
FT_Char* offset_table = NULL;
|
||||||
|
|
||||||
FT_UNUSED( post_limit );
|
FT_UNUSED( post_len );
|
||||||
|
|
||||||
|
|
||||||
if ( FT_READ_USHORT( num_glyphs ) )
|
if ( FT_READ_USHORT( num_glyphs ) )
|
||||||
|
@ -384,7 +374,6 @@
|
||||||
FT_Error error;
|
FT_Error error;
|
||||||
FT_Fixed format;
|
FT_Fixed format;
|
||||||
FT_ULong post_len;
|
FT_ULong post_len;
|
||||||
FT_ULong post_limit;
|
|
||||||
|
|
||||||
|
|
||||||
/* get a stream for the face's resource */
|
/* get a stream for the face's resource */
|
||||||
|
@ -395,8 +384,6 @@
|
||||||
if ( error )
|
if ( error )
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
post_limit = FT_STREAM_POS() + post_len;
|
|
||||||
|
|
||||||
format = face->postscript.FormatType;
|
format = face->postscript.FormatType;
|
||||||
|
|
||||||
/* go to beginning of subtable */
|
/* go to beginning of subtable */
|
||||||
|
@ -404,10 +391,10 @@
|
||||||
goto Exit;
|
goto Exit;
|
||||||
|
|
||||||
/* now read postscript table */
|
/* now read postscript table */
|
||||||
if ( format == 0x00020000L )
|
if ( format == 0x00020000L && post_len >= 34 )
|
||||||
error = load_format_20( face, stream, post_limit );
|
error = load_format_20( face, stream, post_len - 32 );
|
||||||
else if ( format == 0x00025000L )
|
else if ( format == 0x00025000L && post_len >= 34 )
|
||||||
error = load_format_25( face, stream, post_limit );
|
error = load_format_25( face, stream, post_len - 32 );
|
||||||
else
|
else
|
||||||
error = FT_THROW( Invalid_File_Format );
|
error = FT_THROW( Invalid_File_Format );
|
||||||
|
|
||||||
|
@ -433,17 +420,19 @@
|
||||||
if ( format == 0x00020000L )
|
if ( format == 0x00020000L )
|
||||||
{
|
{
|
||||||
TT_Post_20 table = &names->names.format_20;
|
TT_Post_20 table = &names->names.format_20;
|
||||||
FT_UShort n;
|
|
||||||
|
|
||||||
|
|
||||||
FT_FREE( table->glyph_indices );
|
FT_FREE( table->glyph_indices );
|
||||||
table->num_glyphs = 0;
|
table->num_glyphs = 0;
|
||||||
|
|
||||||
for ( n = 0; n < table->num_names; n++ )
|
if ( table->num_names )
|
||||||
FT_FREE( table->glyph_names[n] );
|
{
|
||||||
|
table->glyph_names[0]--;
|
||||||
|
FT_FREE( table->glyph_names[0] );
|
||||||
|
|
||||||
FT_FREE( table->glyph_names );
|
FT_FREE( table->glyph_names );
|
||||||
table->num_names = 0;
|
table->num_names = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if ( format == 0x00025000L )
|
else if ( format == 0x00025000L )
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue