ref: 1c0862938d798a1e79a3a087d4a93ff8628c13d2
parent: c1e1a07f791dd22c8998e6994f6dee90aef2efd8
author: Dominik Röttsches <[email protected]>
date: Fri Apr 2 02:55:29 EDT 2021
[sfnt] Check validity of pointer location of `read_color_line`. * src/sfnt/ttcolr.c (get_child_table_pointer): New function to fetch child table pointer early for all paint formats that compute a child table pointer. (read_color_line, read_paint): Updated. (tt_face_get_colorline_stops): Check `colr->table`.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2021-03-30 Dominik Röttsches <[email protected]>
+
+ [sfnt] Check validity of pointer location of `read_color_line`.
+
+ * src/sfnt/ttcolr.c (get_child_table_pointer): New function to fetch
+ child table pointer early for all paint formats that compute a child
+ table pointer.
+ (read_color_line, read_paint): Updated.
+ (tt_face_get_colorline_stops): Check `colr->table`.
+
2021-03-28 Nikhil Ramakrishnan <[email protected]>
[docs] Update docwriter stylesheet for 1.3.1.
--- a/src/sfnt/ttcolr.c
+++ b/src/sfnt/ttcolr.c
@@ -320,13 +320,11 @@
static FT_Bool
- read_color_line( FT_Byte* paint_base,
- FT_ULong colorline_offset,
+ read_color_line( FT_Byte* color_line_p,
FT_ColorLine *colorline )
{
- FT_Byte* p = (FT_Byte *)( paint_base + colorline_offset );
+ FT_Byte* p = color_line_p;
FT_PaintExtend paint_extend;
- /* TODO: Check pointer limits. */
paint_extend = FT_NEXT_BYTE( p );
@@ -343,14 +341,53 @@
}
+ /*
+ * Read a paint offset for `FT_Paint*` objects that have them and check
+ * whether it is within reasonable limits within the font and the COLR
+ * table.
+ *
+ * Return 1 on success, 0 on failure.
+ */
static FT_Bool
+ get_child_table_pointer ( Colr* colr,
+ FT_Byte* paint_base,
+ FT_Byte** p,
+ FT_Byte** child_table_pointer )
+ {
+ FT_UInt32 paint_offset;
+ FT_Byte* child_table_p;
+
+
+ if ( !child_table_pointer )
+ return 0;
+
+ paint_offset = FT_NEXT_UOFF3( *p );
+ if ( !paint_offset )
+ return 0;
+
+ child_table_p = (FT_Byte*)( paint_base + paint_offset );
+
+ if ( child_table_p < colr->base_glyphs_v1 ||
+ child_table_p >= ( (FT_Byte*)colr->table + colr->table_size ) )
+ return 0;
+
+ *child_table_pointer = child_table_p;
+ return 1;
+ }
+
+
+ static FT_Bool
read_paint( Colr* colr,
FT_Byte* p,
FT_COLR_Paint* apaint )
{
- FT_Byte* paint_base = p;
+ FT_Byte* paint_base = p;
+ FT_Byte* child_table_p = NULL;
+ if ( !p || !colr || !colr->table )
+ return 0;
+
apaint->format = FT_NEXT_BYTE( p );
if ( apaint->format >= FT_COLR_PAINT_FORMAT_MAX )
@@ -382,38 +419,34 @@
return 1;
}
- if ( apaint->format == FT_COLR_PAINTFORMAT_GLYPH )
- {
- FT_UInt32 paint_offset;
- FT_Byte* paint_p;
-
-
- paint_offset = FT_NEXT_UOFF3( p );
- if ( !paint_offset )
- return 0;
-
- paint_p = (FT_Byte*)( paint_base + paint_offset );
- if ( paint_p > ( (FT_Byte*)colr->table + colr->table_size ) )
- return 0;
-
- apaint->u.glyph.paint.p = paint_p;
- apaint->u.glyph.paint.insert_root_transform = 0;
- apaint->u.glyph.glyphID = FT_NEXT_USHORT( p );
- }
-
else if ( apaint->format == FT_COLR_PAINTFORMAT_SOLID )
{
apaint->u.solid.color.palette_index = FT_NEXT_USHORT ( p );
apaint->u.solid.color.alpha = FT_NEXT_USHORT ( p );
+
+ return 1;
}
- else if ( apaint->format == FT_COLR_PAINTFORMAT_LINEAR_GRADIENT )
+ else if ( apaint->format == FT_COLR_PAINTFORMAT_COLR_GLYPH )
{
- FT_ULong color_line_offset = FT_NEXT_OFF3( p );
+ apaint->u.colr_glyph.glyphID = FT_NEXT_USHORT( p );
+ return 1;
+ }
- if ( !read_color_line( paint_base,
- color_line_offset,
+ /*
+ * Grouped below here are all paint formats that have an offset to a
+ * child paint table as the first entry (for example, a color line or a
+ * child paint table). Retrieve that and determine whether that paint
+ * offset is valid first.
+ */
+
+ if ( !get_child_table_pointer( colr, paint_base, &p, &child_table_p ) )
+ return 0;
+
+ if ( apaint->format == FT_COLR_PAINTFORMAT_LINEAR_GRADIENT )
+ {
+ if ( !read_color_line( child_table_p,
&apaint->u.linear_gradient.colorline ) )
return 0;
@@ -423,15 +456,13 @@
apaint->u.linear_gradient.p1.y = FT_NEXT_SHORT ( p );
apaint->u.linear_gradient.p2.x = FT_NEXT_SHORT ( p );
apaint->u.linear_gradient.p2.y = FT_NEXT_SHORT ( p );
+
+ return 1;
}
else if ( apaint->format == FT_COLR_PAINTFORMAT_RADIAL_GRADIENT )
{
- FT_ULong color_line_offset = color_line_offset = FT_NEXT_OFF3( p );
-
-
- if ( !read_color_line( paint_base,
- color_line_offset,
+ if ( !read_color_line( child_table_p,
&apaint->u.radial_gradient.colorline ) )
return 0;
@@ -444,15 +475,13 @@
apaint->u.radial_gradient.c1.y = FT_NEXT_SHORT ( p );
apaint->u.radial_gradient.r1 = FT_NEXT_USHORT ( p );
+
+ return 1;
}
else if ( apaint->format == FT_COLR_PAINTFORMAT_SWEEP_GRADIENT )
{
- FT_ULong color_line_offset = color_line_offset = FT_NEXT_OFF3( p );
-
-
- if ( !read_color_line( paint_base,
- color_line_offset,
+ if ( !read_color_line( child_table_p,
&apaint->u.sweep_gradient.colorline ) )
return 0;
@@ -461,23 +490,22 @@
apaint->u.sweep_gradient.start_angle = FT_NEXT_LONG( p );
apaint->u.sweep_gradient.end_angle = FT_NEXT_LONG( p );
+
+ return 1;
}
- else if ( apaint->format == FT_COLR_PAINTFORMAT_TRANSFORMED )
+ if ( apaint->format == FT_COLR_PAINTFORMAT_GLYPH )
{
- FT_UInt32 paint_offset;
- FT_Byte* paint_p;
+ apaint->u.glyph.paint.p = child_table_p;
+ apaint->u.glyph.paint.insert_root_transform = 0;
+ apaint->u.glyph.glyphID = FT_NEXT_USHORT( p );
+ return 1;
+ }
- paint_offset = FT_NEXT_UOFF3( p );
- if ( !paint_offset )
- return 0;
-
- paint_p = (FT_Byte*)( paint_base + paint_offset );
- if ( paint_p > ( (FT_Byte*)colr->table + colr->table_size ) )
- return 0;
-
- apaint->u.transformed.paint.p = paint_p;
+ else if ( apaint->format == FT_COLR_PAINTFORMAT_TRANSFORMED )
+ {
+ apaint->u.transformed.paint.p = child_table_p;
apaint->u.transformed.paint.insert_root_transform = 0;
apaint->u.transformed.affine.xx = FT_NEXT_LONG( p );
@@ -486,44 +514,24 @@
apaint->u.transformed.affine.yy = FT_NEXT_LONG( p );
apaint->u.transformed.affine.dx = FT_NEXT_LONG( p );
apaint->u.transformed.affine.dy = FT_NEXT_LONG( p );
+
+ return 1;
}
else if ( apaint->format == FT_COLR_PAINTFORMAT_TRANSLATE )
{
- FT_UInt32 paint_offset;
- FT_Byte* paint_p;
-
-
- paint_offset = FT_NEXT_UOFF3( p );
- if ( !paint_offset )
- return 0;
-
- paint_p = (FT_Byte*)( paint_base + paint_offset );
- if ( paint_p > ( (FT_Byte*)colr->table + colr->table_size ) )
- return 0;
-
- apaint->u.translate.paint.p = paint_p;
+ apaint->u.translate.paint.p = child_table_p;
apaint->u.translate.paint.insert_root_transform = 0;
apaint->u.translate.dx = FT_NEXT_LONG( p );
apaint->u.translate.dy = FT_NEXT_LONG( p );
+
+ return 1;
}
else if ( apaint->format == FT_COLR_PAINTFORMAT_ROTATE )
{
- FT_UInt32 paint_offset;
- FT_Byte* paint_p;
-
-
- paint_offset = FT_NEXT_UOFF3( p );
- if ( !paint_offset )
- return 0;
-
- paint_p = (FT_Byte*)( paint_base + paint_offset );
- if ( paint_p > ( (FT_Byte*)colr->table + colr->table_size ) )
- return 0;
-
- apaint->u.rotate.paint.p = paint_p;
+ apaint->u.rotate.paint.p = child_table_p;
apaint->u.rotate.paint.insert_root_transform = 0;
apaint->u.rotate.angle = FT_NEXT_LONG( p );
@@ -530,23 +538,13 @@
apaint->u.rotate.center_x = FT_NEXT_LONG( p );
apaint->u.rotate.center_y = FT_NEXT_LONG( p );
+
+ return 1;
}
else if ( apaint->format == FT_COLR_PAINTFORMAT_SKEW )
{
- FT_UInt32 paint_offset;
- FT_Byte* paint_p;
-
-
- paint_offset = FT_NEXT_UOFF3( p );
- if ( !paint_offset )
- return 0;
-
- paint_p = (FT_Byte*)( paint_base + paint_offset );
- if ( paint_p > ( (FT_Byte*)colr->table + colr->table_size ) )
- return 0;
-
- apaint->u.skew.paint.p = paint_p;
+ apaint->u.skew.paint.p = child_table_p;
apaint->u.skew.paint.insert_root_transform = 0;
apaint->u.skew.x_skew_angle = FT_NEXT_LONG( p );
@@ -554,32 +552,18 @@
apaint->u.skew.center_x = FT_NEXT_LONG( p );
apaint->u.skew.center_y = FT_NEXT_LONG( p );
+
+ return 1;
}
else if ( apaint->format == FT_COLR_PAINTFORMAT_COMPOSITE )
{
- FT_UInt32 source_paint_offset;
- FT_Byte* source_paint_p;
+ FT_UInt composite_mode;
- FT_UInt32 backdrop_paint_offset;
- FT_Byte* backdrop_paint_p;
- FT_UInt composite_mode;
+ apaint->u.composite.source_paint.p = child_table_p;
+ apaint->u.composite.source_paint.insert_root_transform = 0;
-
- source_paint_offset = FT_NEXT_UOFF3( p );
- if ( !source_paint_offset )
- return 0;
-
- source_paint_p = (FT_Byte*)( paint_base + source_paint_offset );
- if ( source_paint_p > ( (FT_Byte*)colr->table + colr->table_size ) )
- return 0;
-
- apaint->u.composite.source_paint.p =
- source_paint_p;
- apaint->u.composite.source_paint.insert_root_transform =
- 0;
-
composite_mode = FT_NEXT_BYTE( p );
if ( composite_mode >= FT_COLR_COMPOSITE_MAX )
return 0;
@@ -586,24 +570,18 @@
apaint->u.composite.composite_mode = composite_mode;
- backdrop_paint_offset = FT_NEXT_UOFF3( p );
- if ( !backdrop_paint_offset )
- return 0;
+ if ( !get_child_table_pointer( colr, paint_base, &p, &child_table_p ) )
+ return 0;
- backdrop_paint_p = (FT_Byte*)( paint_base + backdrop_paint_offset );
- if ( backdrop_paint_p > ( (FT_Byte*)colr->table + colr->table_size ) )
- return 0;
-
apaint->u.composite.backdrop_paint.p =
- backdrop_paint_p;
+ child_table_p;
apaint->u.composite.backdrop_paint.insert_root_transform =
0;
+
+ return 1;
}
- else if ( apaint->format == FT_COLR_PAINTFORMAT_COLR_GLYPH )
- apaint->u.colr_glyph.glyphID = FT_NEXT_USHORT( p );
-
- return 1;
+ return 0;
}
@@ -759,7 +737,7 @@
FT_Byte* p;
- if ( !colr )
+ if ( !colr || !colr->table )
return 0;
if ( iterator->current_color_stop >= iterator->num_color_stops )