Commit de94e2cbfbbb65ad2242023b056a52a5427af9fc

Alexei Podtelezhnikov 2023-02-26T08:07:08

[truetype] Simplify memory management. Instead of using `Update_Max`, switch to regular FreeType memory allocation macros, stop pre-allocating the glyph instruction arrays. * src/truetype/ttgload.c (TT_Load_Simple_Glyph, TT_Process_Composite_Glyph): Switch to regular memory allocation. * src/truetype/ttinterp.c (Update_Max): Removed. (TT_Load_Context): Reallocate stack and free old instructions. (Modify_CVT_Check, Ins_WS): Switch to regular memory allocation. * src/truetype/ttinterp.h (Update_Max): Removed.

diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index d33bdad..52f8ea8 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -437,7 +437,8 @@
 
     if ( IS_HINTED( load->load_flags ) )
     {
-      FT_ULong  tmp;
+      TT_ExecContext  exec = load->exec;
+      FT_Memory       memory = exec->memory;
 
 
       /* check instructions size */
@@ -449,24 +450,19 @@
       }
 
       /* we don't trust `maxSizeOfInstructions' in the `maxp' table */
-      /* and thus update the bytecode array size by ourselves       */
+      /* and thus allocate the bytecode array size by ourselves     */
+      if ( n_ins )
+      {
+        if ( FT_QNEW_ARRAY( exec->glyphIns, n_ins ) )
+          return error;
 
-      tmp   = load->exec->glyphSize;
-      error = Update_Max( load->exec->memory,
-                          &tmp,
-                          sizeof ( FT_Byte ),
-                          (void*)&load->exec->glyphIns,
-                          n_ins );
+        FT_MEM_COPY( exec->glyphIns, p, (FT_Long)n_ins );
 
-      load->exec->glyphSize = (FT_UInt)tmp;
-      if ( error )
-        return error;
-
-      load->glyph->control_len  = n_ins;
-      load->glyph->control_data = load->exec->glyphIns;
+        exec->glyphSize  = n_ins;
 
-      if ( n_ins )
-        FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins );
+        load->glyph->control_len  = n_ins;
+        load->glyph->control_data = exec->glyphIns;
+      }
     }
 
 #endif /* TT_USE_BYTECODE_INTERPRETER */
@@ -1331,12 +1327,12 @@
                               FT_UInt    start_contour )
   {
     FT_Error     error;
-    FT_Outline*  outline;
+    FT_Outline*  outline = &loader->gloader->base.outline;
+    FT_Stream    stream = loader->stream;
+    FT_UShort    n_ins;
     FT_UInt      i;
 
 
-    outline = &loader->gloader->base.outline;
-
     /* make room for phantom points */
     error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader,
                                          outline->n_points + 4,
@@ -1351,53 +1347,40 @@
 
 #ifdef TT_USE_BYTECODE_INTERPRETER
 
-    {
-      FT_Stream  stream = loader->stream;
-      FT_UShort  n_ins, max_ins;
-      FT_ULong   tmp;
+    /* TT_Load_Composite_Glyph only gives us the offset of instructions */
+    /* so we read them here                                             */
+    if ( FT_STREAM_SEEK( loader->ins_pos ) ||
+         FT_READ_USHORT( n_ins )           )
+      return error;
 
+    FT_TRACE5(( "  Instructions size = %hu\n", n_ins ));
 
-      /* TT_Load_Composite_Glyph only gives us the offset of instructions */
-      /* so we read them here                                             */
-      if ( FT_STREAM_SEEK( loader->ins_pos ) ||
-           FT_READ_USHORT( n_ins )           )
-        return error;
+    if ( !n_ins )
+      return FT_Err_Ok;
 
-      FT_TRACE5(( "  Instructions size = %hu\n", n_ins ));
-
-      /* check it */
-      max_ins = loader->face->max_profile.maxSizeOfInstructions;
-      if ( n_ins > max_ins )
-      {
-        /* don't trust `maxSizeOfInstructions'; */
-        /* only do a rough safety check         */
-        if ( n_ins > loader->byte_len )
-        {
-          FT_TRACE1(( "TT_Process_Composite_Glyph:"
-                      " too many instructions (%hu) for glyph with length %u\n",
-                      n_ins, loader->byte_len ));
-          return FT_THROW( Too_Many_Hints );
-        }
+    /* don't trust `maxSizeOfInstructions'; */
+    /* only do a rough safety check         */
+    if ( n_ins > loader->byte_len )
+    {
+      FT_TRACE1(( "TT_Process_Composite_Glyph:"
+                  " too many instructions (%hu) for glyph with length %u\n",
+                  n_ins, loader->byte_len ));
+      return FT_THROW( Too_Many_Hints );
+    }
 
-        tmp   = loader->exec->glyphSize;
-        error = Update_Max( loader->exec->memory,
-                            &tmp,
-                            sizeof ( FT_Byte ),
-                            (void*)&loader->exec->glyphIns,
-                            n_ins );
+    {
+      TT_ExecContext  exec = loader->exec;
+      FT_Memory       memory = exec->memory;
 
-        loader->exec->glyphSize = (FT_UShort)tmp;
-        if ( error )
-          return error;
-      }
-      else if ( n_ins == 0 )
-        return FT_Err_Ok;
 
-      if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) )
+      if ( FT_QNEW_ARRAY( exec->glyphIns, n_ins )  ||
+           FT_STREAM_READ( exec->glyphIns, n_ins ) )
         return error;
 
-      loader->glyph->control_data = loader->exec->glyphIns;
+      exec->glyphSize = n_ins;
+
       loader->glyph->control_len  = n_ins;
+      loader->glyph->control_data = exec->glyphIns;
     }
 
 #endif
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index 69d0100..8cf66eb 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -278,57 +278,6 @@
   /**************************************************************************
    *
    * @Function:
-   *   Update_Max
-   *
-   * @Description:
-   *   Checks the size of a buffer and reallocates it if necessary.
-   *
-   * @Input:
-   *   memory ::
-   *     A handle to the parent memory object.
-   *
-   *   multiplier ::
-   *     The size in bytes of each element in the buffer.
-   *
-   *   new_max ::
-   *     The new capacity (size) of the buffer.
-   *
-   * @InOut:
-   *   size ::
-   *     The address of the buffer's current size expressed
-   *     in elements.
-   *
-   *   buff ::
-   *     The address of the buffer base pointer.
-   *
-   * @Return:
-   *   FreeType error code.  0 means success.
-   */
-  FT_LOCAL_DEF( FT_Error )
-  Update_Max( FT_Memory  memory,
-              FT_ULong*  size,
-              FT_ULong   multiplier,
-              void*      _pbuff,
-              FT_ULong   new_max )
-  {
-    FT_Error  error;
-    void**    pbuff = (void**)_pbuff;
-
-
-    if ( *size < new_max )
-    {
-      if ( FT_QREALLOC( *pbuff, *size * multiplier, new_max * multiplier ) )
-        return error;
-      *size = new_max;
-    }
-
-    return FT_Err_Ok;
-  }
-
-
-  /**************************************************************************
-   *
-   * @Function:
    *   TT_Load_Context
    *
    * @Description:
@@ -359,9 +308,9 @@
                    TT_Size         size )
   {
     FT_Int          i;
-    FT_ULong        tmp;
     TT_MaxProfile*  maxp;
     FT_Error        error;
+    FT_Memory       memory = exec->memory;
 
 
     exec->face = face;
@@ -406,25 +355,15 @@
 
     /* XXX: We reserve a little more elements on the stack to deal safely */
     /*      with broken fonts like arialbs, courbs, timesbs, etc.         */
-    tmp = (FT_ULong)exec->stackSize;
-    error = Update_Max( exec->memory,
-                        &tmp,
-                        sizeof ( FT_F26Dot6 ),
-                        (void*)&exec->stack,
-                        maxp->maxStackElements + 32 );
-    exec->stackSize = (FT_Long)tmp;
-    if ( error )
+    if ( FT_QRENEW_ARRAY( exec->stack,
+                          exec->stackSize,
+                          maxp->maxStackElements + 32 ) )
       return error;
+    exec->stackSize = maxp->maxStackElements + 32;
 
-    tmp = (FT_ULong)exec->glyphSize;
-    error = Update_Max( exec->memory,
-                        &tmp,
-                        sizeof ( FT_Byte ),
-                        (void*)&exec->glyphIns,
-                        maxp->maxSizeOfInstructions );
-    exec->glyphSize = (FT_UInt)tmp;
-    if ( error )
-      return error;
+    /* free previous glyph code range */
+    FT_FREE( exec->glyphIns );
+    exec->glyphSize = 0;
 
     exec->pts.n_points   = 0;
     exec->pts.n_contours = 0;
@@ -1530,14 +1469,16 @@
     if ( exc->iniRange == tt_coderange_glyph &&
          exc->cvt != exc->glyfCvt            )
     {
-      exc->error = Update_Max( exc->memory,
-                               &exc->glyfCvtSize,
-                               sizeof ( FT_Long ),
-                               (void*)&exc->glyfCvt,
-                               exc->cvtSize );
-      if ( exc->error )
+      FT_Memory  memory = exc->memory;
+      FT_Error   error;
+
+
+      FT_MEM_QRENEW_ARRAY( exc->glyfCvt, exc->glyfCvtSize, exc->cvtSize );
+      exc->error = error;
+      if ( error )
         return;
 
+      exc->glyfCvtSize = exc->cvtSize;
       FT_ARRAY_COPY( exc->glyfCvt, exc->cvt, exc->glyfCvtSize );
       exc->cvt = exc->glyfCvt;
     }
@@ -3117,18 +3058,18 @@
       if ( exc->iniRange == tt_coderange_glyph &&
            exc->storage != exc->glyfStorage    )
       {
-        FT_ULong  tmp = (FT_ULong)exc->glyfStoreSize;
+        FT_Memory  memory = exc->memory;
+        FT_Error   error;
 
 
-        exc->error = Update_Max( exc->memory,
-                                 &tmp,
-                                 sizeof ( FT_Long ),
-                                 (void*)&exc->glyfStorage,
-                                 exc->storeSize );
-        exc->glyfStoreSize = (FT_UShort)tmp;
-        if ( exc->error )
+        FT_MEM_QRENEW_ARRAY( exc->glyfStorage,
+                             exc->glyfStoreSize,
+                             exc->storeSize );
+        exc->error  = error;
+        if ( error )
           return;
 
+        exc->glyfStoreSize = exc->storeSize;
         FT_ARRAY_COPY( exc->glyfStorage, exc->storage, exc->glyfStoreSize );
         exc->storage = exc->glyfStorage;
       }
diff --git a/src/truetype/ttinterp.h b/src/truetype/ttinterp.h
index c54c053..891e212 100644
--- a/src/truetype/ttinterp.h
+++ b/src/truetype/ttinterp.h
@@ -460,14 +460,6 @@ FT_BEGIN_HEADER
   FT_LOCAL( void )
   TT_Clear_CodeRange( TT_ExecContext  exec,
                       FT_Int          range );
-
-
-  FT_LOCAL( FT_Error )
-  Update_Max( FT_Memory  memory,
-              FT_ULong*  size,
-              FT_ULong   multiplier,
-              void*      _pbuff,
-              FT_ULong   new_max );
 #endif /* TT_USE_BYTECODE_INTERPRETER */