[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:
parent
d49da66dcb
commit
88ad21fbe5
5 changed files with 110 additions and 34 deletions
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue