From d4f773ef92fdbaa7e61e6577db5e9b2846a100a4 Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Mon, 19 Jul 2004 20:37:22 +0000 Subject: [PATCH] Fix pervasive buffer overruns when skipping glyphs when matching contexts. Mon Jul 19 16:29:45 2004 Owen Taylor * pango/opentype/ftxgsub.c pango/opentype/ftxgpos.c: Fix pervasive buffer overruns when skipping glyphs when matching contexts. (#118592, Kailash C. Chowksey) --- src/ftxgpos.c | 259 +++++++++++++++------------------ src/ftxgsub.c | 388 +++++++++++++++++++++++--------------------------- 2 files changed, 290 insertions(+), 357 deletions(-) diff --git a/src/ftxgpos.c b/src/ftxgpos.c index 8bbddcddb..27c38a33d 100644 --- a/src/ftxgpos.c +++ b/src/ftxgpos.c @@ -1625,10 +1625,9 @@ if ( error && error != TTO_Err_Not_Covered ) return error; - if ( buffer->in_pos < buffer->in_length ) - (buffer->in_pos)++; - else - break; + if ( buffer->in_pos == buffer->in_length ) + return TTO_Err_Not_Covered; + (buffer->in_pos)++; } switch ( pp->PosFormat ) @@ -3864,33 +3863,34 @@ for ( k = 0; k < numpr; k++ ) { if ( context_length != 0xFFFF && context_length < pr[k].GlyphCount ) - continue; + goto next_posrule; if ( buffer->in_pos + pr[k].GlyphCount > buffer->in_length ) - continue; /* context is too long */ + goto next_posrule; /* context is too long */ - for ( i = 1, j = 1; i < pr[k].GlyphCount; i++, j++ ) + for ( i = 1, j = buffer->in_pos + 1; i < pr[k].GlyphCount; i++, j++ ) { - while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) ) + while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) ) { if ( error && error != TTO_Err_Not_Covered ) return error; - if ( buffer->in_pos + j < buffer->in_length ) - j++; - else - break; + if ( j + pr[k].GlyphCount - i == buffer->in_length ) + goto next_posrule; + j++; } - if ( IN_CURGLYPH( j ) != pr[k].Input[i - 1] ) - break; + if ( IN_GLYPH( j ) != pr[k].Input[i - 1] ) + goto next_posrule; } - if ( i == pr[k].GlyphCount ) - return Do_ContextPos( gpi, pr[k].GlyphCount, - pr[k].PosCount, pr[k].PosLookupRecord, - buffer, - nesting_level ); + return Do_ContextPos( gpi, pr[k].GlyphCount, + pr[k].PosCount, pr[k].PosLookupRecord, + buffer, + nesting_level ); + + next_posrule: + ; } return TTO_Err_Not_Covered; @@ -3952,50 +3952,49 @@ pr = &pcs->PosClassRule[k]; if ( context_length != 0xFFFF && context_length < pr->GlyphCount ) - continue; + goto next_posclassrule; if ( buffer->in_pos + pr->GlyphCount > buffer->in_length ) - continue; /* context is too long */ + goto next_posclassrule; /* context is too long */ cl = pr->Class; /* Start at 1 because [0] is implied */ - for ( i = 1, j = 1; i < pr->GlyphCount; i++, j++ ) + for ( i = 1, j = buffer->in_pos + 1; i < pr->GlyphCount; i++, j++ ) { - while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) ) + while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) ) { if ( error && error != TTO_Err_Not_Covered ) goto End; - if ( buffer->in_pos + j < buffer->in_length ) - j++; - else - break; + if ( j + pr->GlyphCount - i == buffer->in_length ) + goto next_posclassrule; + j++; } if ( i > known_classes ) { /* Keeps us from having to do this for each rule */ - error = Get_Class( &cpf2->ClassDef, IN_CURGLYPH( j ), &classes[i], NULL ); + error = Get_Class( &cpf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL ); if ( error && error != TTO_Err_Not_Covered ) goto End; known_classes = i; } if ( cl[i - 1] != classes[i] ) - break; + goto next_posclassrule; } - if ( i == pr->GlyphCount ) - { - error = Do_ContextPos( gpi, pr->GlyphCount, - pr->PosCount, pr->PosLookupRecord, - buffer, - nesting_level ); - goto End; - } + error = Do_ContextPos( gpi, pr->GlyphCount, + pr->PosCount, pr->PosLookupRecord, + buffer, + nesting_level ); + goto End; + + next_posclassrule: + ; } error = TTO_Err_Not_Covered; @@ -4036,18 +4035,17 @@ for ( i = 1, j = 1; i < cpf3->GlyphCount; i++, j++ ) { - while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) ) + while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) ) { if ( error && error != TTO_Err_Not_Covered ) return error; - if ( buffer->in_pos + j < buffer->in_length ) - j++; - else + if ( j + cpf3->GlyphCount - i == buffer->in_length ) return TTO_Err_Not_Covered; + j++; } - error = Coverage_Index( &c[i], IN_CURGLYPH( j ), &index ); + error = Coverage_Index( &c[i], IN_GLYPH( j ), &index ); if ( error ) return error; } @@ -5112,7 +5110,7 @@ int nesting_level ) { FT_UShort index, property; - FT_UShort i, j, k, num_cpr, curr_pos; + FT_UShort i, j, k, num_cpr; FT_UShort bgc, igc, lgc; FT_Error error; TTO_GPOSHeader* gpos = gpi->gpos; @@ -5142,20 +5140,18 @@ lgc = curr_cpr.LookaheadGlyphCount; if ( context_length != 0xFFFF && context_length < igc ) - continue; + goto next_chainposrule; /* check whether context is too long; it is a first guess only */ if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length ) - continue; + goto next_chainposrule; if ( bgc ) { /* Since we don't know in advance the number of glyphs to inspect, we search backwards for matches in the backtrack glyph array */ - curr_pos = 0; - for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- ) { while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) ) @@ -5163,10 +5159,9 @@ if ( error && error != TTO_Err_Not_Covered ) return error; - if ( j > curr_pos ) - j--; - else - break; + if ( j + 1 == bgc - i ) + goto next_chainposrule; + j--; } /* In OpenType 1.3, it is undefined whether the offsets of @@ -5180,65 +5175,55 @@ Lookahead offsets - 0 1 2 3 */ if ( IN_GLYPH( j ) != curr_cpr.Backtrack[i] ) - break; + goto next_chainposrule; } - - if ( i != bgc ) - continue; } - curr_pos = buffer->in_pos; - /* Start at 1 because [0] is implied */ - for ( i = 1, j = 1; i < igc; i++, j++ ) + for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ ) { - while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) ) + while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) ) { if ( error && error != TTO_Err_Not_Covered ) return error; - if ( curr_pos + j < buffer->in_length ) - j++; - else - break; + if ( j + igc - i + lgc == buffer->in_length ) + goto next_chainposrule; + j++; } - if ( IN_GLYPH( curr_pos + j ) != curr_cpr.Input[i - 1] ) - break; + if ( IN_GLYPH( j ) != curr_cpr.Input[i - 1] ) + goto next_chainposrule; } - if ( i != igc ) - continue; - /* we are starting to check for lookahead glyphs right after the last context glyph */ - curr_pos += j; - - for ( i = 0, j = 0; i < lgc; i++, j++ ) + for ( i = 0; i < lgc; i++, j++ ) { - while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) ) + while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) ) { if ( error && error != TTO_Err_Not_Covered ) return error; - if ( curr_pos + j < buffer->in_length ) - j++; - else - break; + if ( j + lgc - i == buffer->in_length ) + goto next_chainposrule; + j++; } - if ( IN_GLYPH( curr_pos + j ) != curr_cpr.Lookahead[i] ) - break; + if ( IN_GLYPH( j ) != curr_cpr.Lookahead[i] ) + goto next_chainposrule; } - if ( i == lgc ) - return Do_ContextPos( gpi, igc, - curr_cpr.PosCount, - curr_cpr.PosLookupRecord, - buffer, - nesting_level ); + return Do_ContextPos( gpi, igc, + curr_cpr.PosCount, + curr_cpr.PosLookupRecord, + buffer, + nesting_level ); + + next_chainposrule: + ; } return TTO_Err_Not_Covered; @@ -5256,7 +5241,7 @@ FT_UShort index, property; FT_Memory memory = gpi->face->memory; FT_Error error; - FT_UShort i, j, k, curr_pos; + FT_UShort i, j, k; FT_UShort bgc, igc, lgc; FT_UShort known_backtrack_classes, known_input_classes, @@ -5321,12 +5306,12 @@ lgc = cpcr.LookaheadGlyphCount; if ( context_length != 0xFFFF && context_length < igc ) - continue; + goto next_chainposclassrule; /* check whether context is too long; it is a first guess only */ if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length ) - continue; + goto next_chainposclassrule; if ( bgc ) { @@ -5334,7 +5319,6 @@ we search backwards for matches in the backtrack glyph array. Note that `known_backtrack_classes' starts at index 0. */ - curr_pos = 0; bc = cpcr.Backtrack; for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- ) @@ -5344,10 +5328,9 @@ if ( error && error != TTO_Err_Not_Covered ) goto End1; - if ( j > curr_pos ) - j--; - else - break; + if ( j + 1 == bgc - i ) + goto next_chainposclassrule; + j++; } if ( i >= known_backtrack_classes ) @@ -5362,34 +5345,29 @@ } if ( bc[i] != backtrack_classes[i] ) - break; + goto next_chainposclassrule; } - - if ( i != bgc ) - continue; } - curr_pos = buffer->in_pos; ic = cpcr.Input; /* Start at 1 because [0] is implied */ - for ( i = 1, j = 1; i < igc; i++, j++ ) + for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ ) { - while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) ) + while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) ) { if ( error && error != TTO_Err_Not_Covered ) goto End1; - if ( curr_pos + j < buffer->in_length ) - j++; - else - break; + if ( j + igc - i + lgc == buffer->in_length ) + goto next_chainposclassrule; + j++; } if ( i >= known_input_classes ) { - error = Get_Class( &ccpf2->InputClassDef, IN_GLYPH( curr_pos + j ), + error = Get_Class( &ccpf2->InputClassDef, IN_GLYPH( j ), &input_classes[i], NULL ); if ( error && error != TTO_Err_Not_Covered ) goto End1; @@ -5397,34 +5375,29 @@ } if ( ic[i - 1] != input_classes[i] ) - break; + goto next_chainposclassrule; } - if ( i != igc ) - continue; - /* we are starting to check for lookahead glyphs right after the last context glyph */ - curr_pos += j; lc = cpcr.Lookahead; - for ( i = 0, j = 0; i < lgc; i++, j++ ) + for ( i = 0; i < lgc; i++, j++ ) { - while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) ) + while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) ) { if ( error && error != TTO_Err_Not_Covered ) goto End1; - if ( curr_pos + j < buffer->in_length ) - j++; - else - break; + if ( j + lgc - i == buffer->in_length ) + goto next_chainposclassrule; + j++; } if ( i >= known_lookahead_classes ) { - error = Get_Class( &ccpf2->LookaheadClassDef, IN_GLYPH( curr_pos + j ), + error = Get_Class( &ccpf2->LookaheadClassDef, IN_GLYPH( j ), &lookahead_classes[i], NULL ); if ( error && error != TTO_Err_Not_Covered ) goto End1; @@ -5432,18 +5405,18 @@ } if ( lc[i] != lookahead_classes[i] ) - break; + goto next_chainposclassrule; } - if ( i == lgc ) - { - error = Do_ContextPos( gpi, igc, - cpcr.PosCount, - cpcr.PosLookupRecord, - buffer, - nesting_level ); - goto End1; - } + error = Do_ContextPos( gpi, igc, + cpcr.PosCount, + cpcr.PosLookupRecord, + buffer, + nesting_level ); + goto End1; + + next_chainposclassrule: + ; } error = TTO_Err_Not_Covered; @@ -5468,7 +5441,7 @@ FT_UShort context_length, int nesting_level ) { - FT_UShort index, i, j, curr_pos, property; + FT_UShort index, i, j, property; FT_UShort bgc, igc, lgc; FT_Error error; TTO_GPOSHeader* gpos = gpi->gpos; @@ -5501,7 +5474,6 @@ /* Since we don't know in advance the number of glyphs to inspect, we search backwards for matches in the backtrack glyph array */ - curr_pos = 0; bc = ccpf3->BacktrackCoverage; for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- ) @@ -5511,10 +5483,9 @@ if ( error && error != TTO_Err_Not_Covered ) return error; - if ( j > curr_pos ) - j--; - else + if ( j + 1 == bgc - i ) return TTO_Err_Not_Covered; + j--; } error = Coverage_Index( &bc[i], IN_GLYPH( j ), &index ); @@ -5523,24 +5494,22 @@ } } - curr_pos = buffer->in_pos; ic = ccpf3->InputCoverage; - for ( i = 0, j = 0; i < igc; i++, j++ ) + for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ ) { - /* We already called CHECK_Property for s_in[0] */ - while ( j > 0 && CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) ) + /* We already called CHECK_Property for IN_GLYPH ( buffer->in_pos ) */ + while ( j > buffer->in_pos && CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) ) { if ( error && error != TTO_Err_Not_Covered ) return error; - if ( curr_pos + j < buffer->in_length ) - j++; - else + if ( j + igc - i + lgc == buffer->in_length ) return TTO_Err_Not_Covered; + j++; } - error = Coverage_Index( &ic[i], IN_GLYPH( curr_pos + j ), &index ); + error = Coverage_Index( &ic[i], IN_GLYPH( j ), &index ); if ( error ) return error; } @@ -5548,23 +5517,21 @@ /* we are starting to check for lookahead glyphs right after the last context glyph */ - curr_pos += j; lc = ccpf3->LookaheadCoverage; - for ( i = 0, j = 0; i < lgc; i++, j++ ) + for ( i = 0; i < lgc; i++, j++ ) { - while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) ) + while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) ) { if ( error && error != TTO_Err_Not_Covered ) return error; - if ( curr_pos + j < buffer->in_length ) - j++; - else + if ( j + lgc - i == buffer->in_length ) return TTO_Err_Not_Covered; + j++; } - error = Coverage_Index( &lc[i], IN_GLYPH( curr_pos + j ), &index ); + error = Coverage_Index( &lc[i], IN_GLYPH( j ), &index ); if ( error ) return error; } diff --git a/src/ftxgsub.c b/src/ftxgsub.c index 0ec246dce..4ca70d139 100644 --- a/src/ftxgsub.c +++ b/src/ftxgsub.c @@ -1026,7 +1026,7 @@ numlig--, lig++ ) { if ( buffer->in_pos + lig->ComponentCount > buffer->in_length ) - continue; /* Not enough glyphs in input */ + goto next_ligature; /* Not enough glyphs in input */ c = lig->Component; @@ -1035,85 +1035,84 @@ if ( context_length != 0xFFFF && context_length < lig->ComponentCount ) break; - for ( i = 1, j = 1; i < lig->ComponentCount; i++, j++ ) + for ( i = 1, j = buffer->in_pos + 1; i < lig->ComponentCount; i++, j++ ) { - while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) ) + while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) ) { if ( error && error != TTO_Err_Not_Covered ) return error; - if ( buffer->in_pos + j < buffer->in_length ) - j++; - else - break; + if ( j + lig->ComponentCount - i == buffer->in_length ) + goto next_ligature; + j++; } if ( !( property == TTO_MARK || property & IGNORE_SPECIAL_MARKS ) ) is_mark = FALSE; - if ( IN_CURGLYPH( j ) != c[i - 1] ) - break; + if ( IN_GLYPH( j ) != c[i - 1] ) + goto next_ligature; } - if ( i == lig->ComponentCount ) + if ( gdef && gdef->NewGlyphClasses ) { - if ( gdef && gdef->NewGlyphClasses ) - { - /* this is just a guess ... */ + /* this is just a guess ... */ - error = Add_Glyph_Property( gdef, lig->LigGlyph, - is_mark ? TTO_MARK : TTO_LIGATURE ); - if ( error && error != TTO_Err_Not_Covered ) - return error; - } - - if ( i == j ) - { - /* We don't use a new ligature ID if there are no skipped - glyphs and the ligature already has an ID. */ - - if ( IN_LIGID( buffer->in_pos ) ) - { - if ( ADD_String( buffer, i, 1, &lig->LigGlyph, - 0xFFFF, 0xFFFF ) ) - return error; - } - else - { - FT_UShort ligID = otl_buffer_allocate_ligid( buffer ); - if ( ADD_String( buffer, i, 1, &lig->LigGlyph, - 0xFFFF, ligID ) ) - return error; - } - } - else - { - FT_UShort ligID = otl_buffer_allocate_ligid( buffer ); - if ( ADD_Glyph( buffer, lig->LigGlyph, - 0xFFFF, ligID ) ) - return error; - - /* Now we must do a second loop to copy the skipped glyphs to - `out' and assign component values to it. We start with the - glyph after the first component. Glyphs between component - i and i+1 belong to component i. Together with the ligID - value it is later possible to check whether a specific - component value really belongs to a given ligature. */ - - for ( i = 0; i < lig->ComponentCount - 1; i++ ) - { - while ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), - flags, &property ) ) - if ( ADD_Glyph( buffer, IN_CURGLYPH( 0 ), - i, ligID ) ) - return error; - - (buffer->in_pos)++; - } - } - - return TT_Err_Ok; + error = Add_Glyph_Property( gdef, lig->LigGlyph, + is_mark ? TTO_MARK : TTO_LIGATURE ); + if ( error && error != TTO_Err_Not_Covered ) + return error; } + + if ( j == buffer->in_pos + i ) /* No input glyphs skipped */ + { + /* We don't use a new ligature ID if there are no skipped + glyphs and the ligature already has an ID. */ + + if ( IN_LIGID( buffer->in_pos ) ) + { + if ( ADD_String( buffer, i, 1, &lig->LigGlyph, + 0xFFFF, 0xFFFF ) ) + return error; + } + else + { + FT_UShort ligID = otl_buffer_allocate_ligid( buffer ); + if ( ADD_String( buffer, i, 1, &lig->LigGlyph, + 0xFFFF, ligID ) ) + return error; + } + } + else + { + FT_UShort ligID = otl_buffer_allocate_ligid( buffer ); + if ( ADD_Glyph( buffer, lig->LigGlyph, + 0xFFFF, ligID ) ) + return error; + + /* Now we must do a second loop to copy the skipped glyphs to + `out' and assign component values to it. We start with the + glyph after the first component. Glyphs between component + i and i+1 belong to component i. Together with the ligID + value it is later possible to check whether a specific + component value really belongs to a given ligature. */ + + for ( i = 0; i < lig->ComponentCount - 1; i++ ) + { + while ( CHECK_Property( gdef, IN_CURGLYPH( 0 ), + flags, &property ) ) + if ( ADD_Glyph( buffer, IN_CURGLYPH( 0 ), + i, ligID ) ) + return error; + + (buffer->in_pos)++; + } + } + + return TT_Err_Ok; + + next_ligature: + ; } return TTO_Err_Not_Covered; @@ -1921,33 +1920,33 @@ for ( k = 0; k < numsr; k++ ) { if ( context_length != 0xFFFF && context_length < sr[k].GlyphCount ) - continue; + goto next_subrule; if ( buffer->in_pos + sr[k].GlyphCount > buffer->in_length ) - continue; /* context is too long */ + goto next_subrule; /* context is too long */ - for ( i = 1, j = 1; i < sr[k].GlyphCount; i++, j++ ) + for ( i = 1, j = buffer->in_pos + 1; i < sr[k].GlyphCount; i++, j++ ) { - while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) ) + while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) ) { if ( error && error != TTO_Err_Not_Covered ) return error; - if ( buffer->in_pos + j < buffer->in_length ) - j++; - else - break; + if ( j + sr[k].GlyphCount - i == buffer->in_length ) + goto next_subrule; + j++; } - if ( IN_CURGLYPH( j ) != sr[k].Input[i - 1] ) - break; + if ( IN_GLYPH( j ) != sr[k].Input[i - 1] ) + goto next_subrule; } - if ( i == sr[k].GlyphCount ) - return Do_ContextSubst( gsub, sr[k].GlyphCount, - sr[k].SubstCount, sr[k].SubstLookupRecord, - buffer, - nesting_level ); + return Do_ContextSubst( gsub, sr[k].GlyphCount, + sr[k].SubstCount, sr[k].SubstLookupRecord, + buffer, + nesting_level ); + next_subrule: + ; } return TTO_Err_Not_Covered; @@ -2009,50 +2008,49 @@ sr = &scs->SubClassRule[k]; if ( context_length != 0xFFFF && context_length < sr->GlyphCount ) - continue; + goto next_subclassrule; if ( buffer->in_pos + sr->GlyphCount > buffer->in_length ) - continue; /* context is too long */ + goto next_subclassrule; /* context is too long */ cl = sr->Class; /* Start at 1 because [0] is implied */ - for ( i = 1, j = 1; i < sr->GlyphCount; i++, j++ ) + for ( i = 1, j = buffer->in_pos + 1; i < sr->GlyphCount; i++, j++ ) { - while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) ) + while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) ) { if ( error && error != TTO_Err_Not_Covered ) goto End; - if ( buffer->in_pos + j < buffer->in_length ) - j++; - else - break; + if ( j + sr->GlyphCount - i < buffer->in_length ) + goto next_subclassrule; + j++; } if ( i > known_classes ) { /* Keeps us from having to do this for each rule */ - error = Get_Class( &csf2->ClassDef, IN_CURGLYPH( j ), &classes[i], NULL ); + error = Get_Class( &csf2->ClassDef, IN_GLYPH( j ), &classes[i], NULL ); if ( error && error != TTO_Err_Not_Covered ) goto End; known_classes = i; } if ( cl[i - 1] != classes[i] ) - break; + goto next_subclassrule; } - if ( i == sr->GlyphCount ) - { - error = Do_ContextSubst( gsub, sr->GlyphCount, - sr->SubstCount, sr->SubstLookupRecord, - buffer, - nesting_level ); - goto End; - } + error = Do_ContextSubst( gsub, sr->GlyphCount, + sr->SubstCount, sr->SubstLookupRecord, + buffer, + nesting_level ); + goto End; + + next_subclassrule: + ; } error = TTO_Err_Not_Covered; @@ -2091,20 +2089,19 @@ c = csf3->Coverage; - for ( i = 1, j = 1; i < csf3->GlyphCount; i++, j++ ) + for ( i = 1, j = buffer->in_pos + 1; i < csf3->GlyphCount; i++, j++ ) { - while ( CHECK_Property( gdef, IN_CURGLYPH( j ), flags, &property ) ) + while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) ) { if ( error && error != TTO_Err_Not_Covered ) return error; - if ( buffer->in_pos + j < buffer->in_length ) - j++; - else + if ( j + csf3->GlyphCount - i == buffer->in_length ) return TTO_Err_Not_Covered; + j++; } - error = Coverage_Index( &c[i], IN_CURGLYPH( j ), &index ); + error = Coverage_Index( &c[i], IN_GLYPH( j ), &index ); if ( error ) return error; } @@ -3175,7 +3172,7 @@ int nesting_level ) { FT_UShort index, property; - FT_UShort i, j, k, num_csr, curr_pos; + FT_UShort i, j, k, num_csr; FT_UShort bgc, igc, lgc; FT_Error error; @@ -3204,20 +3201,18 @@ lgc = curr_csr.LookaheadGlyphCount; if ( context_length != 0xFFFF && context_length < igc ) - continue; + goto next_chainsubrule; /* check whether context is too long; it is a first guess only */ if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length ) - continue; + goto next_chainsubrule; if ( bgc ) { /* since we don't know in advance the number of glyphs to inspect, we search backwards for matches in the backtrack glyph array */ - curr_pos = 0; - for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- ) { while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) ) @@ -3225,10 +3220,9 @@ if ( error && error != TTO_Err_Not_Covered ) return error; - if ( j > curr_pos ) - j--; - else - break; + if ( j + 1 == bgc - i ) + goto next_chainsubrule; + j--; } /* In OpenType 1.3, it is undefined whether the offsets of @@ -3242,65 +3236,55 @@ Lookahead offsets - 0 1 2 3 */ if ( IN_GLYPH( j ) != curr_csr.Backtrack[i] ) - break; + goto next_chainsubrule; } - - if ( i != bgc ) - continue; } - curr_pos = buffer->in_pos; - /* Start at 1 because [0] is implied */ - for ( i = 1, j = 1; i < igc; i++, j++ ) + for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ ) { - while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) ) + while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) ) { if ( error && error != TTO_Err_Not_Covered ) return error; - if ( curr_pos + j < buffer->in_length ) - j++; - else - break; + if ( j + igc - i + lgc == buffer->in_length ) + goto next_chainsubrule; + j++; } - if ( IN_GLYPH( curr_pos + j ) != curr_csr.Input[i - 1] ) - break; + if ( IN_GLYPH( j ) != curr_csr.Input[i - 1] ) + goto next_chainsubrule; } - if ( i != igc ) - continue; - /* we are starting to check for lookahead glyphs right after the last context glyph */ - curr_pos += j; - - for ( i = 0, j = 0; i < lgc; i++, j++ ) + for ( i = 0; i < lgc; i++, j++ ) { - while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) ) + while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) ) { if ( error && error != TTO_Err_Not_Covered ) return error; - if ( curr_pos + j < buffer->in_length ) - j++; - else - break; + if ( j + lgc - i == buffer->in_length ) + goto next_chainsubrule; + j++; } - if ( IN_GLYPH( curr_pos + j ) != curr_csr.Lookahead[i] ) - break; + if ( IN_GLYPH( j ) != curr_csr.Lookahead[i] ) + goto next_chainsubrule; } - if ( i == lgc ) - return Do_ContextSubst( gsub, igc, - curr_csr.SubstCount, - curr_csr.SubstLookupRecord, - buffer, - nesting_level ); + return Do_ContextSubst( gsub, igc, + curr_csr.SubstCount, + curr_csr.SubstLookupRecord, + buffer, + nesting_level ); + + next_chainsubrule: + ; } return TTO_Err_Not_Covered; @@ -3318,7 +3302,7 @@ FT_UShort index, property; FT_Memory memory; FT_Error error; - FT_UShort i, j, k, curr_pos; + FT_UShort i, j, k; FT_UShort bgc, igc, lgc; FT_UShort known_backtrack_classes, known_input_classes, @@ -3383,12 +3367,12 @@ lgc = ccsr.LookaheadGlyphCount; if ( context_length != 0xFFFF && context_length < igc ) - continue; + goto next_chainsubclassrule; /* check whether context is too long; it is a first guess only */ if ( bgc > buffer->in_pos || buffer->in_pos + igc + lgc > buffer->in_length ) - continue; + goto next_chainsubclassrule; if ( bgc ) { @@ -3396,7 +3380,6 @@ we search backwards for matches in the backtrack glyph array. Note that `known_backtrack_classes' starts at index 0. */ - curr_pos = 0; bc = ccsr.Backtrack; for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- ) @@ -3406,10 +3389,9 @@ if ( error && error != TTO_Err_Not_Covered ) goto End1; - if ( j > curr_pos ) - j--; - else - break; + if ( j + 1 == bgc - i ) + goto next_chainsubclassrule; + j--; } if ( i >= known_backtrack_classes ) @@ -3424,34 +3406,29 @@ } if ( bc[i] != backtrack_classes[i] ) - break; + goto next_chainsubclassrule; } - - if ( i != bgc ) - continue; } - curr_pos = buffer->in_pos; ic = ccsr.Input; /* Start at 1 because [0] is implied */ - for ( i = 1, j = 1; i < igc; i++, j++ ) + for ( i = 1, j = buffer->in_pos + 1; i < igc; i++, j++ ) { - while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) ) + while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) ) { if ( error && error != TTO_Err_Not_Covered ) goto End1; - if ( curr_pos + j < buffer->in_length ) - j++; - else - break; + if ( j + igc - i + lgc == buffer->in_length ) + goto next_chainsubclassrule; + j++; } if ( i >= known_input_classes ) { - error = Get_Class( &ccsf2->InputClassDef, IN_GLYPH( curr_pos + j ), + error = Get_Class( &ccsf2->InputClassDef, IN_GLYPH( j ), &input_classes[i], NULL ); if ( error && error != TTO_Err_Not_Covered ) goto End1; @@ -3459,34 +3436,29 @@ } if ( ic[i - 1] != input_classes[i] ) - break; + goto next_chainsubclassrule; } - if ( i != igc ) - continue; - /* we are starting to check for lookahead glyphs right after the last context glyph */ - curr_pos += j; lc = ccsr.Lookahead; - for ( i = 0, j = 0; i < lgc; i++, j++ ) + for ( i = 0; i < lgc; i++, j++ ) { - while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) ) + while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) ) { if ( error && error != TTO_Err_Not_Covered ) goto End1; - if ( curr_pos + j < buffer->in_length ) - j++; - else - break; + if ( j + lgc - i == buffer->in_length ) + goto next_chainsubclassrule; + j++; } if ( i >= known_lookahead_classes ) { - error = Get_Class( &ccsf2->LookaheadClassDef, IN_GLYPH( curr_pos + j ), + error = Get_Class( &ccsf2->LookaheadClassDef, IN_GLYPH( j ), &lookahead_classes[i], NULL ); if ( error && error != TTO_Err_Not_Covered ) goto End1; @@ -3494,18 +3466,18 @@ } if ( lc[i] != lookahead_classes[i] ) - break; + goto next_chainsubclassrule; } - if ( i == lgc ) - { - error = Do_ContextSubst( gsub, igc, - ccsr.SubstCount, - ccsr.SubstLookupRecord, - buffer, - nesting_level ); - goto End1; - } + error = Do_ContextSubst( gsub, igc, + ccsr.SubstCount, + ccsr.SubstLookupRecord, + buffer, + nesting_level ); + goto End1; + + next_chainsubclassrule: + ; } error = TTO_Err_Not_Covered; @@ -3530,7 +3502,7 @@ FT_UShort context_length, int nesting_level ) { - FT_UShort index, i, j, curr_pos, property; + FT_UShort index, i, j, property; FT_UShort bgc, igc, lgc; FT_Error error; @@ -3562,7 +3534,6 @@ /* Since we don't know in advance the number of glyphs to inspect, we search backwards for matches in the backtrack glyph array */ - curr_pos = 0; bc = ccsf3->BacktrackCoverage; for ( i = 0, j = buffer->in_pos - 1; i < bgc; i++, j-- ) @@ -3572,10 +3543,9 @@ if ( error && error != TTO_Err_Not_Covered ) return error; - if ( j > curr_pos ) - j--; - else - return TTO_Err_Not_Covered; + if ( j + 1 == bgc - i ) + return TTO_Err_Not_Covered; + j--; } error = Coverage_Index( &bc[i], IN_GLYPH( j ), &index ); @@ -3584,24 +3554,22 @@ } } - curr_pos = buffer->in_pos; ic = ccsf3->InputCoverage; - for ( i = 0, j = 0; i < igc; i++, j++ ) + for ( i = 0, j = buffer->in_pos; i < igc; i++, j++ ) { - /* We already called CHECK_Property for IN_GLYPH( curr_pos ) */ - while ( j > 0 && CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) ) + /* We already called CHECK_Property for IN_GLYPH( buffer->in_pos ) */ + while ( j > buffer->in_pos && CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) ) { if ( error && error != TTO_Err_Not_Covered ) return error; - - if ( curr_pos + j < buffer->in_length ) - j++; - else + + if ( j + igc - i + lgc == buffer->in_length ) return TTO_Err_Not_Covered; + j++; } - error = Coverage_Index( &ic[i], IN_GLYPH( curr_pos + j ), &index ); + error = Coverage_Index( &ic[i], IN_GLYPH( j ), &index ); if ( error ) return error; } @@ -3609,23 +3577,21 @@ /* we are starting for lookahead glyphs right after the last context glyph */ - curr_pos += j; lc = ccsf3->LookaheadCoverage; - for ( i = 0, j = 0; i < lgc; i++, j++ ) + for ( i = 0; i < lgc; i++, j++ ) { - while ( CHECK_Property( gdef, IN_GLYPH( curr_pos + j ), flags, &property ) ) + while ( CHECK_Property( gdef, IN_GLYPH( j ), flags, &property ) ) { if ( error && error != TTO_Err_Not_Covered ) return error; - if ( curr_pos + j < buffer->in_length ) - j++; - else - return TTO_Err_Not_Covered; + if ( j + lgc - i == buffer->in_length ) + return TTO_Err_Not_Covered; + j++; } - error = Coverage_Index( &lc[i], IN_GLYPH( curr_pos + j ), &index ); + error = Coverage_Index( &lc[i], IN_GLYPH( j ), &index ); if ( error ) return error; }