[sfnt] Avoid unnecessarily large allocation for WOFFs (#46257).

* src/sfnt/sfobjs.c (woff_open_font): Use WOFF's `totalSfntSize'
only after thorough checks.
Add tracing messages.
This commit is contained in:
Werner Lemberg 2015-10-21 08:04:29 +02:00
parent 649ca5562d
commit e6593389cf
4 changed files with 132 additions and 7 deletions

View File

@ -1,3 +1,11 @@
2015-10-21 Werner Lemberg <wl@gnu.org>
[sfnt] Avoid unnecessarily large allocation for WOFFs (#46257).
* src/sfnt/sfobjs.c (woff_open_font): Use WOFF's `totalSfntSize'
only after thorough checks.
Add tracing messages.
2015-10-21 Werner Lemberg <wl@gnu.org>
[type42] Better check invalid `sfnts' array data (#46255).

View File

@ -179,6 +179,34 @@
};
const AF_Script_UniRangeRec af_khmr_uniranges[] =
{
AF_UNIRANGE_REC( 0x1780UL, 0x17FFUL ), /* Khmer */
AF_UNIRANGE_REC( 0UL, 0UL )
};
const AF_Script_UniRangeRec af_khmr_nonbase_uniranges[] =
{
AF_UNIRANGE_REC( 0x17B7UL, 0x17BDUL ),
AF_UNIRANGE_REC( 0x17C6UL, 0x17C6UL ),
AF_UNIRANGE_REC( 0x17C9UL, 0x17D3UL ),
AF_UNIRANGE_REC( 0x17DDUL, 0x17DDUL ),
AF_UNIRANGE_REC( 0UL, 0UL )
};
const AF_Script_UniRangeRec af_khms_uniranges[] =
{
AF_UNIRANGE_REC( 0x19E0UL, 0x19FFUL ), /* Khmer Symbols */
AF_UNIRANGE_REC( 0UL, 0UL )
};
const AF_Script_UniRangeRec af_khms_nonbase_uniranges[] =
{
AF_UNIRANGE_REC( 0UL, 0UL )
};
const AF_Script_UniRangeRec af_lao_uniranges[] =
{
AF_UNIRANGE_REC( 0x0E80UL, 0x0EFFUL ), /* Lao */

View File

@ -451,10 +451,14 @@
woff.metaOrigLength != 0 ) ) ||
( woff.metaLength != 0 && woff.metaOrigLength == 0 ) ||
( woff.privOffset == 0 && woff.privLength != 0 ) )
{
FT_ERROR(( "woff_font_open: invalid WOFF header\n" ));
return FT_THROW( Invalid_Table );
}
if ( FT_ALLOC( sfnt, woff.totalSfntSize ) ||
FT_NEW( sfnt_stream ) )
/* Don't trust `totalSfntSize' before thorough checks. */
if ( FT_ALLOC( sfnt, 12 + woff.num_tables * 16UL ) ||
FT_NEW( sfnt_stream ) )
goto Exit;
sfnt_header = sfnt;
@ -521,6 +525,8 @@
if ( table->Tag <= old_tag )
{
FT_FRAME_EXIT();
FT_ERROR(( "woff_font_open: table tags are not sorted\n" ));
error = FT_THROW( Invalid_Table );
goto Exit;
}
@ -555,6 +561,7 @@
sfnt_offset > woff.totalSfntSize - table->OrigLength ||
table->CompLength > table->OrigLength )
{
FT_ERROR(( "woff_font_open: invalid table offsets\n" ));
error = FT_THROW( Invalid_Table );
goto Exit;
}
@ -580,6 +587,8 @@
if ( woff.metaOffset != woff_offset ||
woff.metaOffset + woff.metaLength > woff.length )
{
FT_ERROR(( "woff_font_open:"
" invalid `metadata' offset or length\n" ));
error = FT_THROW( Invalid_Table );
goto Exit;
}
@ -596,6 +605,7 @@
if ( woff.privOffset != woff_offset ||
woff.privOffset + woff.privLength > woff.length )
{
FT_ERROR(( "woff_font_open: invalid `private' offset or length\n" ));
error = FT_THROW( Invalid_Table );
goto Exit;
}
@ -607,10 +617,19 @@
if ( sfnt_offset != woff.totalSfntSize ||
woff_offset != woff.length )
{
FT_ERROR(( "woff_font_open: invalid `sfnt' table structure\n" ));
error = FT_THROW( Invalid_Table );
goto Exit;
}
/* Now use `totalSfntSize'. */
if ( FT_REALLOC( sfnt,
12 + woff.num_tables * 16UL,
woff.totalSfntSize ) )
goto Exit;
sfnt_header = sfnt + 12;
/* Write the tables. */
for ( nn = 0; nn < woff.num_tables; nn++ )
@ -651,6 +670,7 @@
goto Exit;
if ( output_len != table->OrigLength )
{
FT_ERROR(( "woff_font_open: compressed table length mismatch\n" ));
error = FT_THROW( Invalid_Table );
goto Exit;
}

View File

@ -3,6 +3,9 @@
# error "a C++11 compiler is needed"
#endif
#include <archive.h>
#include <archive_entry.h>
#include <assert.h>
#include <stdint.h>
@ -45,6 +48,59 @@ using namespace std;
FT_Global global_ft;
static int
archive_read_entry_data( struct archive *ar, vector<FT_Byte> *vw )
{
int r;
const FT_Byte *buff;
size_t size;
int64_t offset;
for (;;) {
r = archive_read_data_block( ar, reinterpret_cast<const void**>(&buff), &size, &offset );
if (r == ARCHIVE_EOF)
return (ARCHIVE_OK);
if (r != ARCHIVE_OK)
return (r);
vw->insert(vw->end(), buff, buff + size);
}
}
static vector<vector<FT_Byte>>
parse_data( const uint8_t* data,
size_t size )
{
struct archive_entry *entry;
int r;
vector<vector<FT_Byte>> files;
unique_ptr<struct archive, decltype ( archive_read_free )*> a( archive_read_new(), archive_read_free );
archive_read_support_format_tar(a.get());
// The need for the const_cast was removed with libarchive be4d4ddcfca77f6e43753156eaa919f4d25ed903
if (!(r = archive_read_open_memory( a.get(), const_cast<void*>(static_cast<const void*>(data)), size )))
{
unique_ptr<struct archive, decltype ( archive_read_close )*> a_open( a.get(), archive_read_close );
for (;;) {
r = archive_read_next_header( a_open.get(), &entry );
if (r == ARCHIVE_EOF)
break;
if (r != ARCHIVE_OK)
break;
vector<FT_Byte> entry_data;
r = archive_read_entry_data( a.get(), &entry_data );
if (r != ARCHIVE_OK)
break;
files.push_back( move( entry_data ) );
}
}
if (files.size() == 0)
files.emplace_back(data, data + size);
return files;
}
static void
setIntermediateAxis( FT_Face face )
@ -85,6 +141,8 @@ using namespace std;
long size = (long)size_;
const vector<vector<FT_Byte>>& files = parse_data( data, size );
FT_Face face;
FT_Int32 load_flags = FT_LOAD_DEFAULT;
#if 0
@ -99,7 +157,7 @@ using namespace std;
// more than a single font.
// get number of faces
if ( FT_New_Memory_Face( library, data, size, -1, &face ) )
if ( FT_New_Memory_Face( library, files[0].data(), files[0].size(), -1, &face ) )
return 0;
long num_faces = face->num_faces;
FT_Done_Face( face );
@ -111,8 +169,8 @@ using namespace std;
{
// get number of instances
if ( FT_New_Memory_Face( library,
data,
size,
files[0].data(),
files[0].size(),
-( face_index + 1 ),
&face ) )
continue;
@ -125,12 +183,23 @@ using namespace std;
instance_index++ )
{
if ( FT_New_Memory_Face( library,
data,
size,
files[0].data(),
files[0].size(),
( instance_index << 16 ) + face_index,
&face ) )
continue;
for ( long files_index = 1;
files_index < files.size();
files_index++)
{
FT_Open_Args open_args = {};
open_args.flags = FT_OPEN_MEMORY;
open_args.memory_base = files[files_index].data();
open_args.memory_size = files[files_index].size();
FT_Attach_Stream( face, &open_args );
}
// loop over all bitmap stroke sizes
// and an arbitrary size for outlines
for ( long fixed_sizes_index = 0;