forked from minhngoc25a/freetype2
[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:
parent
649ca5562d
commit
e6593389cf
|
@ -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).
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue