In Load_ChainContextSubst2, handle the case where an empty class
authorOwen Taylor <otaylor@redhat.com>
Fri, 15 Mar 2002 06:46:05 +0000 (06:46 +0000)
committerOwen Taylor <otaylor@src.gnome.org>
Fri, 15 Mar 2002 06:46:05 +0000 (06:46 +0000)
Fri Mar 15 01:35:56 2002  Owen Taylor  <otaylor@redhat.com>

* pango/opentype/ftxgsub.c pango/opentype/ftxopen.c
pango/opentype/ftxopenf.h: In Load_ChainContextSubst2,
handle the case where an empty class definition
is represented by an offset of 0.

* pango/opentype/ftxgpos.c: Same for Load_ChainContextPos2.

* pango/opentype/{ftxopen.c,ftxgpos.c,ftxgsub.c,ftgdef.c}:
Fix pervasive bug where on cleanups on failure of loading
an array element, all array elements were freed, not
just the ones that had been succesfully loaded.

src/ftxgdef.c
src/ftxgpos.c
src/ftxgsub.c
src/ftxopen.c
src/ftxopenf.h

index 54b1dd0..6456f18 100644 (file)
     FT_Memory memory = stream->memory;
     FT_Error  error;
 
-    FT_UShort         n, count;
+    FT_UShort         n, m, count;
     FT_ULong          cur_offset, new_offset, base_offset;
 
     TTO_AttachPoint*  ap;
     return TT_Err_Ok;
 
   Fail1:
-    for ( n = 0; n < count; n++ )
-      Free_AttachPoint( &ap[n], memory );
+    for ( m = 0; m < n; m++ )
+      Free_AttachPoint( &ap[m], memory );
 
     FREE( ap );
 
     FT_Memory memory = stream->memory;
     FT_Error  error;
 
-    FT_UShort        n, count;
+    FT_UShort        n, m, count;
     FT_ULong         cur_offset, new_offset, base_offset;
 
     TTO_CaretValue*  cv;
     return TT_Err_Ok;
 
   Fail:
-    for ( n = 0; n < count; n++ )
-      Free_CaretValue( &cv[n], memory );
+    for ( m = 0; m < n; m++ )
+      Free_CaretValue( &cv[m], memory );
 
     FREE( cv );
     return error;
     FT_Memory memory = stream->memory;
     FT_Error  error;
 
-    FT_UShort      n, count;
+    FT_UShort      m, n, count;
     FT_ULong       cur_offset, new_offset, base_offset;
 
     TTO_LigGlyph*  lg;
     return TT_Err_Ok;
 
   Fail1:
-    for ( n = 0; n < count; n++ )
-      Free_LigGlyph( &lg[n], memory );
+    for ( m = 0; m < n; m++ )
+      Free_LigGlyph( &lg[m], memory );
 
     FREE( lg );
 
                                            FT_UShort*       class_array )
   {
     FT_UShort              start, curr_glyph, curr_class;
-    FT_UShort              n, count;
+    FT_UShort              n, m, count;
     FT_Error               error;
     FT_Memory              memory = gdef->memory;
 
     return TT_Err_Ok;
 
   Fail1:
-    for ( n = 0; n < count; n++ )
-      FREE( ngc[n] );
+    for ( m = 0; m < n; m++ )
+      FREE( ngc[m] );
 
   Fail2:
     FREE( gdef->NewGlyphClasses );
index 7515b53..012e82d 100644 (file)
     FT_Error  error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort        n, count;
+    FT_UShort        n, m, count;
     FT_ULong         cur_offset, new_offset, base_offset;
 
     TTO_MarkRecord*  mr;
     return TT_Err_Ok;
 
   Fail:
-    for ( n = 0; n < count; n++ )
-      Free_Anchor( &mr[n].MarkAnchor, memory );
+    for ( m = 0; m < n; m++ )
+      Free_Anchor( &mr[m].MarkAnchor, memory );
 
     FREE( mr );
     return error;
     FT_Error  error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort         n, count, format;
+    FT_UShort         n, m, count, format;
     FT_ULong          cur_offset, new_offset, base_offset;
 
     TTO_ValueRecord*  vr;
     return TT_Err_Ok;
 
   Fail1:
-    for ( n = 0; n < count; n++ )
-      Free_ValueRecord( &vr[n], format, memory );
+    for ( m = 0; m < n; m++ )
+      Free_ValueRecord( &vr[m], format, memory );
 
     FREE( vr );
 
     FT_Error  error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort             n, count;
+    FT_UShort             n, m, count;
     FT_ULong              base_offset;
 
     TTO_PairValueRecord*  pvr;
         error = Load_ValueRecord( &pvr[n].Value2, format2,
                                   base_offset, stream );
         if ( error )
+       {
+         if ( format1 )
+           Free_ValueRecord( &pvr[n].Value1, format1, memory );
           goto Fail;
+       }
       }
     }
 
     return TT_Err_Ok;
 
   Fail:
-    for ( n = 0; n < count; n++ )
+    for ( m = 0; m < n; m++ )
     {
       if ( format1 )
-        Free_ValueRecord( &pvr[n].Value1, format1, memory );
+        Free_ValueRecord( &pvr[m].Value1, format1, memory );
       if ( format2 )
-        Free_ValueRecord( &pvr[n].Value2, format2, memory );
+        Free_ValueRecord( &pvr[m].Value2, format2, memory );
     }
 
     FREE( pvr );
     FT_Error  error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort     n, count;
+    FT_UShort     n, m, count;
     FT_ULong      cur_offset, new_offset, base_offset;
 
     TTO_PairSet*  ps;
     ppf1->PairSet = NULL;
 
     if ( ALLOC_ARRAY( ppf1->PairSet, count, TTO_PairSet ) )
-      goto Fail;
+      return error;
 
     ps = ppf1->PairSet;
 
     return TT_Err_Ok;
 
   Fail:
-    for ( n = 0; n < count; n++ )
-      Free_PairSet( &ps[n], format1, format2, memory );
+    for ( m = 0; m < n; m++ )
+      Free_PairSet( &ps[m], format1, format2, memory );
 
     FREE( ps );
     return error;
     FT_Error  error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort          m, n, count1, count2;
+    FT_UShort          m, n, k, count1, count2;
     FT_ULong           cur_offset, new_offset1, new_offset2, base_offset;
 
     TTO_Class1Record*  c1r;
     if ( FILE_Seek( new_offset2 ) ||
          ( error = Load_ClassDefinition( &ppf2->ClassDef2, count2,
                                          stream ) ) != TT_Err_Ok )
-      goto Fail2;
+      goto Fail3;
     (void)FILE_Seek( cur_offset );
 
     ppf2->Class1Record = NULL;
 
     if ( ALLOC_ARRAY( ppf2->Class1Record, count1, TTO_Class1Record ) )
-      goto Fail1;
+      goto Fail2;
 
     c1r = ppf2->Class1Record;
 
           error = Load_ValueRecord( &c2r[n].Value1, format1,
                                     base_offset, stream );
           if ( error )
-            goto Fail1;
+            goto Fail0;
         }
         if ( format2 )
         {
           error = Load_ValueRecord( &c2r[n].Value2, format2,
                                     base_offset, stream );
           if ( error )
-            goto Fail1;
+         {
+           if ( format1 )
+             Free_ValueRecord( &c2r[n].Value1, format1, memory );            
+            goto Fail0;
+         }
         }
       }
+
+      continue;
+
+    Fail0:
+      for ( k = 0; k < n; k++ )
+      {
+        if ( format1 )
+          Free_ValueRecord( &c2r[k].Value1, format1, memory );
+        if ( format2 )
+          Free_ValueRecord( &c2r[k].Value2, format2, memory );
+      }
+      goto Fail1;
     }
 
     return TT_Err_Ok;
 
   Fail1:
-    for ( m = 0; m < count1; m++ )
+    for ( k = 0; k < m; k++ )
     {
-      c2r = c1r[m].Class2Record;
+      c2r = c1r[k].Class2Record;
 
       for ( n = 0; n < count2; n++ )
       {
     }
 
     FREE( c1r );
+  Fail2:
 
     Free_ClassDefinition( &ppf2->ClassDef2, memory );
 
-  Fail2:
+  Fail3:
     Free_ClassDefinition( &ppf2->ClassDef1, memory );
     return error;
   }
     FT_Error  error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort             n, count;
+    FT_UShort             n, m, count;
     FT_ULong              cur_offset, new_offset, base_offset;
 
     TTO_EntryExitRecord*  eer;
 
     for ( n = 0; n < count; n++ )
     {
+      FT_ULong entry_offset;
+      
       if ( ACCESS_Frame( 2L ) )
         return error;
 
-      new_offset = GET_UShort();
+      entry_offset = new_offset = GET_UShort();
 
       FORGET_Frame();
 
         if ( FILE_Seek( new_offset ) ||
              ( error = Load_Anchor( &eer[n].ExitAnchor,
                                     stream ) ) != TT_Err_Ok )
+       {
+         if ( entry_offset )
+           Free_Anchor( &eer[n].EntryAnchor, memory );
           goto Fail1;
+       }
         (void)FILE_Seek( cur_offset );
       }
       else
     return TT_Err_Ok;
 
   Fail1:
-    for ( n = 0; n < count; n++ )
+    for ( m = 0; m < n; m++ )
     {
-      Free_Anchor( &eer[n].EntryAnchor, memory );
-      Free_Anchor( &eer[n].ExitAnchor, memory );
+      Free_Anchor( &eer[m].EntryAnchor, memory );
+      Free_Anchor( &eer[m].ExitAnchor, memory );
     }
 
     FREE( eer );
     FT_Error  error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort        m, n, count;
+    FT_UShort        m, n, k, count;
     FT_ULong         cur_offset, new_offset, base_offset;
 
     TTO_BaseRecord*  br;
       for ( n = 0; n < num_classes; n++ )
       {
         if ( ACCESS_Frame( 2L ) )
-          goto Fail;
+          goto Fail0;
 
         new_offset = GET_UShort() + base_offset;
 
         cur_offset = FILE_Pos();
         if ( FILE_Seek( new_offset ) ||
              ( error = Load_Anchor( &ban[n], stream ) ) != TT_Err_Ok )
-          goto Fail;
+          goto Fail0;
         (void)FILE_Seek( cur_offset );
       }
+
+      continue;
+    Fail0:
+      for ( k = 0; k < n; k++ )
+        Free_Anchor( &ban[k], memory );
+      goto Fail;
     }
 
     return TT_Err_Ok;
 
   Fail:
-    for ( m = 0; m < count; m++ )
+    for ( k = 0; k < m; k++ )
     {
-      ban = br[m].BaseAnchor;
+      ban = br[k].BaseAnchor;
       
       for ( n = 0; n < num_classes; n++ )
         Free_Anchor( &ban[n], memory );
     FT_Error  error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort             m, n, count;
+    FT_UShort             m, n, k, count;
     FT_ULong              cur_offset, new_offset, base_offset;
 
     TTO_ComponentRecord*  cr;
       for ( n = 0; n < num_classes; n++ )
       {
         if ( ACCESS_Frame( 2L ) )
-          goto Fail;
+          goto Fail0;
 
         new_offset = GET_UShort();
 
           cur_offset = FILE_Pos();
           if ( FILE_Seek( new_offset ) ||
                ( error = Load_Anchor( &lan[n], stream ) ) != TT_Err_Ok )
-            goto Fail;
+            goto Fail0;
           (void)FILE_Seek( cur_offset );
         }
         else
           lan[n].PosFormat = 0;
       }
+
+      continue;
+    Fail0:
+      for ( k = 0; k < n; k++ )
+        Free_Anchor( &lan[k], memory );
+      goto Fail;
     }
 
     return TT_Err_Ok;
 
   Fail:
-    for ( m = 0; m < count; m++ )
+    for ( k = 0; k < m; k++ )
     {
-      lan = cr[m].LigatureAnchor;
+      lan = cr[k].LigatureAnchor;
       
       for ( n = 0; n < num_classes; n++ )
         Free_Anchor( &lan[n], memory );
     FT_Error  error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort            n, count;
+    FT_UShort            n, m, count;
     FT_ULong             cur_offset, new_offset, base_offset;
 
     TTO_LigatureAttach*  lat;
     return TT_Err_Ok;
 
   Fail:
-    for ( n = 0; n < count; n++ )
-      Free_LigatureAttach( &lat[n], num_classes, memory );
+    for ( m = 0; m < n; m++ )
+      Free_LigatureAttach( &lat[m], num_classes, memory );
 
     FREE( lat );
     return error;
     FT_Error  error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort         m, n, count;
+    FT_UShort         k, m, n, count;
     FT_ULong          cur_offset, new_offset, base_offset;
 
     TTO_Mark2Record*  m2r;
       for ( n = 0; n < num_classes; n++ )
       {
         if ( ACCESS_Frame( 2L ) )
-          goto Fail;
+          goto Fail0;
 
         new_offset = GET_UShort() + base_offset;
 
         cur_offset = FILE_Pos();
         if ( FILE_Seek( new_offset ) ||
              ( error = Load_Anchor( &m2an[n], stream ) ) != TT_Err_Ok )
-          goto Fail;
+          goto Fail0;
         (void)FILE_Seek( cur_offset );
       }
+
+      continue;
+    Fail0:
+      for ( k = 0; k < n; k++ )
+        Free_Anchor( &m2an[k], memory );
+      goto Fail;
     }
 
     return TT_Err_Ok;
 
   Fail:
-    for ( m = 0; m < count; m++ )
+    for ( k = 0; k < m; k++ )
     {
-      m2an = m2r[m].Mark2Anchor;
+      m2an = m2r[k].Mark2Anchor;
       
       for ( n = 0; n < num_classes; n++ )
         Free_Anchor( &m2an[n], memory );
     FT_Error  error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort     n, count;
+    FT_UShort     n, m, count;
     FT_ULong      cur_offset, new_offset, base_offset;
 
     TTO_PosRule*  pr;
     return TT_Err_Ok;
 
   Fail:
-    for ( n = 0; n < count; n++ )
-      Free_PosRule( &pr[n], memory );
+    for ( m = 0; m < n; m++ )
+      Free_PosRule( &pr[m], memory );
 
     FREE( pr );
     return error;
     FT_Error  error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort        n, count;
+    FT_UShort        n, m, count;
     FT_ULong         cur_offset, new_offset, base_offset;
 
     TTO_PosRuleSet*  prs;
     return TT_Err_Ok;
 
   Fail1:
-    for ( n = 0; n < count; n++ )
-      Free_PosRuleSet( &prs[n], memory );
+    for ( m = 0; m < n; m++ )
+      Free_PosRuleSet( &prs[m], memory );
 
     FREE( prs );
 
     FT_Error  error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort          n, count;
+    FT_UShort          n, m, count;
     FT_ULong           cur_offset, new_offset, base_offset;
 
     TTO_PosClassRule*  pcr;
     return TT_Err_Ok;
 
   Fail:
-    for ( n = 0; n < count; n++ )
-      Free_PosClassRule( &pcr[n], memory );
+    for ( m = 0; m < n; m++ )
+      Free_PosClassRule( &pcr[m], memory );
 
     FREE( pcr );
     return error;
     FT_Error  error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort         n, count;
+    FT_UShort         n, m, count;
     FT_ULong          cur_offset, new_offset, base_offset;
 
     TTO_PosClassSet*  pcs;
     return TT_Err_Ok;
 
   Fail1:
-    for ( n = 0; n < count; n++ )
-      Free_PosClassSet( &pcs[n], memory );
+    for ( m = 0; m < n; n++ )
+      Free_PosClassSet( &pcs[m], memory );
 
     FREE( pcs );
 
     FT_Error  error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort          n, count;
+    FT_UShort          n, m, count;
     FT_ULong           cur_offset, new_offset, base_offset;
 
     TTO_ChainPosRule*  cpr;
     return TT_Err_Ok;
 
   Fail:
-    for ( n = 0; n < count; n++ )
-      Free_ChainPosRule( &cpr[n], memory );
+    for ( m = 0; m < n; m++ )
+      Free_ChainPosRule( &cpr[m], memory );
 
     FREE( cpr );
     return error;
     FT_Error  error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort             n, count;
+    FT_UShort             n, m, count;
     FT_ULong              cur_offset, new_offset, base_offset;
 
     TTO_ChainPosRuleSet*  cprs;
     return TT_Err_Ok;
 
   Fail1:
-    for ( n = 0; n < count; n++ )
-      Free_ChainPosRuleSet( &cprs[n], memory );
+    for ( m = 0; m < n; m++ )
+      Free_ChainPosRuleSet( &cprs[m], memory );
 
     FREE( cprs );
 
     FT_Error  error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort               n, count;
+    FT_UShort               n, m, count;
     FT_ULong                cur_offset, new_offset, base_offset;
 
     TTO_ChainPosClassRule*  cpcr;
     return TT_Err_Ok;
 
   Fail:
-    for ( n = 0; n < count; n++ )
-      Free_ChainPosClassRule( &cpcr[n], memory );
+    for ( m = 0; m < n; m++ )
+      Free_ChainPosClassRule( &cpcr[m], memory );
 
     FREE( cpcr );
     return error;
   }
 
 
+  static FT_Error Load_EmptyOrClassDefinition( TTO_ClassDefinition*  cd,
+                                               FT_UShort             limit,
+                                              FT_ULong              class_offset,
+                                              FT_ULong              base_offset,
+                                              FT_Stream             stream )
+  {
+    FT_Error error;
+    FT_ULong               cur_offset;
+
+    cur_offset = FILE_Pos();
+
+    if ( class_offset )
+      {
+        if ( !FILE_Seek( class_offset + base_offset ) )
+          error = Load_ClassDefinition( cd, limit, stream ) == TT_Err_Ok;
+      }
+    else
+       error = Load_EmptyClassDefinition ( cd, stream );
+
+    (void)FILE_Seek( cur_offset );
+
+    return error;
+  }
+
   /* ChainContextPosFormat2 */
 
   static FT_Error  Load_ChainContextPos2( TTO_ChainContextPosFormat2*  ccpf2,
     FT_Error  error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort              n, count;
+    FT_UShort              n, m, count;
     FT_ULong               cur_offset, new_offset, base_offset;
     FT_ULong               backtrack_offset, input_offset, lookahead_offset;
 
     if ( ACCESS_Frame( 8L ) )
       goto Fail5;
 
-    backtrack_offset = GET_UShort() + base_offset;
-    input_offset     = GET_UShort() + base_offset;
-    lookahead_offset = GET_UShort() + base_offset;
+    backtrack_offset = GET_UShort();
+    input_offset     = GET_UShort();
+    lookahead_offset = GET_UShort();
 
     /* `ChainPosClassSetCount' is the upper limit for input class values,
        thus we read it now to make an additional safety check.            */
 
     FORGET_Frame();
 
-    cur_offset = FILE_Pos();
-    if ( FILE_Seek( backtrack_offset ) ||
-         ( error = Load_ClassDefinition( &ccpf2->BacktrackClassDef, count,
-                                         stream ) ) != TT_Err_Ok )
+    if ( ( error = Load_EmptyOrClassDefinition( &ccpf2->BacktrackClassDef, count,
+                                               backtrack_offset, base_offset,
+                                               stream ) ) != TT_Err_Ok )
       goto Fail5;
-    if ( FILE_Seek( input_offset ) ||
-         ( error = Load_ClassDefinition( &ccpf2->InputClassDef, count,
-                                         stream ) ) != TT_Err_Ok )
+    if ( ( error = Load_EmptyOrClassDefinition( &ccpf2->InputClassDef, count,
+                                               input_offset, base_offset,
+                                               stream ) ) != TT_Err_Ok )
       goto Fail4;
-    if ( FILE_Seek( lookahead_offset ) ||
-         ( error = Load_ClassDefinition( &ccpf2->LookaheadClassDef, count,
-                                         stream ) ) != TT_Err_Ok )
+    if ( ( error = Load_EmptyOrClassDefinition( &ccpf2->LookaheadClassDef, count,
+                                               lookahead_offset, base_offset,
+                                               stream ) ) != TT_Err_Ok )
       goto Fail3;
-    (void)FILE_Seek( cur_offset );
 
     ccpf2->ChainPosClassSet   = NULL;
     ccpf2->MaxBacktrackLength = 0;
     return TT_Err_Ok;
 
   Fail1:
-    for ( n = 0; n < count; n++ )
-      Free_ChainPosClassSet( &cpcs[n], memory );
+    for ( m = 0; m < n; m++ )
+      Free_ChainPosClassSet( &cpcs[m], memory );
 
     FREE( cpcs );
 
     FT_Error  error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort             n, count;
+    FT_UShort             n, nb, ni, nl, m, count;
     FT_UShort             backtrack_count, input_count, lookahead_count;
     FT_ULong              cur_offset, new_offset, base_offset;
 
 
     b = ccpf3->BacktrackCoverage;
 
-    for ( n = 0; n < backtrack_count; n++ )
+    for ( nb = 0; nb < backtrack_count; nb++ )
     {
       if ( ACCESS_Frame( 2L ) )
         goto Fail4;
 
       cur_offset = FILE_Pos();
       if ( FILE_Seek( new_offset ) ||
-           ( error = Load_Coverage( &b[n], stream ) ) != TT_Err_Ok )
+           ( error = Load_Coverage( &b[nb], stream ) ) != TT_Err_Ok )
         goto Fail4;
       (void)FILE_Seek( cur_offset );
     }
 
     i = ccpf3->InputCoverage;
 
-    for ( n = 0; n < input_count; n++ )
+    for ( ni = 0; ni < input_count; ni++ )
     {
       if ( ACCESS_Frame( 2L ) )
         goto Fail3;
 
       cur_offset = FILE_Pos();
       if ( FILE_Seek( new_offset ) ||
-           ( error = Load_Coverage( &i[n], stream ) ) != TT_Err_Ok )
+           ( error = Load_Coverage( &i[ni], stream ) ) != TT_Err_Ok )
         goto Fail3;
       (void)FILE_Seek( cur_offset );
     }
 
     l = ccpf3->LookaheadCoverage;
 
-    for ( n = 0; n < lookahead_count; n++ )
+    for ( nl = 0; nl < lookahead_count; nl++ )
     {
       if ( ACCESS_Frame( 2L ) )
         goto Fail2;
 
       cur_offset = FILE_Pos();
       if ( FILE_Seek( new_offset ) ||
-           ( error = Load_Coverage( &l[n], stream ) ) != TT_Err_Ok )
+           ( error = Load_Coverage( &l[nl], stream ) ) != TT_Err_Ok )
         goto Fail2;
       (void)FILE_Seek( cur_offset );
     }
     FREE( plr );
 
   Fail2:
-    for ( n = 0; n < lookahead_count; n++ )
-      Free_Coverage( &l[n], memory );
+    for ( m = 0; m < nl; nl++ )
+      Free_Coverage( &l[m], memory );
 
     FREE( l );
 
   Fail3:
-    for ( n = 0; n < input_count; n++ )
-      Free_Coverage( &i[n], memory );
+    for ( m = 0; m < ni; n++ )
+      Free_Coverage( &i[m], memory );
 
     FREE( i );
 
   Fail4:
-    for ( n = 0; n < backtrack_count; n++ )
-      Free_Coverage( &b[n], memory );
+    for ( m = 0; m < nb; n++ )
+      Free_Coverage( &b[m], memory );
 
     FREE( b );
     return error;
index b1f516c..6cdf3bd 100644 (file)
     FT_Error error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort      n, count;
+    FT_UShort      n = 0, m, count;
     FT_ULong       cur_offset, new_offset, base_offset;
 
     TTO_Sequence*  s;
     return TT_Err_Ok;
 
   Fail1:
-    for ( n = 0; n < count; n++ )
-      Free_Sequence( &s[n], memory );
+    for ( m = 0; m < n; m++ )
+      Free_Sequence( &s[m], memory );
 
     FREE( s );
 
     FT_Error error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort          n, count;
+    FT_UShort          n = 0, m, count;
     FT_ULong           cur_offset, new_offset, base_offset;
 
     TTO_AlternateSet*  aset;
     return TT_Err_Ok;
 
   Fail1:
-    for ( n = 0; n < count; n++ )
-      Free_AlternateSet( &aset[n], memory );
+    for ( m = 0; m < n; m++ )
+      Free_AlternateSet( &aset[m], memory );
 
     FREE( aset );
 
     FT_Error error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort      n, count;
+    FT_UShort      n = 0, m, count;
     FT_ULong       cur_offset, new_offset, base_offset;
 
     TTO_Ligature*  l;
     return TT_Err_Ok;
 
   Fail:
-    for ( n = 0; n < count; n++ )
-      Free_Ligature( &l[n], memory );
+    for ( m = 0; m < n; m++ )
+      Free_Ligature( &l[m], memory );
 
     FREE( l );
     return error;
     FT_Error error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort         n, count;
+    FT_UShort         n = 0, m, count;
     FT_ULong          cur_offset, new_offset, base_offset;
 
     TTO_LigatureSet*  lset;
     return TT_Err_Ok;
 
   Fail1:
-    for ( n = 0; n < count; n++ )
-      Free_LigatureSet( &lset[n], memory );
+    for ( m = 0; m < n; m++ )
+      Free_LigatureSet( &lset[m], memory );
 
     FREE( lset );
 
     FT_Error error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort     n, count;
+    FT_UShort     n = 0, m, count;
     FT_ULong      cur_offset, new_offset, base_offset;
 
     TTO_SubRule*  sr;
     return TT_Err_Ok;
 
   Fail:
-    for ( n = 0; n < count; n++ )
-      Free_SubRule( &sr[n], memory );
+    for ( m = 0; m < n; m++ )
+      Free_SubRule( &sr[m], memory );
 
     FREE( sr );
     return error;
     FT_Error error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort        n, count;
+    FT_UShort        n = 0, m, count;
     FT_ULong         cur_offset, new_offset, base_offset;
 
     TTO_SubRuleSet*  srs;
     return TT_Err_Ok;
 
   Fail1:
-    for ( n = 0; n < count; n++ )
-      Free_SubRuleSet( &srs[n], memory );
+    for ( m = 0; m < n; m++ )
+      Free_SubRuleSet( &srs[m], memory );
 
     FREE( srs );
 
     FT_Error error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort          n, count;
+    FT_UShort          n = 0, m, count;
     FT_ULong           cur_offset, new_offset, base_offset;
 
     TTO_SubClassRule*  scr;
     return TT_Err_Ok;
 
   Fail:
-    for ( n = 0; n < count; n++ )
-      Free_SubClassRule( &scr[n], memory );
+    for ( m = 0; m < n; m++ )
+      Free_SubClassRule( &scr[m], memory );
 
     FREE( scr );
     return error;
     FT_Error error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort         n, count;
+    FT_UShort         n = 0, m, count;
     FT_ULong          cur_offset, new_offset, base_offset;
 
     TTO_SubClassSet*  scs;
     return TT_Err_Ok;
 
   Fail1:
-    for ( n = 0; n < count; n++ )
-      Free_SubClassSet( &scs[n], memory );
+    for ( m = 0; m < n; m++ )
+      Free_SubClassSet( &scs[m], memory );
 
     FREE( scs );
 
     FT_Error error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort               n, count;
+    FT_UShort               n = 0, m, count;
     FT_ULong                cur_offset, new_offset, base_offset;
 
     TTO_Coverage*           c;
     FREE( slr );
 
   Fail2:
-    for ( n = 0; n < count; n++ )
-      Free_Coverage( &c[n], memory );
+    for ( m = 0; m < n; m++ )
+      Free_Coverage( &c[m], memory );
 
     FREE( c );
     return error;
     FT_Error error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort          n, count;
+    FT_UShort          n = 0, m, count;
     FT_ULong           cur_offset, new_offset, base_offset;
 
     TTO_ChainSubRule*  csr;
     return TT_Err_Ok;
 
   Fail:
-    for ( n = 0; n < count; n++ )
-      Free_ChainSubRule( &csr[n], memory );
+    for ( m = 0; m < n; m++ )
+      Free_ChainSubRule( &csr[m], memory );
 
     FREE( csr );
     return error;
     FT_Error error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort             n, count;
+    FT_UShort             n = 0, m, count;
     FT_ULong              cur_offset, new_offset, base_offset;
 
     TTO_ChainSubRuleSet*  csrs;
     return TT_Err_Ok;
 
   Fail1:
-    for ( n = 0; n < count; n++ )
-      Free_ChainSubRuleSet( &csrs[n], memory );
+    for ( m = 0; m < n; m++ )
+      Free_ChainSubRuleSet( &csrs[m], memory );
 
     FREE( csrs );
 
     FT_Error error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort               n, count;
+    FT_UShort               n = 0, m, count;
     FT_ULong                cur_offset, new_offset, base_offset;
 
     TTO_ChainSubClassRule*  cscr;
     return TT_Err_Ok;
 
   Fail:
-    for ( n = 0; n < count; n++ )
-      Free_ChainSubClassRule( &cscr[n], memory );
+    for ( m = 0; m < n; m++ )
+      Free_ChainSubClassRule( &cscr[m], memory );
 
     FREE( cscr );
     return error;
     }
   }
 
+  static FT_Error Load_EmptyOrClassDefinition( TTO_ClassDefinition*  cd,
+                                               FT_UShort             limit,
+                                              FT_ULong              class_offset,
+                                              FT_ULong              base_offset,
+                                              FT_Stream             stream )
+  {
+    FT_Error error;
+    FT_ULong               cur_offset;
+
+    cur_offset = FILE_Pos();
+
+    if ( class_offset )
+      {
+        if ( !FILE_Seek( class_offset + base_offset ) )
+          error = Load_ClassDefinition( cd, limit, stream ) == TT_Err_Ok;
+      }
+    else
+       error = Load_EmptyClassDefinition ( cd, stream );
+
+    (void)FILE_Seek( cur_offset );
+
+    return error;
+  }
+
 
   /* ChainContextSubstFormat2 */
 
     FT_Error error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort              n, count;
+    FT_UShort              n = 0, m, count;
     FT_ULong               cur_offset, new_offset, base_offset;
     FT_ULong               backtrack_offset, input_offset, lookahead_offset;
 
     if ( ACCESS_Frame( 8L ) )
       goto Fail5;
 
-    backtrack_offset = GET_UShort() + base_offset;
-    input_offset     = GET_UShort() + base_offset;
-    lookahead_offset = GET_UShort() + base_offset;
+    backtrack_offset = GET_UShort();
+    input_offset     = GET_UShort();
+    lookahead_offset = GET_UShort();
 
     /* `ChainSubClassSetCount' is the upper limit for input class values,
        thus we read it now to make an additional safety check.            */
 
     FORGET_Frame();
 
-    cur_offset = FILE_Pos();
-    if ( FILE_Seek( backtrack_offset ) ||
-         ( error = Load_ClassDefinition( &ccsf2->BacktrackClassDef, count,
-                                         stream ) ) != TT_Err_Ok )
-      goto Fail5;
-    if ( FILE_Seek( input_offset ) ||
-         ( error = Load_ClassDefinition( &ccsf2->InputClassDef, count,
-                                         stream ) ) != TT_Err_Ok )
-      goto Fail4;
-    if ( FILE_Seek( lookahead_offset ) ||
-         ( error = Load_ClassDefinition( &ccsf2->LookaheadClassDef, count,
-                                         stream ) ) != TT_Err_Ok )
+    if ( ( error = Load_EmptyOrClassDefinition( &ccsf2->BacktrackClassDef, count,
+                                                backtrack_offset, base_offset,
+                                               stream ) ) != TT_Err_Ok )
+        goto Fail5;
+              
+    if ( ( error = Load_EmptyOrClassDefinition( &ccsf2->InputClassDef, count,
+                                                input_offset, base_offset,
+                                                stream ) ) != TT_Err_Ok )
+        goto Fail4;
+    if ( ( error = Load_EmptyOrClassDefinition( &ccsf2->LookaheadClassDef, count,
+                                                lookahead_offset, base_offset,
+                                                stream ) ) != TT_Err_Ok )
       goto Fail3;
-    (void)FILE_Seek( cur_offset );
 
     ccsf2->ChainSubClassSet   = NULL;
     ccsf2->MaxBacktrackLength = 0;
     return TT_Err_Ok;
 
   Fail1:
-    for ( n = 0; n < count; n++ )
-      Free_ChainSubClassSet( &cscs[n], memory );
+    for ( m = 0; m < n; m++ )
+      Free_ChainSubClassSet( &cscs[m], memory );
 
     FREE( cscs );
 
     FT_Error error;
     FT_Memory memory = stream->memory;
 
-    FT_UShort               n, count;
+    FT_UShort               n, nb = 0, ni =0, nl = 0, m, count;
     FT_UShort               backtrack_count, input_count, lookahead_count;
     FT_ULong                cur_offset, new_offset, base_offset;
 
 
     b = ccsf3->BacktrackCoverage;
 
-    for ( n = 0; n < backtrack_count; n++ )
+    for ( nb = 0; nb < backtrack_count; nb++ )
     {
       if ( ACCESS_Frame( 2L ) )
         goto Fail4;
 
       cur_offset = FILE_Pos();
       if ( FILE_Seek( new_offset ) ||
-           ( error = Load_Coverage( &b[n], stream ) ) != TT_Err_Ok )
+           ( error = Load_Coverage( &b[nb], stream ) ) != TT_Err_Ok )
         goto Fail4;
       (void)FILE_Seek( cur_offset );
     }
 
     i = ccsf3->InputCoverage;
 
-    for ( n = 0; n < input_count; n++ )
+    for ( ni = 0; ni < input_count; ni++ )
     {
       if ( ACCESS_Frame( 2L ) )
         goto Fail3;
 
       cur_offset = FILE_Pos();
       if ( FILE_Seek( new_offset ) ||
-           ( error = Load_Coverage( &i[n], stream ) ) != TT_Err_Ok )
+           ( error = Load_Coverage( &i[ni], stream ) ) != TT_Err_Ok )
         goto Fail3;
       (void)FILE_Seek( cur_offset );
     }
 
     l = ccsf3->LookaheadCoverage;
 
-    for ( n = 0; n < lookahead_count; n++ )
+    for ( nl = 0; nl < lookahead_count; nl++ )
     {
       if ( ACCESS_Frame( 2L ) )
         goto Fail2;
 
       cur_offset = FILE_Pos();
       if ( FILE_Seek( new_offset ) ||
-           ( error = Load_Coverage( &l[n], stream ) ) != TT_Err_Ok )
+           ( error = Load_Coverage( &l[nl], stream ) ) != TT_Err_Ok )
         goto Fail2;
       (void)FILE_Seek( cur_offset );
     }
     FREE( slr );
 
   Fail2:
-    for ( n = 0; n < lookahead_count; n++ )
-      Free_Coverage( &l[n], memory );
+    for ( m = 0; m < nl; m++ )
+      Free_Coverage( &l[m], memory );
 
     FREE( l );
 
   Fail3:
-    for ( n = 0; n < input_count; n++ )
-      Free_Coverage( &i[n], memory );
+    for ( m = 0; m < ni; m++ )
+      Free_Coverage( &i[m], memory );
 
     FREE( i );
 
   Fail4:
-    for ( n = 0; n < backtrack_count; n++ )
-      Free_Coverage( &b[n], memory );
+    for ( m = 0; m < nb; m++ )
+      Free_Coverage( &b[m], memory );
 
     FREE( b );
     return error;
index 3f252b1..c721eec 100644 (file)
@@ -86,7 +86,7 @@
   {
     FT_Error   error;
     FT_Memory  memory = stream->memory;
-    FT_UShort  n, count;
+    FT_UShort  n, m, count;
     FT_ULong   cur_offset, new_offset, base_offset;
 
     TTO_LangSysRecord*  lsr;
     return TT_Err_Ok;
 
   Fail1:
-    for ( n = 0; n < count; n++ )
-      Free_LangSys( &lsr[n].LangSys, memory );
+    for ( m = 0; m < n; m++ )
+      Free_LangSys( &lsr[m].LangSys, memory );
 
     FREE( s->LangSysRecord );
 
     FT_Error   error;
     FT_Memory  memory = stream->memory;
 
-    FT_UShort          n, count;
+    FT_UShort          n, m, count;
     FT_ULong           cur_offset, new_offset, base_offset;
 
     TTO_ScriptRecord*  sr;
     return TT_Err_Ok;
 
   Fail:
-    for ( n = 0; n < count; n++ )
-      Free_Script( &sr[n].Script, memory );
+    for ( m = 0; m < n; m++ )
+      Free_Script( &sr[m].Script, memory );
 
     FREE( sl->ScriptRecord );
     return error;
     FT_Error   error;
     FT_Memory  memory = stream->memory;
 
-    FT_UShort           n, count;
+    FT_UShort           n, m, count;
     FT_ULong            cur_offset, new_offset, base_offset;
 
     TTO_FeatureRecord*  fr;
     return TT_Err_Ok;
 
   Fail:
-    for ( n = 0; n < count; n++ )
-      Free_Feature( &fr[n].Feature, memory );
+    for ( m = 0; m < n; m++ )
+      Free_Feature( &fr[m].Feature, memory );
 
     FREE( fl->FeatureRecord );
     return error;
     FT_Error   error;
     FT_Memory  memory = stream->memory;
 
-    FT_UShort      n, count;
+    FT_UShort      n, m, count;
     FT_ULong       cur_offset, new_offset, base_offset;
 
     TTO_SubTable*  st;
     return TT_Err_Ok;
 
   Fail:
-    for ( n = 0; n < count; n++ )
-      Free_SubTable( &st[n], type, l->LookupType, memory );
+    for ( m = 0; m < n; m++ )
+      Free_SubTable( &st[m], type, l->LookupType, memory );
 
     FREE( l->SubTable );
     return error;
     FT_Error   error;
     FT_Memory  memory = stream->memory;
 
-    FT_UShort    n, count;
+    FT_UShort    n, m, count;
     FT_ULong     cur_offset, new_offset, base_offset;
 
     TTO_Lookup*  l;
   Fail1:
     FREE( ll->Properties );
 
-    for ( n = 0; n < count; n++ )
-      Free_Lookup( &l[n], type, memory );
+    for ( m = 0; m < n; m++ )
+      Free_Lookup( &l[m], type, memory );
 
   Fail2:
     FREE( ll->Lookup );
   }
 
 
+  FT_Error  Load_EmptyClassDefinition( TTO_ClassDefinition*  cd,
+                                      FT_Stream             stream )
+  {
+    FT_Error   error;
+    FT_Memory  memory = stream->memory;
+
+
+    if ( ALLOC_ARRAY( cd->Defined, 1, FT_Bool ) )
+      return error;
+
+    cd->ClassFormat = 1; /* Meaningless */
+    cd->Defined[0] = FALSE;
+
+    if ( ALLOC_ARRAY( cd->cd.cd1.ClassValueArray, 1, FT_UShort ) )
+      goto Fail;
+
+    return TT_Err_Ok;
+
+  Fail:
+    FREE( cd->Defined );
+    return error;
+  }
+
   void  Free_ClassDefinition( TTO_ClassDefinition*  cd,
                              FT_Memory             memory )
   {
index bbb2c85..0c4db8b 100644 (file)
@@ -39,6 +39,8 @@ extern "C" {
   FT_Error  Load_ClassDefinition( TTO_ClassDefinition*  cd,
                                   FT_UShort             limit,
                                   FT_Stream             input );
+  FT_Error  Load_EmptyClassDefinition( TTO_ClassDefinition*  cd,
+                                       FT_Stream             input );
   FT_Error  Load_Device( TTO_Device*  d,
                          FT_Stream    input );