* src/otlayout/otlgpos.c (otl_gpos_lookup1_validate,

otl_gpos_lookup2_validate, otl_gpos_lookup3_validate,
otl_gpos_lookup4_validate, otl_gpos_lookup5_validate,
otl_gpos_lookup6_validate, otl_gpos_lookup9_validate,
otl_gpos_validate): Update
function arguments.
(otl_gpos_lookup7_validate, otl_gpos_lookup8_validate): Update
function arguments.
Handle NULL offsets correctly.
Check sequence and lookup indices for format 3.
(otl_pos_rule_validate, otl_chain_pos_rule_validate): Add argument
to pass lookup count.
Check sequence and glyph indices.
(otl_gpos_subtable_validate): Update function arguments.
Update callers.

* src/otlayout/otlgpos.h: Updated.

* src/otlayout/otlgsub.c (otl_gsub_lookup1_validate,
otl_gsub_lookup3_validate, otl_gsub_lookup8_validate): Update
function arguments.
Add glyph index checks.
(otl_sequence_validate, otl_alternate_set_validate,
otl_ligature_validate): Add argument to pass glyph count.
Update callers.
Add glyph index check.
(otl_gsub_lookup2_validate, otl_gsub_lookup4_validate): Update
function arguments.
(otl_ligature_set_validate): Add argument to pass glyph count.
Update caller.
(otl_sub_class_rule_validate,
otl_sub_class_rule_set_validate): Removed.
(otl_sub_rule_validate, otl_chain_sub_rule_validate): Add argument
to pass lookup count.
Update callers.
Add lookup index check.
(otl_sub_rule_set_validate, otl_chain_sub_rule_set_validate): Add
argument to pass lookup count.
Update callers.
(otl_gsub_lookup5_validate): Update function arguments.
Handle NULL offsets correctly.
Don't call otl_sub_class_rule_set_validate but
otl_sub_rule_set_validate.
Check sequence and lookup indices for format 3.
(otl_gsub_lookup6_validate): Update function arguments.
Handle NULL offsets correctly.
Check sequence and lookup indices for format 3.
(otl_gsub_lookup7_validate, otl_gsub_validate): Update function
arguments.

* src/otlayout/otlgsub.h: Updated.

* src/otlayout/otlbase.c (otl_base_validate): Handle NULL offsets
correctly.

* src/otlayout/otlcommn.c (otl_class_definition_validate): Fix
compiler warning.
(otl_coverage_get_first, otl_coverage_get_last): New functions.
(otl_lookup_validate): Add arguments to pass lookup and glyph
counts.
Update callers.
(otl_lookup_list_validate): Add argument to pass glyph count.
Update callers.

* src/otlayout/otlcommn.h: Updated.

* src/otlayout/otljstf.c (otl_jstf_extender_validate,
otl_jstf_max_validate, otl_jstf_script_validate,
otl_jstf_priority_validate, otl_jstf_lang_validate): Add parameter
to validate glyph indices.
Update callers.
(otl_jstf_validate): Add parameter which specifies number of glyphs
in font.

* src/otlayout/otljstf.h: Updated.
This commit is contained in:
Werner Lemberg 2004-08-17 23:02:06 +00:00
parent 961d9819bd
commit d91be9e66d
11 changed files with 486 additions and 155 deletions

View File

@ -1,3 +1,81 @@
2004-08-16 Werner Lemberg <wl@gnu.org>
* src/otlayout/otlgpos.c (otl_gpos_lookup1_validate,
otl_gpos_lookup2_validate, otl_gpos_lookup3_validate,
otl_gpos_lookup4_validate, otl_gpos_lookup5_validate,
otl_gpos_lookup6_validate, otl_gpos_lookup9_validate,
otl_gpos_validate): Update
function arguments.
(otl_gpos_lookup7_validate, otl_gpos_lookup8_validate): Update
function arguments.
Handle NULL offsets correctly.
Check sequence and lookup indices for format 3.
(otl_pos_rule_validate, otl_chain_pos_rule_validate): Add argument
to pass lookup count.
Check sequence and glyph indices.
(otl_gpos_subtable_validate): Update function arguments.
Update callers.
* src/otlayout/otlgpos.h: Updated.
* src/otlayout/otlgsub.c (otl_gsub_lookup1_validate,
otl_gsub_lookup3_validate, otl_gsub_lookup8_validate): Update
function arguments.
Add glyph index checks.
(otl_sequence_validate, otl_alternate_set_validate,
otl_ligature_validate): Add argument to pass glyph count.
Update callers.
Add glyph index check.
(otl_gsub_lookup2_validate, otl_gsub_lookup4_validate): Update
function arguments.
(otl_ligature_set_validate): Add argument to pass glyph count.
Update caller.
(otl_sub_class_rule_validate,
otl_sub_class_rule_set_validate): Removed.
(otl_sub_rule_validate, otl_chain_sub_rule_validate): Add argument
to pass lookup count.
Update callers.
Add lookup index check.
(otl_sub_rule_set_validate, otl_chain_sub_rule_set_validate): Add
argument to pass lookup count.
Update callers.
(otl_gsub_lookup5_validate): Update function arguments.
Handle NULL offsets correctly.
Don't call otl_sub_class_rule_set_validate but
otl_sub_rule_set_validate.
Check sequence and lookup indices for format 3.
(otl_gsub_lookup6_validate): Update function arguments.
Handle NULL offsets correctly.
Check sequence and lookup indices for format 3.
(otl_gsub_lookup7_validate, otl_gsub_validate): Update function
arguments.
* src/otlayout/otlgsub.h: Updated.
* src/otlayout/otlbase.c (otl_base_validate): Handle NULL offsets
correctly.
* src/otlayout/otlcommn.c (otl_class_definition_validate): Fix
compiler warning.
(otl_coverage_get_first, otl_coverage_get_last): New functions.
(otl_lookup_validate): Add arguments to pass lookup and glyph
counts.
Update callers.
(otl_lookup_list_validate): Add argument to pass glyph count.
Update callers.
* src/otlayout/otlcommn.h: Updated.
* src/otlayout/otljstf.c (otl_jstf_extender_validate,
otl_jstf_max_validate, otl_jstf_script_validate,
otl_jstf_priority_validate, otl_jstf_lang_validate): Add parameter
to validate glyph indices.
Update callers.
(otl_jstf_validate): Add parameter which specifies number of glyphs
in font.
* src/otlayout/otljstf.h: Updated.
2004-08-15 Werner Lemberg <wl@gnu.org>
* src/otlayout/otlgpos.c (otl_liga_mark2_validate): Add parameter

View File

@ -189,6 +189,8 @@ OTL_BEGIN_HEADER
} OTL_ValidatorRec;
typedef void (*OTL_ValidateFunc)( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid );
OTL_API( void )

View File

@ -208,6 +208,7 @@
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt val;
OTL_CHECK( 6 );
@ -215,8 +216,15 @@
if ( OTL_NEXT_ULONG( p ) != 0x10000UL )
OTL_INVALID_DATA;
otl_axis_table_validate( table + OTL_NEXT_USHORT( p ), valid );
otl_axis_table_validate( table + OTL_NEXT_USHORT( p ), valid );
/* validate horizontal axis table */
val = OTL_NEXT_USHORT( p );
if ( val )
otl_axis_table_validate( table + val, valid );
/* validate vertical axis table */
val = OTL_NEXT_USHORT( p );
if ( val )
otl_axis_table_validate( table + val, valid );
}

View File

@ -86,6 +86,47 @@
}
OTL_LOCALDEF( OTL_UInt )
otl_coverage_get_first( OTL_Bytes table )
{
OTL_Bytes p = table;
p += 4; /* skip format and count */
return OTL_NEXT_USHORT( p );
}
OTL_LOCALDEF( OTL_UInt )
otl_coverage_get_last( OTL_Bytes table )
{
OTL_Bytes p = table;
OTL_UInt format = OTL_NEXT_USHORT( p );
OTL_UInt count = OTL_NEXT_USHORT( p );
OTL_UInt result;
switch ( format )
{
case 1:
p += ( count - 1 ) * 2;
result = OTL_NEXT_USHORT( p );
break;
case 2:
p += ( count - 1 ) * 6 + 2;
result = OTL_NEXT_USHORT( p );
break;
default:
;
}
return result;
}
OTL_LOCALDEF( OTL_UInt )
otl_coverage_get_count( OTL_Bytes table )
{
@ -215,14 +256,15 @@
{
case 1:
{
OTL_UInt num_glyphs, start = OTL_NEXT_USHORT( p );
OTL_UInt num_glyphs;
p += 2; /* skip start_glyph */
OTL_CHECK( 2 );
num_glyphs = OTL_NEXT_USHORT( p );
OTL_CHECK( num_glyphs * 2 );
}
break;
@ -442,6 +484,8 @@
otl_lookup_validate( OTL_Bytes table,
OTL_UInt type_count,
OTL_ValidateFunc* type_funcs,
OTL_UInt lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
@ -463,7 +507,8 @@
/* scan subtables */
for ( ; num_subtables > 0; num_subtables-- )
validate( table + OTL_NEXT_USHORT( p ), valid );
validate( table + OTL_NEXT_USHORT( p ), lookup_count, glyph_count,
valid );
}
@ -511,10 +556,11 @@
otl_lookup_list_validate( OTL_Bytes table,
OTL_UInt type_count,
OTL_ValidateFunc* type_funcs,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt num_lookups;
OTL_UInt num_lookups, count;
OTL_CHECK( 2 );
@ -522,9 +568,10 @@
OTL_CHECK( 2 * num_lookups );
/* scan lookup records */
for ( ; num_lookups > 0; num_lookups-- )
for ( count = num_lookups; count > 0; count-- )
otl_lookup_validate( table + OTL_NEXT_USHORT( p ),
type_count, type_funcs, valid );
type_count, type_funcs,
num_lookups, glyph_count, valid );
}

View File

@ -37,6 +37,14 @@ OTL_BEGIN_HEADER
otl_coverage_validate( OTL_Bytes table,
OTL_Validator valid );
/* return first covered glyph */
OTL_LOCAL( OTL_UInt )
otl_coverage_get_first( OTL_Bytes table );
/* return last covered glyph */
OTL_LOCAL( OTL_UInt )
otl_coverage_get_last( OTL_Bytes table );
/* return number of covered glyphs */
OTL_LOCAL( OTL_UInt )
otl_coverage_get_count( OTL_Bytes table );
@ -116,6 +124,8 @@ OTL_BEGIN_HEADER
otl_lookup_validate( OTL_Bytes table,
OTL_UInt type_count,
OTL_ValidateFunc* type_funcs,
OTL_UInt lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid );
/* return number of sub-tables in a lookup */
@ -143,6 +153,7 @@ OTL_BEGIN_HEADER
otl_lookup_list_validate( OTL_Bytes table,
OTL_UInt type_count,
OTL_ValidateFunc* type_funcs,
OTL_UInt glyph_count,
OTL_Validator valid );
#if 0

View File

@ -173,11 +173,16 @@
static void
otl_gpos_lookup1_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt format;
OTL_UNUSED( lookup_count );
OTL_UNUSED( glyph_count );
OTL_CHECK( 2 );
format = OTL_NEXT_USHORT( p );
@ -270,11 +275,16 @@
static void
otl_gpos_lookup2_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt format;
OTL_UNUSED( lookup_count );
OTL_UNUSED( glyph_count );
OTL_CHECK( 2 );
format = OTL_NEXT_USHORT( p );
@ -354,11 +364,16 @@
static void
otl_gpos_lookup3_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt format;
OTL_UNUSED( lookup_count );
OTL_UNUSED( glyph_count );
OTL_CHECK( 2 );
format = OTL_NEXT_USHORT( p );
@ -430,11 +445,16 @@
static void
otl_gpos_lookup4_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt format;
OTL_UNUSED( lookup_count );
OTL_UNUSED( glyph_count );
OTL_CHECK( 2 );
format = OTL_NEXT_USHORT( p );
@ -466,6 +486,7 @@
}
}
/*************************************************************************/
/*************************************************************************/
/***** *****/
@ -529,11 +550,16 @@
static void
otl_gpos_lookup5_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt format;
OTL_UNUSED( lookup_count );
OTL_UNUSED( glyph_count );
OTL_CHECK( 2 );
format = OTL_NEXT_USHORT( p );
@ -576,11 +602,16 @@
static void
otl_gpos_lookup6_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt format;
OTL_UNUSED( lookup_count );
OTL_UNUSED( glyph_count );
OTL_CHECK( 2 );
format = OTL_NEXT_USHORT( p );
@ -623,6 +654,7 @@
/* used for both format 1 and 2 */
static void
otl_pos_rule_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
@ -638,7 +670,14 @@
OTL_CHECK( ( num_glyphs - 1 ) * 2 + num_pos * 4 );
/* XXX: check pos lookups */
for ( ; num_pos > 0; num_pos-- )
{
if ( OTL_NEXT_USHORT( p ) >= num_glyphs )
OTL_INVALID_DATA;
if ( OTL_NEXT_USHORT( p ) >= lookup_count )
OTL_INVALID_DATA;
}
/* no need to check glyph indices/classes used as input for this */
/* context rule since even invalid glyph indices/classes return a */
@ -649,6 +688,7 @@
/* used for both format 1 and 2 */
static void
otl_pos_rule_set_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
@ -662,17 +702,22 @@
/* scan posrule records */
for ( ; num_posrules > 0; num_posrules-- )
otl_pos_rule_validate( table + OTL_NEXT_USHORT( p ), valid );
otl_pos_rule_validate( table + OTL_NEXT_USHORT( p ), lookup_count,
valid );
}
static void
otl_gpos_lookup7_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt format;
OTL_UNUSED( glyph_count );
OTL_CHECK( 2 );
format = OTL_NEXT_USHORT( p );
@ -693,7 +738,8 @@
/* scan posrule set records */
for ( ; num_posrule_sets > 0; num_posrule_sets-- )
otl_pos_rule_set_validate( table + OTL_NEXT_USHORT( p ), valid );
otl_pos_rule_set_validate( table + OTL_NEXT_USHORT( p ),
lookup_count, valid );
}
break;
@ -714,13 +760,19 @@
/* scan pos class set rules */
for ( ; num_posclass_sets > 0; num_posclass_sets-- )
otl_pos_rule_set_validate( table + OTL_NEXT_USHORT( p ), valid );
{
OTL_UInt offset = OTL_NEXT_USHORT( p );
if ( offset )
otl_pos_rule_set_validate( table + offset, lookup_count, valid );
}
}
break;
case 3:
{
OTL_UInt num_glyphs, num_pos;
OTL_UInt num_glyphs, num_pos, count;
OTL_CHECK( 4 );
@ -729,10 +781,17 @@
OTL_CHECK( num_glyphs * 2 + num_pos * 4 );
for ( ; num_glyphs > 0; num_glyphs-- )
for ( count = num_glyphs; count > 0; count-- )
otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid );
/* XXX: check pos lookups */
for ( ; num_pos > 0; num_pos-- )
{
if ( OTL_NEXT_USHORT( p ) >= num_glyphs )
OTL_INVALID_DATA;
if ( OTL_NEXT_USHORT( p ) >= lookup_count )
OTL_INVALID_DATA;
}
}
break;
@ -753,6 +812,7 @@
/* used for both format 1 and 2 */
static void
otl_chain_pos_rule_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
@ -780,37 +840,54 @@
num_pos = OTL_NEXT_USHORT( p );
OTL_CHECK( num_pos * 4 );
/* XXX: check pos lookups */
for ( ; num_pos > 0; num_pos-- )
{
if ( OTL_NEXT_USHORT( p ) >= num_input_glyphs )
OTL_INVALID_DATA;
if ( OTL_NEXT_USHORT( p ) >= lookup_count )
OTL_INVALID_DATA;
}
/* no need to check glyph indices/classes used as input for this */
/* context rule since even invalid glyph indices/classes return a */
/* meaningful result */
}
/* used for both format 1 and 2 */
static void
otl_chain_pos_rule_set_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt count;
OTL_UInt num_chain_subrules;
OTL_CHECK( 2 );
count = OTL_NEXT_USHORT( p );
num_chain_subrules = OTL_NEXT_USHORT( p );
OTL_CHECK( 2 * count );
OTL_CHECK( num_chain_subrules * 2 );
/* scan chain pos rule records */
for ( ; count > 0; count-- )
otl_chain_pos_rule_validate( table + OTL_NEXT_USHORT( p ), valid );
for ( ; num_chain_subrules > 0; num_chain_subrules-- )
otl_chain_pos_rule_validate( table + OTL_NEXT_USHORT( p ),
lookup_count, valid );
}
static void
otl_gpos_lookup8_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt format;
OTL_UNUSED( glyph_count );
OTL_CHECK( 2 );
format = OTL_NEXT_USHORT( p );
@ -832,7 +909,7 @@
/* scan chain pos ruleset records */
for ( ; num_chain_pos_rulesets > 0; num_chain_pos_rulesets-- )
otl_chain_pos_rule_set_validate( table + OTL_NEXT_USHORT( p ),
valid );
lookup_count, valid );
}
break;
@ -859,33 +936,39 @@
/* scan chainpos class set records */
for ( ; num_chainpos_class_sets > 0; num_chainpos_class_sets-- )
otl_chain_pos_rule_set_validate( table + OTL_NEXT_USHORT( p ),
valid );
{
OTL_UInt offset = OTL_NEXT_USHORT( p );
if ( offset )
otl_chain_pos_rule_set_validate( table + offset, lookup_count,
valid );
}
}
break;
case 3:
{
OTL_UInt num_backtrack_glyphs, num_input_glyphs;
OTL_UInt num_lookahead_glyphs, num_pos;
OTL_UInt num_lookahead_glyphs, num_pos, count;
OTL_CHECK( 2 );
num_backtrack_glyphs = OTL_NEXT_USHORT( p );
OTL_CHECK( 2 * num_backtrack_glyphs + 2 );
num_backtrack_glyphs = OTL_NEXT_USHORT( p );
OTL_CHECK( num_backtrack_glyphs * 2 + 2 );
for ( ; num_backtrack_glyphs > 0; num_backtrack_glyphs-- )
otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid );
num_input_glyphs = OTL_NEXT_USHORT( p );
OTL_CHECK( 2 * num_input_glyphs + 2 );
OTL_CHECK( num_input_glyphs * 2 + 2 );
for ( ; num_input_glyphs > 0; num_input_glyphs-- )
for ( count = num_input_glyphs; count > 0; count-- )
otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid );
num_lookahead_glyphs = OTL_NEXT_USHORT( p );
OTL_CHECK( 2 * num_lookahead_glyphs + 2 );
OTL_CHECK( num_lookahead_glyphs * 2 + 2 );
for ( ; num_lookahead_glyphs > 0; num_lookahead_glyphs-- )
otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid );
@ -893,7 +976,14 @@
num_pos = OTL_NEXT_USHORT( p );
OTL_CHECK( num_pos * 4 );
/* XXX: check pos lookups */
for ( ; num_pos > 0; num_pos-- )
{
if ( OTL_NEXT_USHORT( p ) >= num_input_glyphs )
OTL_INVALID_DATA;
if ( OTL_NEXT_USHORT( p ) >= lookup_count )
OTL_INVALID_DATA;
}
}
break;
@ -913,6 +1003,8 @@
static void
otl_gpos_lookup9_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
@ -937,7 +1029,7 @@
OTL_INVALID_DATA;
validate = otl_gpos_validate_funcs[lookup_type - 1];
validate( table + lookup_offset, valid );
validate( table + lookup_offset, lookup_count, glyph_count, valid );
}
break;
@ -963,9 +1055,11 @@
OTL_LOCALDEF( void )
otl_gpos_subtable_validate( OTL_Bytes table,
OTL_UInt glyph_count,
OTL_Validator valid )
{
otl_lookup_list_validate( table, 9, otl_gpos_validate_funcs, valid );
otl_lookup_list_validate( table, 9, otl_gpos_validate_funcs,
glyph_count, valid );
}
@ -979,6 +1073,7 @@
OTL_LOCALDEF( void )
otl_gpos_validate( OTL_Bytes table,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
@ -994,7 +1089,7 @@
features = OTL_NEXT_USHORT( p );
lookups = OTL_NEXT_USHORT( p );
otl_gpos_subtable_validate( table + lookups, valid );
otl_gpos_subtable_validate( table + lookups, glyph_count, valid );
otl_feature_list_validate( table + features, table + lookups, valid );
otl_script_list_validate( table + scripts, table + features, valid );
}

View File

@ -26,10 +26,12 @@ OTL_BEGIN_HEADER
OTL_LOCAL( void )
otl_gpos_subtable_validate( OTL_Bytes table,
OTL_UInt glyph_count,
OTL_Validator valid );
OTL_LOCAL( void )
otl_gpos_validate( OTL_Bytes table,
OTL_UInt glyph_count,
OTL_Validator valid );

View File

@ -57,11 +57,15 @@
static void
otl_gsub_lookup1_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt format;
OTL_UNUSED( lookup_count );
OTL_CHECK( 2 );
format = OTL_NEXT_USHORT( p );
@ -69,12 +73,26 @@
switch ( format )
{
case 1:
OTL_CHECK( 4 );
{
OTL_Bytes coverage;
OTL_Int delta;
OTL_Long idx;
otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid );
/* skip delta glyph ID */
OTL_CHECK( 4 );
coverage = table + OTL_NEXT_USHORT( p );
delta = OTL_NEXT_SHORT( p );
otl_coverage_validate( coverage, valid );
idx = otl_coverage_get_first( coverage ) + delta;
if ( idx < 0 )
OTL_INVALID_DATA;
idx = otl_coverage_get_last( coverage ) + delta;
if ( (OTL_UInt)idx >= glyph_count )
OTL_INVALID_DATA;
}
break;
case 2:
@ -88,11 +106,11 @@
otl_coverage_validate( table + coverage, valid );
OTL_CHECK( 2 * num_glyphs );
OTL_CHECK( num_glyphs * 2 );
/* We don't check that there are at most `num_glyphs' */
/* elements in the coverage table. This is delayed */
/* to the lookup function. */
for ( ; num_glyphs > 0; num_glyphs-- )
if ( OTL_NEXT_USHORT( p ) >= glyph_count )
OTL_INVALID_DATA;
}
break;
@ -198,6 +216,7 @@
static void
otl_sequence_validate( OTL_Bytes table,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
@ -207,22 +226,28 @@
OTL_CHECK( 2 );
num_glyphs = OTL_NEXT_USHORT( p );
/* XXX: according to the spec, `num_glyphs' should be > 0; */
/* we can deal with these cases pretty well, however */
/* according to the specification, `num_glyphs' should be > 0; */
/* we can deal with these cases pretty well, however */
OTL_CHECK( 2 * num_glyphs );
OTL_CHECK( num_glyphs * 2 );
/* XXX: check glyph indices */
for ( ; num_glyphs > 0; num_glyphs-- )
if ( OTL_NEXT_USHORT( p ) >= glyph_count )
OTL_INVALID_DATA;
}
static void
otl_gsub_lookup2_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt format;
OTL_UNUSED( lookup_count );
OTL_CHECK( 2 );
format = OTL_NEXT_USHORT( p );
@ -243,7 +268,8 @@
/* scan sequence records */
for ( ; num_sequences > 0; num_sequences-- )
otl_sequence_validate( table + OTL_NEXT_USHORT( p ), valid );
otl_sequence_validate( table + OTL_NEXT_USHORT( p ), glyph_count,
valid );
}
break;
@ -329,28 +355,35 @@
static void
otl_alternate_set_validate( OTL_Bytes table,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt count;
OTL_UInt num_glyphs;
OTL_CHECK( 2 );
count = OTL_NEXT_USHORT( p );
num_glyphs = OTL_NEXT_USHORT( p );
OTL_CHECK( 2 * count );
OTL_CHECK( num_glyphs * 2 );
/* XXX: check glyph indices */
for ( ; num_glyphs > 0; num_glyphs-- )
if ( OTL_NEXT_USHORT( p ) >= glyph_count )
OTL_INVALID_DATA;
}
static void
otl_gsub_lookup3_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt format;
OTL_UNUSED( lookup_count );
OTL_CHECK( 2 );
format = OTL_NEXT_USHORT( p );
@ -367,11 +400,12 @@
otl_coverage_validate( table + coverage, valid );
OTL_CHECK( 2 * num_alternate_sets );
OTL_CHECK( num_alternate_sets * 2 );
/* scan alternate set records */
for ( ; num_alternate_sets > 0; num_alternate_sets-- )
otl_alternate_set_validate( table + OTL_NEXT_USHORT( p ), valid );
otl_alternate_set_validate( table + OTL_NEXT_USHORT( p ),
glyph_count, valid );
}
break;
@ -442,6 +476,7 @@
static void
otl_ligature_validate( OTL_Bytes table,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
@ -455,14 +490,19 @@
if ( num_components == 0 )
OTL_INVALID_DATA;
OTL_CHECK( 2 * ( num_components - 1 ) );
num_components--;
/* XXX: check glyph indices */
OTL_CHECK( num_components * 2 );
for ( ; num_components > 0; num_components-- )
if ( OTL_NEXT_USHORT( p ) >= glyph_count )
OTL_INVALID_DATA;
}
static void
otl_ligature_set_validate( OTL_Bytes table,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
@ -472,21 +512,26 @@
OTL_CHECK( 2 );
num_ligatures = OTL_NEXT_USHORT( p );
OTL_CHECK( 2 * num_ligatures );
OTL_CHECK( num_ligatures * 2 );
/* scan ligature records */
for ( ; num_ligatures > 0; num_ligatures-- )
otl_ligature_validate( table + OTL_NEXT_USHORT( p ), valid );
otl_ligature_validate( table + OTL_NEXT_USHORT( p ), glyph_count,
valid );
}
static void
otl_gsub_lookup4_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt format;
OTL_UNUSED( lookup_count);
OTL_CHECK( 2 );
format = OTL_NEXT_USHORT( p );
@ -503,11 +548,12 @@
otl_coverage_validate( table + coverage, valid );
OTL_CHECK( 2 * num_ligsets );
OTL_CHECK( num_ligsets * 2 );
/* scan ligature set records */
for ( ; num_ligsets > 0; num_ligsets-- )
otl_ligature_set_validate( table + OTL_NEXT_USHORT( p ), valid );
otl_ligature_set_validate( table + OTL_NEXT_USHORT( p ),
glyph_count, valid );
}
break;
@ -525,8 +571,10 @@
/*************************************************************************/
/*************************************************************************/
/* used for both format 1 and 2 */
static void
otl_sub_rule_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
@ -542,12 +590,25 @@
OTL_CHECK( ( num_glyphs - 1 ) * 2 + num_subst * 4 );
/* XXX: check glyph indices and subst lookups */
for ( ; num_subst > 0; num_subst-- )
{
if ( OTL_NEXT_USHORT( p ) >= num_glyphs )
OTL_INVALID_DATA;
if ( OTL_NEXT_USHORT( p ) >= lookup_count )
OTL_INVALID_DATA;
}
/* no need to check glyph indices/classes used as input for this */
/* context rule since even invalid glyph indices/classes return a */
/* meaningful result */
}
/* used for both format 1 and 2 */
static void
otl_sub_rule_set_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
@ -557,64 +618,26 @@
OTL_CHECK( 2 );
num_subrules = OTL_NEXT_USHORT( p );
OTL_CHECK( 2 * num_subrules );
/* scan sub rule records */
for ( ; num_subrules > 0; num_subrules-- )
otl_sub_rule_validate( table + OTL_NEXT_USHORT( p ), valid );
}
static void
otl_sub_class_rule_validate( OTL_Bytes table,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt num_glyphs, num_subst;
OTL_CHECK( 4 );
num_glyphs = OTL_NEXT_USHORT( p );
num_subst = OTL_NEXT_USHORT( p );
if ( num_glyphs == 0 )
OTL_INVALID_DATA;
OTL_CHECK( ( num_glyphs - 1 ) * 2 + num_subst * 4 );
/* XXX: check subst lookups */
/* no need to check glyph indices used as input for this context */
/* rule since even invalid glyph indices return a meaningful result */
}
static void
otl_sub_class_rule_set_validate( OTL_Bytes table,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt num_subrules;
OTL_CHECK( 2 );
num_subrules = OTL_NEXT_USHORT( p );
OTL_CHECK( 2 * num_subrules );
OTL_CHECK( num_subrules * 2 );
/* scan subrule records */
for ( ; num_subrules > 0; num_subrules-- )
otl_sub_class_rule_validate( table + OTL_NEXT_USHORT( p ), valid );
otl_sub_rule_validate( table + OTL_NEXT_USHORT( p ), lookup_count,
valid );
}
static void
otl_gsub_lookup5_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt format;
OTL_UNUSED( glyph_count );
OTL_CHECK( 2 );
format = OTL_NEXT_USHORT( p );
@ -631,11 +654,12 @@
otl_coverage_validate( table + coverage, valid );
OTL_CHECK( 2 * num_subrulesets );
OTL_CHECK( num_subrulesets * 2 );
/* scan subrule set records */
for ( ; num_subrulesets > 0; num_subrulesets-- )
otl_sub_rule_set_validate( table + OTL_NEXT_USHORT( p ), valid );
otl_sub_rule_set_validate( table + OTL_NEXT_USHORT( p ),
lookup_count, valid );
}
break;
@ -652,30 +676,42 @@
otl_coverage_validate( table + coverage, valid );
otl_class_definition_validate( table + class_def, valid );
OTL_CHECK( 2 * num_subclass_sets );
OTL_CHECK( num_subclass_sets * 2 );
/* scan subclass set records */
for ( ; num_subclass_sets > 0; num_subclass_sets-- )
otl_sub_class_rule_set_validate( table + OTL_NEXT_USHORT( p ),
valid );
{
OTL_UInt offset = OTL_NEXT_USHORT( p );
if ( offset )
otl_sub_rule_set_validate( table + offset, lookup_count, valid );
}
}
break;
case 3:
{
OTL_UInt num_glyphs, num_subst;
OTL_UInt num_glyphs, num_subst, count;
OTL_CHECK( 4 );
num_glyphs = OTL_NEXT_USHORT( p );
num_subst = OTL_NEXT_USHORT( p );
OTL_CHECK( 2 * num_glyphs + 4 * num_subst );
OTL_CHECK( num_glyphs * 2 + num_subst * 4 );
for ( ; num_glyphs > 0; num_glyphs-- )
for ( count = num_glyphs; count > 0; count-- )
otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid );
/* XXX: check subst lookups */
for ( ; num_subst > 0; num_subst-- )
{
if ( OTL_NEXT_USHORT( p ) >= num_glyphs )
OTL_INVALID_DATA;
if ( OTL_NEXT_USHORT( p ) >= lookup_count )
OTL_INVALID_DATA;
}
}
break;
@ -696,6 +732,7 @@
/* used for both format 1 and 2 */
static void
otl_chain_sub_rule_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
@ -706,33 +743,42 @@
OTL_CHECK( 2 );
num_backtrack_glyphs = OTL_NEXT_USHORT( p );
OTL_CHECK( 2 * num_backtrack_glyphs + 2 );
p += 2 * num_backtrack_glyphs;
OTL_CHECK( num_backtrack_glyphs * 2 + 2 );
p += num_backtrack_glyphs * 2;
num_input_glyphs = OTL_NEXT_USHORT( p );
if ( num_input_glyphs == 0 )
OTL_INVALID_DATA;
OTL_CHECK( 2 * num_input_glyphs );
p += 2 * ( num_input_glyphs - 1 );
OTL_CHECK( num_input_glyphs * 2 );
p += ( num_input_glyphs - 1 ) * 2;
num_lookahead_glyphs = OTL_NEXT_USHORT( p );
OTL_CHECK( 2 * num_lookahead_glyphs + 2 );
p += 2 * num_lookahead_glyphs;
OTL_CHECK( num_lookahead_glyphs * 2 + 2 );
p += num_lookahead_glyphs * 2;
num_subst = OTL_NEXT_USHORT( p );
OTL_CHECK( 4 * num_subst );
OTL_CHECK( num_subst * 4 );
/* XXX: check subst lookups */
for ( ; num_subst > 0; num_subst-- )
{
if ( OTL_NEXT_USHORT( p ) >= num_input_glyphs )
OTL_INVALID_DATA;
/* no need to check glyph indices used as input for this context */
/* rule since even invalid glyph indices return a meaningful result */
if ( OTL_NEXT_USHORT( p ) >= lookup_count )
OTL_INVALID_DATA;
}
/* no need to check glyph indices/classes used as input for this */
/* context rule since even invalid glyph indices/classes return a */
/* meaningful result */
}
/* used for both format 1 and 2 */
static void
otl_chain_sub_rule_set_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
@ -742,21 +788,26 @@
OTL_CHECK( 2 );
num_chain_subrules = OTL_NEXT_USHORT( p );
OTL_CHECK( 2 * num_chain_subrules );
OTL_CHECK( num_chain_subrules * 2 );
/* scan chain subrule records */
/* scan chain subst rule records */
for ( ; num_chain_subrules > 0; num_chain_subrules-- )
otl_chain_sub_rule_validate( table + OTL_NEXT_USHORT( p ), valid );
otl_chain_sub_rule_validate( table + OTL_NEXT_USHORT( p ),
lookup_count, valid );
}
static void
otl_gsub_lookup6_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
OTL_UInt format;
OTL_UNUSED( glyph_count );
OTL_CHECK( 2 );
format = OTL_NEXT_USHORT( p );
@ -773,12 +824,12 @@
otl_coverage_validate( table + coverage, valid );
OTL_CHECK( 2 * num_chain_subrulesets );
OTL_CHECK( num_chain_subrulesets * 2 );
/* scan chain subrule set records */
for ( ; num_chain_subrulesets > 0; num_chain_subrulesets-- )
otl_chain_sub_rule_set_validate( table + OTL_NEXT_USHORT( p ),
valid );
lookup_count, valid );
}
break;
@ -801,37 +852,43 @@
otl_class_definition_validate( table + input_class, valid );
otl_class_definition_validate( table + ahead_class, valid );
OTL_CHECK( 2 * num_chain_subclass_sets );
OTL_CHECK( num_chain_subclass_sets * 2 );
/* scan chain subclass set records */
for ( ; num_chain_subclass_sets > 0; num_chain_subclass_sets-- )
otl_chain_sub_rule_set_validate( table + OTL_NEXT_USHORT( p ),
valid );
{
OTL_UInt offset = OTL_NEXT_USHORT( p );
if ( offset )
otl_chain_sub_rule_set_validate( table + offset, lookup_count,
valid );
}
}
break;
case 3:
{
OTL_UInt num_backtrack_glyphs, num_input_glyphs;
OTL_UInt num_lookahead_glyphs, num_subst;
OTL_UInt num_lookahead_glyphs, num_subst, count;
OTL_CHECK( 2 );
num_backtrack_glyphs = OTL_NEXT_USHORT( p );
OTL_CHECK( 2 * num_backtrack_glyphs + 2 );
OTL_CHECK( num_backtrack_glyphs * 2 + 2 );
for ( ; num_backtrack_glyphs > 0; num_backtrack_glyphs-- )
otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid );
num_input_glyphs = OTL_NEXT_USHORT( p );
OTL_CHECK( 2 * num_input_glyphs + 2 );
OTL_CHECK( num_input_glyphs * 2 + 2 );
for ( ; num_input_glyphs > 0; num_input_glyphs-- )
for ( count = num_input_glyphs; count > 0; count-- )
otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid );
num_lookahead_glyphs = OTL_NEXT_USHORT( p );
OTL_CHECK( 2 * num_lookahead_glyphs + 2 );
OTL_CHECK( num_lookahead_glyphs * 2 + 2 );
for ( ; num_lookahead_glyphs > 0; num_lookahead_glyphs-- )
otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid );
@ -839,7 +896,14 @@
num_subst = OTL_NEXT_USHORT( p );
OTL_CHECK( num_subst * 4 );
/* XXX: check subst lookups */
for ( ; num_subst > 0; num_subst-- )
{
if ( OTL_NEXT_USHORT( p ) >= num_input_glyphs )
OTL_INVALID_DATA;
if ( OTL_NEXT_USHORT( p ) >= lookup_count )
OTL_INVALID_DATA;
}
}
break;
@ -859,6 +923,8 @@
static void
otl_gsub_lookup7_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
@ -883,7 +949,7 @@
OTL_INVALID_DATA;
validate = otl_gsub_validate_funcs[lookup_type - 1];
validate( table + lookup_offset, valid );
validate( table + lookup_offset, lookup_count, glyph_count, valid );
}
break;
@ -903,12 +969,16 @@
static void
otl_gsub_lookup8_validate( OTL_Bytes table,
OTL_UInt lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table, coverage;
OTL_UInt format;
OTL_UInt num_backtrack_glyphs, num_lookahead_glyphs, num_glyphs;
OTL_UNUSED( lookup_count );
OTL_CHECK( 2 );
format = OTL_NEXT_USHORT( p );
@ -922,13 +992,13 @@
otl_coverage_validate( coverage, valid );
OTL_CHECK( 2 * num_backtrack_glyphs + 2 );
OTL_CHECK( num_backtrack_glyphs * 2 + 2 );
for ( ; num_backtrack_glyphs > 0; num_backtrack_glyphs-- )
otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid );
num_lookahead_glyphs = OTL_NEXT_USHORT( p );
OTL_CHECK( 2 * num_lookahead_glyphs + 2 );
OTL_CHECK( num_lookahead_glyphs * 2 + 2 );
for ( ; num_lookahead_glyphs > 0; num_lookahead_glyphs-- )
otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid );
@ -937,9 +1007,12 @@
if ( num_glyphs != otl_coverage_get_count( coverage ) )
OTL_INVALID_DATA;
OTL_CHECK( 2 * num_glyphs );
OTL_CHECK( num_glyphs * 2 );
for ( ; num_glyphs > 0; num_glyphs-- )
if ( OTL_NEXT_USHORT( p ) >= glyph_count )
OTL_INVALID_DATA;
/* XXX: check glyph indices */
break;
default:
@ -971,6 +1044,7 @@
OTL_LOCALDEF( void )
otl_gsub_validate( OTL_Bytes table,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
@ -987,7 +1061,7 @@
lookups = OTL_NEXT_USHORT( p );
otl_lookup_list_validate( table + lookups, 8, otl_gsub_validate_funcs,
valid );
glyph_count, valid );
otl_feature_list_validate( table + features, table + lookups, valid );
otl_script_list_validate( table + scripts, table + features, valid );
}

View File

@ -40,6 +40,7 @@ OTL_BEGIN_HEADER
OTL_LOCAL( void )
otl_gsub_validate( OTL_Bytes table,
OTL_UInt glyph_count,
OTL_Validator valid );

View File

@ -23,6 +23,7 @@
static void
otl_jstf_extender_validate( OTL_Bytes table,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
@ -35,7 +36,9 @@
OTL_CHECK( num_glyphs * 2 );
/* XXX: check glyph indices */
for ( ; num_glyphs > 0; num_glyphs-- )
if ( OTL_NEXT_USHORT( p ) >= glyph_count )
OTL_INVALID_DATA;
}
@ -63,6 +66,7 @@
static void
otl_jstf_max_validate( OTL_Bytes table,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
@ -76,7 +80,8 @@
/* scan subtable records */
for ( ; num_lookups > 0; num_lookups-- )
/* XXX: check lookup types? */
otl_gpos_subtable_validate( table + OTL_NEXT_USHORT( p ), valid );
otl_gpos_subtable_validate( table + OTL_NEXT_USHORT( p ), glyph_count,
valid );
}
@ -84,6 +89,7 @@
otl_jstf_priority_validate( OTL_Bytes table,
OTL_UInt gsub_lookup_count,
OTL_UInt gpos_lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
@ -117,7 +123,7 @@
/* shrinkage JSTF max */
val = OTL_NEXT_USHORT( p );
if ( val )
otl_jstf_max_validate( table + val, valid );
otl_jstf_max_validate( table + val, glyph_count, valid );
/* extension GSUB enable/disable */
val = OTL_NEXT_USHORT( p );
@ -144,7 +150,7 @@
/* extension JSTF max */
val = OTL_NEXT_USHORT( p );
if ( val )
otl_jstf_max_validate( table + val, valid );
otl_jstf_max_validate( table + val, glyph_count, valid );
}
@ -152,6 +158,7 @@
otl_jstf_lang_validate( OTL_Bytes table,
OTL_UInt gsub_lookup_count,
OTL_UInt gpos_lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
@ -166,7 +173,7 @@
for ( ; num_priorities > 0; num_priorities-- )
otl_jstf_priority_validate( table + OTL_NEXT_USHORT( p ),
gsub_lookup_count, gpos_lookup_count,
valid );
glyph_count, valid );
}
@ -174,6 +181,7 @@
otl_jstf_script_validate( OTL_Bytes table,
OTL_UInt gsub_lookup_count,
OTL_UInt gpos_lookup_count,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
@ -186,11 +194,12 @@
num_langsys = OTL_NEXT_USHORT( p );
if ( extender )
otl_jstf_extender_validate( table + extender, valid );
otl_jstf_extender_validate( table + extender, glyph_count, valid );
if ( default_lang )
otl_jstf_lang_validate( table + default_lang,
gsub_lookup_count, gpos_lookup_count, valid );
gsub_lookup_count, gpos_lookup_count,
glyph_count, valid );
OTL_CHECK( 6 * num_langsys );
@ -200,7 +209,8 @@
p += 4; /* skip tag */
otl_jstf_lang_validate( table + OTL_NEXT_USHORT( p ),
gsub_lookup_count, gpos_lookup_count, valid );
gsub_lookup_count, gpos_lookup_count,
glyph_count, valid );
}
}
@ -209,6 +219,7 @@
otl_jstf_validate( OTL_Bytes table,
OTL_Bytes gsub,
OTL_Bytes gpos,
OTL_UInt glyph_count,
OTL_Validator valid )
{
OTL_Bytes p = table;
@ -239,7 +250,8 @@
p += 4; /* skip tag */
otl_jstf_script_validate( table + OTL_NEXT_USHORT( p ),
gsub_lookup_count, gpos_lookup_count, valid );
gsub_lookup_count, gpos_lookup_count,
glyph_count, valid );
}
}

View File

@ -25,13 +25,14 @@
OTL_BEGIN_HEADER
/* validate JSTF table */
/* GSUB and GPOS tables must already be validated; if table is */
/* missing, set value to 0 */
/* validate JSTF table */
/* GSUB and GPOS tables should already be validated; */
/* if missing, set corresponding argument to 0 */
OTL_LOCAL( void )
otl_jstf_validate( OTL_Bytes table,
OTL_Bytes gsub,
OTL_Bytes gpos,
OTL_UInt glyph_count,
OTL_Validator valid );