ref: bb7668d7c30e16ef1d6442c4aa2b694fadd15295
parent: 1e0207681544327f9e96c6d50231b6fbc1f6ed70
author: Nikhil Ramakrishnan <[email protected]>
date: Sun Jul 28 15:38:05 EDT 2019
[woff2] Improve memory and error handling. Free up memory after use, and improve error handling. * src/sfnt/sfwoff2.c (reconstruct_font, woff2_open_font): Implement changes.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
2019-08-27 Nikhil Ramakrishnan <[email protected]>
+ [woff2] Improve memory and error handling.
+
+ Free up memory after use, and improve error handling.
+
+ * src/sfnt/sfwoff2.c (reconstruct_font, woff2_open_font): Implement
+ changes.
+
+2019-08-27 Nikhil Ramakrishnan <[email protected]>
+
[woff2] Avoid too many calls to `FT_REALLOC'.
We do this by using `totalSfntSize' as an initial reference, and
--- a/src/sfnt/sfwoff2.c
+++ b/src/sfnt/sfwoff2.c
@@ -1333,6 +1333,7 @@
FT_Int nn = 0;
FT_UShort num_hmetrics;
FT_ULong font_checksum = info->header_checksum;
+ FT_Bool is_glyf_xform = FALSE;
FT_ULong table_entry_offset = 12;
WOFF2_Table head_table;
@@ -1370,7 +1371,8 @@
if ( FT_NEW( stream ) )
return FT_THROW( Invalid_Table );
FT_Stream_OpenMemory( stream, transformed_buf, transformed_buf_size );
- stream->close = stream_close;
+ stream->memory = memory;
+ stream->close = stream_close;
FT_ASSERT( FT_STREAM_POS() == 0 );
@@ -1432,6 +1434,7 @@
if( table.Tag == TTAG_glyf )
{
+ is_glyf_xform = TRUE;
table.dst_offset = dest_offset;
if( reconstruct_glyf( stream, &table, &checksum,
@@ -1447,6 +1450,12 @@
}
else if( table.Tag == TTAG_hmtx )
{
+ if( !is_glyf_xform )
+ {
+ FT_ERROR(( "hmtx is transformed but glyf is not.\n" ));
+ error = FT_THROW( Unimplemented_Feature );
+ goto Fail;
+ }
table.dst_offset = dest_offset;
if( reconstruct_hmtx( stream, table.src_length, info->num_glyphs,
info->num_hmetrics, info->x_mins, &checksum,
@@ -1501,7 +1510,11 @@
/* Set pointer of sfnt stream to its correct value. */
*sfnt_bytes = sfnt;
+
FT_FREE( table_entry );
+ FT_Stream_Close( stream );
+ FT_FREE( stream );
+
return error;
Fail:
@@ -1509,10 +1522,10 @@
error = FT_THROW( Invalid_Table );
FT_FREE( table_entry );
+ FT_Stream_Close( stream );
+ FT_FREE( stream );
return error;
-
- /* TODO free the uncompressed stream after everything is done. */
}
@@ -1673,7 +1686,8 @@
if( table->Tag == TTAG_loca && table->TransformLength )
{
FT_ERROR(( "woff_font_open: Invalid loca `transformLength'.\n" ));
- return FT_THROW( Invalid_Table );
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
}
}
@@ -1680,7 +1694,8 @@
if ( src_offset + table->TransformLength < src_offset )
{
FT_ERROR(( "woff_font_open: invalid WOFF2 table directory.\n" ));
- return FT_THROW( Invalid_Table );
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
}
table->src_offset = src_offset;
@@ -1708,7 +1723,11 @@
woff2.uncompressed_size = last_table->src_offset
+ last_table->src_length;
if( woff2.uncompressed_size < last_table->src_offset )
- return FT_THROW( Invalid_Table );
+ {
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+
/* DEBUG - Remove later. */
FT_TRACE2(( "Uncompressed size: %ld\n", woff2.uncompressed_size ));
@@ -1724,7 +1743,10 @@
FT_TRACE2(( "Header version: %lx\n", woff2.header_version ));
if( woff2.header_version != 0x00010000 &&
woff2.header_version != 0x00020000 )
- return FT_THROW( Invalid_Table );
+ {
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
if( READ_255USHORT( woff2.num_fonts ) )
goto Exit;
@@ -1779,10 +1801,10 @@
{
if( glyf_index > loca_index ||
loca_index - glyf_index != 1 )
- return FT_THROW( Invalid_Table );
- /* DEBUG - Remove later */
- else
- FT_TRACE2(( "glyf and loca indices are valid.\n" ));
+ {
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
}
}
/* Collection directory reading complete. */
@@ -1795,12 +1817,18 @@
/* Few more checks before we start reading the tables. */
if( file_offset > woff2.length )
- return FT_THROW( Invalid_Table );
+ {
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
if ( woff2.metaOffset )
{
if ( file_offset != woff2.metaOffset )
- return FT_THROW( Invalid_Table );
+ {
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
file_offset = ROUND4(woff2.metaOffset + woff2.metaLength);
}
@@ -1807,12 +1835,18 @@
if( woff2.privOffset )
{
if( file_offset != woff2.privOffset )
- return FT_THROW( Invalid_Table );
+ {
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
file_offset = ROUND4(woff2.privOffset + woff2.privLength);
}
if( file_offset != ( ROUND4( woff2.length ) ) )
- return FT_THROW( Invalid_Table );
+ {
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
/* Only retain tables of the requested face in a TTC. */
/* TODO Check whether it is OK for rest of the code to be unaware of the
@@ -1919,13 +1953,15 @@
error = woff2_uncompress( uncompressed_buf, woff2.uncompressed_size,
stream->cursor, woff2.totalCompressedSize );
if( error )
- goto Exit;
+ goto Exit;
FT_FRAME_EXIT();
- reconstruct_font( uncompressed_buf, woff2.uncompressed_size,
- indices, &woff2, &info, &sfnt, &sfnt_size,
- memory );
+ error = reconstruct_font( uncompressed_buf, woff2.uncompressed_size,
+ indices, &woff2, &info, &sfnt, &sfnt_size,
+ memory );
+ if( error )
+ goto Exit;
/* Resize `sfnt' to actual size of sfnt stream. */
if ( woff2.actual_sfnt_size < sfnt_size )
@@ -1953,7 +1989,7 @@
face->root.face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM;
- /* Set face_index to 0. */
+ /* Set face_index to 0. */
*face_instance_index = 0;
/* error = FT_THROW( Unimplemented_Feature ); */
@@ -1964,13 +2000,15 @@
Exit:
FT_FREE( tables );
FT_FREE( indices );
- FT_FREE( uncompressed_buf );
if( error )
{
FT_FREE( sfnt );
- FT_Stream_Close( sfnt_stream );
- FT_FREE( sfnt_stream );
+ if ( sfnt_stream )
+ {
+ FT_Stream_Close( sfnt_stream );
+ FT_FREE( sfnt_stream );
+ }
}
return error;