[cff] Make cff parser stack dynamic

Allocate and free parser->stack. Allow maxstack to increase the default.

Do validation of maxstack at parse time; make it a CALLBACK.

Defer support for > 256 FDs in cff_font_load().
This commit is contained in:
Dave Arnold 2016-11-16 14:57:52 -08:00
parent d49da66dcb
commit 88ad21fbe5
5 changed files with 110 additions and 34 deletions

View File

@ -562,13 +562,8 @@
*/
/* allocate an operand stack */
if ( font->isCFF2 )
{
/* CFF2 font may increase the operand stack size */
FT_UInt maxstack = cf2_getMaxstack( decoder );
if ( maxstack > stackSize )
stackSize = maxstack;
}
stackSize = font->isCFF2 ? cf2_getMaxstack( decoder ) :
CF2_OPERAND_STACK_SIZE;
opStack = cf2_stack_init( memory, error, stackSize );
if ( !opStack )
{

View File

@ -1740,9 +1740,10 @@ Exit:
CFF_FontRecDict top = &subfont->font_dict;
CFF_Private priv = &subfont->private_dict;
FT_Stream stream = font->stream;
FT_UInt stackSize;
if ( top->private_offset == 0 || top->private_size == 0 )
goto Exit; /* no private DICT, do nothing */
goto Exit2; /* no private DICT, do nothing */
/* store handle needed to access memory, vstore for blend */
subfont->blend.font = font;
@ -1762,12 +1763,17 @@ Exit:
subfont->lenNDV = lenNDV;
subfont->NDV = NDV;
cff_parser_init( &parser,
font->cff2 ? CFF2_CODE_PRIVATE : CFF_CODE_PRIVATE,
priv,
font->library,
top->num_designs,
top->num_axes );
stackSize = font->cff2 ? font->top_font.font_dict.maxstack :
CFF_MAX_STACK_DEPTH + 1;
if ( cff_parser_init( &parser,
font->cff2 ? CFF2_CODE_PRIVATE : CFF_CODE_PRIVATE,
priv,
font->library,
stackSize,
top->num_designs,
top->num_axes ) )
goto Exit;
if ( FT_STREAM_SEEK( font->base_offset + top->private_offset ) ||
FT_FRAME_ENTER( top->private_size ) )
goto Exit;
@ -1784,7 +1790,12 @@ Exit:
priv->num_blue_values &= ~1;
Exit:
cff_blend_clear( subfont );
/* clean up */
cff_blend_clear( subfont ); /* clear blend stack */
cff_parser_done( &parser ); /* free parser stack */
Exit2:
/* no clean up (parser not inited) */
return error;
}
@ -1811,12 +1822,15 @@ Exit:
CFF_Private priv = &subfont->private_dict;
FT_Bool cff2 = (code == CFF2_CODE_TOPDICT ||
code == CFF2_CODE_FONTDICT );
FT_UInt stackSize = cff2 ? CFF2_DEFAULT_STACK : CFF_MAX_STACK_DEPTH;
/* Note: we use default stack size for CFF2 Font DICT because */
/* Top and Font DICTs are not allowed to have blend operators */
cff_parser_init( &parser,
code,
&subfont->font_dict,
library,
stackSize,
0,
0 );
@ -1902,6 +1916,8 @@ Exit:
}
Exit:
cff_parser_done( &parser ); /* free parser stack */
return error;
}
@ -2113,7 +2129,8 @@ Exit:
goto Exit;
/* Font Dicts are not limited to 256 for CFF2 */
if ( !cff2 && fd_index.count > CFF_MAX_CID_FONTS )
/* TODO: support this for CFF2 */
if ( fd_index.count > CFF_MAX_CID_FONTS )
{
FT_TRACE0(( "cff_font_load: FD array too large in CID font\n" ));
goto Fail_CID;
@ -2134,7 +2151,7 @@ Exit:
sub = font->subfonts[idx];
FT_TRACE4(( "parsing subfont %u\n", idx ));
error = cff_subfont_load( sub, &fd_index, idx,
stream, base_offset, library,
stream, base_offset, library,
cff2 ? CFF2_CODE_FONTDICT : CFF_CODE_TOPDICT,
font );
if ( error )

View File

@ -37,22 +37,48 @@
#define FT_COMPONENT trace_cffparse
FT_LOCAL_DEF( void )
FT_LOCAL_DEF( FT_Error )
cff_parser_init( CFF_Parser parser,
FT_UInt code,
void* object,
FT_Library library,
FT_UInt stackSize,
FT_UShort num_designs,
FT_UShort num_axes )
{
FT_Memory memory = library->memory; /* for FT_NEW_ARRAY */
FT_Error error; /* for FT_NEW_ARRAY */
FT_MEM_ZERO( parser, sizeof ( *parser ) );
parser->top = parser->stack;
/*parser->top = parser->stack;*/
parser->object_code = code;
parser->object = object;
parser->library = library;
parser->num_designs = num_designs;
parser->num_axes = num_axes;
/* allocate the stack buffer */
if ( FT_NEW_ARRAY( parser->stack, stackSize ) )
{
FT_FREE( parser->stack );
goto Exit;
}
parser->stackSize = stackSize;
parser->top = parser->stack; /* empty stack */
Exit:
return error;
}
FT_LOCAL_DEF( void )
cff_parser_done( CFF_Parser parser )
{
FT_Memory memory = parser->library->memory; /* for FT_FREE */
FT_FREE( parser->stack );
}
@ -865,6 +891,36 @@
return error;
}
/* maxstack operator increases parser and operand stacks for CFF2 */
static FT_Error
cff_parse_maxstack( CFF_Parser parser )
{
/* maxstack operator can only be used in a Top DICT */
CFF_FontRecDict dict = (CFF_FontRecDict)parser->object;
FT_Byte** data = parser->stack;
FT_Error error = FT_Err_Ok;
if ( !dict )
{
error = FT_ERR( Invalid_File_Format );
goto Exit;
}
dict->maxstack = (FT_UInt)cff_parse_num( parser, data++ );
if ( dict->maxstack > CFF2_MAX_STACK )
dict->maxstack = CFF2_MAX_STACK;
if ( dict->maxstack < CFF2_DEFAULT_STACK )
dict->maxstack = CFF2_DEFAULT_STACK;
FT_TRACE4(( " %d\n", dict->maxstack ));
error = FT_Err_Ok;
Exit:
return error;
}
#define CFF_FIELD_NUM( code, name, id ) \
CFF_FIELD( code, name, id, cff_kind_num )
#define CFF_FIELD_FIXED( code, name, id ) \
@ -1171,7 +1227,7 @@
if ( v >= 27 && v != 31 && v != 255 )
{
/* it's a number; we will push its position on the stack */
if ( parser->top - parser->stack >= CFF_MAX_STACK_DEPTH )
if ( (FT_UInt)( parser->top - parser->stack ) >= parser->stackSize )
goto Stack_Overflow;
*parser->top++ = p;
@ -1262,7 +1318,7 @@
FT_Bool neg;
if ( parser->top - parser->stack >= CFF_MAX_STACK_DEPTH )
if ( parser->top - parser->stack >= parser->stackSize )*/
goto Stack_Overflow;
*parser->top++ = q;

View File

@ -28,7 +28,11 @@
FT_BEGIN_HEADER
#define CFF_MAX_STACK_DEPTH 193
/* CFF uses constant parser stack size */
/* CFF2 can increase from default 193 */
#define CFF_MAX_STACK_DEPTH 96
#define CFF2_MAX_STACK 513
#define CFF2_DEFAULT_STACK 193
#define CFF_CODE_TOPDICT 0x1000
#define CFF_CODE_PRIVATE 0x2000
@ -44,8 +48,9 @@ FT_BEGIN_HEADER
FT_Byte* limit;
FT_Byte* cursor;
FT_Byte* stack[CFF_MAX_STACK_DEPTH + 1];
FT_Byte** stack;
FT_Byte** top;
FT_UInt stackSize; /* allocated size */
FT_UInt object_code;
void* object;
@ -56,14 +61,18 @@ FT_BEGIN_HEADER
} CFF_ParserRec, *CFF_Parser;
FT_LOCAL( void )
FT_LOCAL( FT_Error )
cff_parser_init( CFF_Parser parser,
FT_UInt code,
void* object,
FT_Library library,
FT_UInt stackSize,
FT_UShort num_designs,
FT_UShort num_axes );
FT_LOCAL( void )
cff_parser_done( CFF_Parser parser );
FT_LOCAL( FT_Error )
cff_parser_run( CFF_Parser parser,
FT_Byte* start,

View File

@ -107,12 +107,12 @@
#undef CFFCODE
#define CFFCODE CFF2_CODE_TOPDICT
CFF_FIELD_CALLBACK( 0x107, font_matrix, "FontMatrix" )
CFF_FIELD_NUM ( 17, charstrings_offset, "CharStrings" )
CFF_FIELD_NUM ( 0x124, cid_fd_array_offset, "FDArray" )
CFF_FIELD_NUM ( 0x125, cid_fd_select_offset, "FDSelect" )
CFF_FIELD_NUM ( 24, vstore_offset, "vstore" )
CFF_FIELD_NUM ( 25, maxstack, "maxstack" )
CFF_FIELD_CALLBACK( 0x107, font_matrix, "FontMatrix" )
CFF_FIELD_NUM ( 17, charstrings_offset, "CharStrings" )
CFF_FIELD_NUM ( 0x124, cid_fd_array_offset, "FDArray" )
CFF_FIELD_NUM ( 0x125, cid_fd_select_offset, "FDSelect" )
CFF_FIELD_NUM ( 24, vstore_offset, "vstore" )
CFF_FIELD_CALLBACK( 25, maxstack, "maxstack" )
#undef FT_STRUCTURE
#define FT_STRUCTURE CFF_FontRecDictRec
@ -120,9 +120,8 @@
#undef CFFCODE
#define CFFCODE CFF2_CODE_FONTDICT
CFF_FIELD_CALLBACK( 18, private_dict, "Private" )
CFF_FIELD_CALLBACK( 0x107, font_matrix, "FontMatrix" )
CFF_FIELD_STRING ( 0x126, cid_font_name, "FontName" )
CFF_FIELD_CALLBACK( 18, private_dict, "Private" )
CFF_FIELD_CALLBACK( 0x107, font_matrix, "FontMatrix" )
#undef FT_STRUCTURE
#define FT_STRUCTURE CFF_PrivateRec