Commit ebcc96e559257756478bb93304fbd973857c4c90

Anuj Verma 2021-08-02T08:40:43

Fix invalid memory access in `bsdf` rasterizer. Do not generate SDF from bitmap if the `FT_GLYPH_OWN_BITMAP` flag is not set. In some cases the bitmap buffer is freed but still points to a valid address; to handle those cases check the flag before accessing the memory. * src/sdf/ftsdfrend.c (ft_bsdf_render): Handle the above case. Also, return an error message if the bitmap's rows/pitch is invalid, otherwise `slot->buffer` might be assigned to some invalid memory location. (ft_sdf_render): Same as above. Plus, move the outline back to original state after rasterization and not if any error occurs. Signed-off-by: Anuj Verma <anujv@iitbhilai.ac.in>

diff --git a/src/sdf/ftsdfrend.c b/src/sdf/ftsdfrend.c
index 420ad49..30f2e62 100644
--- a/src/sdf/ftsdfrend.c
+++ b/src/sdf/ftsdfrend.c
@@ -298,8 +298,15 @@
       goto Exit;
     }
 
+    /* the rows and pitch must be valid after presetting the */
+    /* bitmap using outline                                  */
     if ( !bitmap->rows || !bitmap->pitch )
+    {
+      FT_ERROR(( "ft_sdf_render: failed to preset bitmap\n" ));
+
+      error = FT_THROW( Cannot_Render_Glyph );
       goto Exit;
+    }
 
     /* the padding will simply be equal to the `spread' */
     x_pad = sdf_module->spread;
@@ -350,6 +357,10 @@
     error = render->raster_render( render->raster,
                                    (const FT_Raster_Params*)&params );
 
+    /* transform the outline back to the original state */
+    if ( x_shift || y_shift )
+      FT_Outline_Translate( outline, -x_shift, -y_shift );
+
   Exit:
     if ( !error )
     {
@@ -362,9 +373,6 @@
       slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
     }
 
-    if ( x_shift || y_shift )
-      FT_Outline_Translate( outline, -x_shift, -y_shift );
-
     return error;
   }
 
@@ -506,8 +514,24 @@
       goto Exit;
     }
 
+    /* Do not generate SDF if the bitmap is not owned by the       */
+    /* glyph: it might be that the source buffer is already freed. */
+    if ( !( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
+    {
+      FT_ERROR(( "ft_bsdf_render: can't generate SDF from"
+                 " unowned source bitmap\n" ));
+
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
     if ( !bitmap->rows || !bitmap->pitch )
+    {
+      FT_ERROR(( "ft_bsdf_render: invalid bitmap size\n" ));
+
+      error = FT_THROW( Invalid_Argument );
       goto Exit;
+    }
 
     FT_Bitmap_New( &target );