Merge "Merge Android 13 QPR2"
diff --git a/src/sfnt/ttcolr.c b/src/sfnt/ttcolr.c
index 8f5cc8b..ec972a8 100644
--- a/src/sfnt/ttcolr.c
+++ b/src/sfnt/ttcolr.c
@@ -49,6 +49,11 @@
 #define LAYER_SIZE                        4U
 #define COLR_HEADER_SIZE                 14U
 
+#define ENSURE_READ_BYTES( byte_size )                             \
+  if ( p < colr->paints_start_v1                                || \
+       p > (FT_Byte*)colr->table + colr->table_size - byte_size )  \
+    return 0;
+
 
   typedef enum  FT_PaintFormat_Internal_
   {
@@ -372,13 +377,16 @@
 
 
   static FT_Bool
-  read_color_line( FT_Byte*      color_line_p,
-                   FT_ColorLine  *colorline )
+  read_color_line( Colr*          colr,
+                   FT_Byte*       color_line_p,
+                   FT_ColorLine*  colorline)
   {
     FT_Byte*        p = color_line_p;
     FT_PaintExtend  paint_extend;
 
 
+    ENSURE_READ_BYTES( 3 );
+
     paint_extend = (FT_PaintExtend)FT_NEXT_BYTE( p );
     if ( paint_extend > FT_COLR_PAINT_EXTEND_REFLECT )
       return 0;
@@ -477,6 +485,7 @@
 
     else if ( apaint->format == FT_COLR_PAINTFORMAT_SOLID )
     {
+      ENSURE_READ_BYTES( 4 );
       apaint->u.solid.color.palette_index = FT_NEXT_USHORT( p );
       apaint->u.solid.color.alpha         = FT_NEXT_SHORT( p );
 
@@ -485,6 +494,7 @@
 
     else if ( apaint->format == FT_COLR_PAINTFORMAT_COLR_GLYPH )
     {
+      ENSURE_READ_BYTES(2);
       apaint->u.colr_glyph.glyphID = FT_NEXT_USHORT( p );
 
       return 1;
@@ -502,14 +512,16 @@
 
     if ( apaint->format == FT_COLR_PAINTFORMAT_LINEAR_GRADIENT )
     {
-      if ( !read_color_line( child_table_p,
-                             &apaint->u.linear_gradient.colorline ) )
+      if ( !read_color_line( colr,
+                             child_table_p,
+                             &apaint->u.linear_gradient.colorline) )
         return 0;
 
       /*
        * In order to support variations expose these as FT_Fixed 16.16 values so
        * that we can support fractional values after interpolation.
        */
+      ENSURE_READ_BYTES( 12 );
       apaint->u.linear_gradient.p0.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
       apaint->u.linear_gradient.p0.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
       apaint->u.linear_gradient.p1.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
@@ -522,10 +534,21 @@
 
     else if ( apaint->format == FT_COLR_PAINTFORMAT_RADIAL_GRADIENT )
     {
-      if ( !read_color_line( child_table_p,
-                             &apaint->u.radial_gradient.colorline ) )
+      FT_Pos  tmp;
+
+
+      if ( !read_color_line( colr,
+                             child_table_p,
+                             &apaint->u.radial_gradient.colorline) )
         return 0;
 
+      /* In the OpenType specification, `r0` and `r1` are defined as   */
+      /* `UFWORD`.  Since FreeType doesn't have a corresponding 16.16  */
+      /* format we convert to `FWORD` and replace negative values with */
+      /* (32bit) `FT_INT_MAX`.                                         */
+
+      ENSURE_READ_BYTES( 12 );
+
       apaint->u.radial_gradient.c0.x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
       apaint->u.radial_gradient.c0.y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
 
@@ -541,10 +564,13 @@
 
     else if ( apaint->format == FT_COLR_PAINTFORMAT_SWEEP_GRADIENT )
     {
-      if ( !read_color_line( child_table_p,
-                             &apaint->u.sweep_gradient.colorline ) )
+      if ( !read_color_line( colr,
+                             child_table_p,
+                             &apaint->u.sweep_gradient.colorline) )
         return 0;
 
+      ENSURE_READ_BYTES( 8 );
+
       apaint->u.sweep_gradient.center.x =
           INT_TO_FIXED( FT_NEXT_SHORT( p ) );
       apaint->u.sweep_gradient.center.y =
@@ -560,6 +586,7 @@
 
     if ( apaint->format == FT_COLR_PAINTFORMAT_GLYPH )
     {
+      ENSURE_READ_BYTES( 2 );
       apaint->u.glyph.paint.p                     = child_table_p;
       apaint->u.glyph.paint.insert_root_transform = 0;
       apaint->u.glyph.glyphID                     = FT_NEXT_USHORT( p );
@@ -581,6 +608,7 @@
        * The following matrix coefficients are encoded as
        * OpenType 16.16 fixed-point values.
        */
+      ENSURE_READ_BYTES( 24 );
       apaint->u.transform.affine.xx = FT_NEXT_LONG( p );
       apaint->u.transform.affine.yx = FT_NEXT_LONG( p );
       apaint->u.transform.affine.xy = FT_NEXT_LONG( p );
@@ -596,6 +624,7 @@
       apaint->u.translate.paint.p                     = child_table_p;
       apaint->u.translate.paint.insert_root_transform = 0;
 
+      ENSURE_READ_BYTES( 4 );
       apaint->u.translate.dx = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
       apaint->u.translate.dy = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
 
@@ -615,6 +644,7 @@
       apaint->u.scale.paint.insert_root_transform = 0;
 
       /* All scale paints get at least one scale value. */
+      ENSURE_READ_BYTES( 2 );
       apaint->u.scale.scale_x = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
 
       /* Non-uniform ones read an extra y value. */
@@ -622,7 +652,10 @@
              FT_COLR_PAINTFORMAT_SCALE                 ||
            (FT_PaintFormat_Internal)apaint->format ==
              FT_COLR_PAINTFORMAT_INTERNAL_SCALE_CENTER )
+      {
+        ENSURE_READ_BYTES( 2 );
         apaint->u.scale.scale_y = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
+      }
       else
         apaint->u.scale.scale_y = apaint->u.scale.scale_x;
 
@@ -633,6 +666,7 @@
            (FT_PaintFormat_Internal)apaint->format ==
              FT_COLR_PAINTFORMAT_INTERNAL_SCALE_UNIFORM_CENTER )
       {
+        ENSURE_READ_BYTES( 4 );
         apaint->u.scale.center_x = INT_TO_FIXED( FT_NEXT_SHORT ( p ) );
         apaint->u.scale.center_y = INT_TO_FIXED( FT_NEXT_SHORT ( p ) );
       }
@@ -656,11 +690,13 @@
       apaint->u.rotate.paint.p                     = child_table_p;
       apaint->u.rotate.paint.insert_root_transform = 0;
 
+      ENSURE_READ_BYTES( 2 );
       apaint->u.rotate.angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
 
       if ( (FT_PaintFormat_Internal)apaint->format ==
            FT_COLR_PAINTFORMAT_INTERNAL_ROTATE_CENTER )
       {
+        ENSURE_READ_BYTES( 4 );
         apaint->u.rotate.center_x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
         apaint->u.rotate.center_y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
       }
@@ -682,12 +718,14 @@
       apaint->u.skew.paint.p                     = child_table_p;
       apaint->u.skew.paint.insert_root_transform = 0;
 
+      ENSURE_READ_BYTES( 4 );
       apaint->u.skew.x_skew_angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
       apaint->u.skew.y_skew_angle = F2DOT14_TO_FIXED( FT_NEXT_SHORT( p ) );
 
       if ( (FT_PaintFormat_Internal)apaint->format ==
            FT_COLR_PAINTFORMAT_INTERNAL_SKEW_CENTER )
       {
+        ENSURE_READ_BYTES( 4 );
         apaint->u.skew.center_x = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
         apaint->u.skew.center_y = INT_TO_FIXED( FT_NEXT_SHORT( p ) );
       }
@@ -710,6 +748,7 @@
       apaint->u.composite.source_paint.p                     = child_table_p;
       apaint->u.composite.source_paint.insert_root_transform = 0;
 
+      ENSURE_READ_BYTES( 1 );
       composite_mode = FT_NEXT_BYTE( p );
       if ( composite_mode >= FT_COLR_COMPOSITE_MAX )
         return 0;
@@ -955,13 +994,6 @@
     p = iterator->p;
 
     /*
-     * First ensure that p is within COLRv1.
-     */
-    if ( p < colr->layers_v1                               ||
-         p >= ( (FT_Byte*)colr->table + colr->table_size ) )
-      return 0;
-
-    /*
      * Do a cursor sanity check of the iterator.  Counting backwards from
      * where it stands, we need to end up at a position after the beginning
      * of the `LayerV1List` table and not after the end of the
@@ -977,6 +1009,14 @@
            colr->num_layers_v1 * LAYER_V1_LIST_PAINT_OFFSET_SIZE ) )
       return 0;
 
+    /*
+     * Before reading, ensure that `p` is within 'COLR' v1 and we can read a
+     * 4-byte ULONG.
+     */
+    if ( p < colr->layers_v1                                  ||
+         p > ( (FT_Byte*)colr->table + colr->table_size - 4 ) )
+      return 0;
+
     paint_offset =
       FT_NEXT_ULONG( p );
     opaque_paint->insert_root_transform =