Werner Lemberg pushed to branch master at FreeType / FreeType
Commits:
-
369d8be9
by Ben Wagner at 2021-04-02T10:31:39+02:00
4 changed files:
Changes:
1 |
+2021-04-02 Ben Wagner <bungeman@chromium.org>
|
|
2 |
+ |
|
3 |
+ [truetype] Prevent glyph program state from persisting.
|
|
4 |
+ |
|
5 |
+ `FDEF` instructions are specified as allowed only in 'prep' or
|
|
6 |
+ 'fpgm'. FreeType has attempted to prevent their use in the glyph
|
|
7 |
+ program, but they were still allowed in glyph programs if defined in
|
|
8 |
+ a function defined in 'prep' or 'fpgm' and called from the glyph
|
|
9 |
+ program.
|
|
10 |
+ |
|
11 |
+ Similarly, `IDEF` instructions are specified not to be able to
|
|
12 |
+ modify any existing instruction. FreeType has attempted to prevent
|
|
13 |
+ their use in the glyph program, but they can still be used like
|
|
14 |
+ `FDEF`.
|
|
15 |
+ |
|
16 |
+ This change stores the initial bytecode range type and disallows the
|
|
17 |
+ use of `FDEF` and `IDEF` while running the glyph program.
|
|
18 |
+ |
|
19 |
+ Most other state is copied from the `TT_Size` into the execution
|
|
20 |
+ context. However, it is possible for a glyph program to use `WS` to
|
|
21 |
+ write to the storage area or `WCVTP`, `WCVTF`, and `DELTAC[123]` to
|
|
22 |
+ write to the control value table.
|
|
23 |
+ |
|
24 |
+ Allowing any change to the global state from the glyph program is
|
|
25 |
+ problematic as the outlines of any given glyph may change based on
|
|
26 |
+ the order the glyphs are loaded or even how many times they are
|
|
27 |
+ loaded. There exist fonts that write to the storage area or the
|
|
28 |
+ control value table in the glyph program, so their use should not be
|
|
29 |
+ an error.
|
|
30 |
+ |
|
31 |
+ Possible solutions to using these in the glyph program are
|
|
32 |
+ |
|
33 |
+ * ignore the writes;
|
|
34 |
+ * value-level copy on write, discard modified values when finished;
|
|
35 |
+ * array-level copy on write, discard the copy when finished;
|
|
36 |
+ * array-level copy up-front.
|
|
37 |
+ |
|
38 |
+ Ignoring the writes may break otherwise good uses. A full copy
|
|
39 |
+ up-front was implemented, but was quite heavy as even well behaved
|
|
40 |
+ fonts required a full copy and the memory management that goes along
|
|
41 |
+ with it. Value-level copy on write could use less memory but
|
|
42 |
+ requires a great deal more record keeping and complexity. This
|
|
43 |
+ change implements array-level copy on write. If any attempt is made
|
|
44 |
+ to write to the control value table or the storage area when the
|
|
45 |
+ initial bytecode range was in a glyph program, the relevant array
|
|
46 |
+ will be copied to a designated storage area and the copy used for
|
|
47 |
+ the rest of the glyph program's execution.
|
|
48 |
+ |
|
49 |
+ * src/truetype/ttinterp.h (TT_ExecContextRec): New fields
|
|
50 |
+ `iniRange`, `glyfCvtSize`, `glyfCvt`, `origCvt`, `glyfStoreSize`,
|
|
51 |
+ `glyfStorage`, and `origStorage`.
|
|
52 |
+ |
|
53 |
+ * src/truetype/ttinterp.c (Modify_CVT_Check): New function to handle
|
|
54 |
+ `exc->glyfCvt`.
|
|
55 |
+ (Write_CVT, Write_CVT_Stretched, Move_CVT, Move_CVT_Stretched): Use
|
|
56 |
+ it.
|
|
57 |
+ (Ins_WS): Handle `exc->glyfStorage`.
|
|
58 |
+ (Ins_FDEF, Ins_IDEF): Updated.
|
|
59 |
+ (TT_RunIns): Updated.
|
|
60 |
+ (TT_Done_Context): Free 'glyf' CVT working and storage area.
|
|
61 |
+ (TT_Load_Context): Fix/add casts.
|
|
62 |
+ |
|
63 |
+ * src/truetype/ttgload.c (TT_Load_Simple_Glyph): Fix cast.
|
|
64 |
+ |
|
1 | 65 |
2021-03-30 Dominik Röttsches <drott@chromium.org>
|
2 | 66 |
|
3 | 67 |
[sfnt] Check validity of pointer location of `read_color_line`.
|
... | ... | @@ -277,7 +341,7 @@ |
277 | 341 |
|
278 | 342 |
[sfnt] Provide optional root transform for 'COLR' v1 glyph graph.
|
279 | 343 |
|
280 |
- * include/freetype/freetype.h (FT_Get_Color_Glyph_Paint):
|
|
344 |
+ * include/freetype/freetype.h (FT_Get_Color_Glyph_Paint):
|
|
281 | 345 |
Additional function argument `root_transform` to control whether
|
282 | 346 |
root transform should be returned.
|
283 | 347 |
(FT_OpaquePaint): Additional tracking field to denote whether
|
... | ... | @@ -458,7 +458,7 @@ |
458 | 458 |
(void*)&load->exec->glyphIns,
|
459 | 459 |
n_ins );
|
460 | 460 |
|
461 |
- load->exec->glyphSize = (FT_UShort)tmp;
|
|
461 |
+ load->exec->glyphSize = (FT_UInt)tmp;
|
|
462 | 462 |
if ( error )
|
463 | 463 |
return error;
|
464 | 464 |
|
... | ... | @@ -251,6 +251,14 @@ |
251 | 251 |
FT_FREE( exec->stack );
|
252 | 252 |
exec->stackSize = 0;
|
253 | 253 |
|
254 |
+ /* free glyf cvt working area */
|
|
255 |
+ FT_FREE( exec->glyfCvt );
|
|
256 |
+ exec->glyfCvtSize = 0;
|
|
257 |
+ |
|
258 |
+ /* free glyf storage working area */
|
|
259 |
+ FT_FREE( exec->glyfStorage );
|
|
260 |
+ exec->glyfStoreSize = 0;
|
|
261 |
+ |
|
254 | 262 |
/* free call stack */
|
255 | 263 |
FT_FREE( exec->callStack );
|
256 | 264 |
exec->callSize = 0;
|
... | ... | @@ -464,13 +472,13 @@ |
464 | 472 |
if ( error )
|
465 | 473 |
return error;
|
466 | 474 |
|
467 |
- tmp = exec->glyphSize;
|
|
475 |
+ tmp = (FT_ULong)exec->glyphSize;
|
|
468 | 476 |
error = Update_Max( exec->memory,
|
469 | 477 |
&tmp,
|
470 | 478 |
sizeof ( FT_Byte ),
|
471 | 479 |
(void*)&exec->glyphIns,
|
472 | 480 |
maxp->maxSizeOfInstructions );
|
473 |
- exec->glyphSize = (FT_UShort)tmp;
|
|
481 |
+ exec->glyphSize = (FT_UInt)tmp;
|
|
474 | 482 |
if ( error )
|
475 | 483 |
return error;
|
476 | 484 |
|
... | ... | @@ -1572,11 +1580,36 @@ |
1572 | 1580 |
}
|
1573 | 1581 |
|
1574 | 1582 |
|
1583 |
+ static void
|
|
1584 |
+ Modify_CVT_Check( TT_ExecContext exc )
|
|
1585 |
+ {
|
|
1586 |
+ /* TT_RunIns sets origCvt and restores cvt to origCvt when done. */
|
|
1587 |
+ if ( exc->iniRange == tt_coderange_glyph &&
|
|
1588 |
+ exc->cvt == exc->origCvt )
|
|
1589 |
+ {
|
|
1590 |
+ exc->error = Update_Max( exc->memory,
|
|
1591 |
+ &exc->glyfCvtSize,
|
|
1592 |
+ sizeof ( FT_Long ),
|
|
1593 |
+ (void*)&exc->glyfCvt,
|
|
1594 |
+ exc->cvtSize );
|
|
1595 |
+ if ( exc->error )
|
|
1596 |
+ return;
|
|
1597 |
+ |
|
1598 |
+ FT_ARRAY_COPY( exc->glyfCvt, exc->cvt, exc->glyfCvtSize );
|
|
1599 |
+ exc->cvt = exc->glyfCvt;
|
|
1600 |
+ }
|
|
1601 |
+ }
|
|
1602 |
+ |
|
1603 |
+ |
|
1575 | 1604 |
FT_CALLBACK_DEF( void )
|
1576 | 1605 |
Write_CVT( TT_ExecContext exc,
|
1577 | 1606 |
FT_ULong idx,
|
1578 | 1607 |
FT_F26Dot6 value )
|
1579 | 1608 |
{
|
1609 |
+ Modify_CVT_Check( exc );
|
|
1610 |
+ if ( exc->error )
|
|
1611 |
+ return;
|
|
1612 |
+ |
|
1580 | 1613 |
exc->cvt[idx] = value;
|
1581 | 1614 |
}
|
1582 | 1615 |
|
... | ... | @@ -1586,6 +1619,10 @@ |
1586 | 1619 |
FT_ULong idx,
|
1587 | 1620 |
FT_F26Dot6 value )
|
1588 | 1621 |
{
|
1622 |
+ Modify_CVT_Check( exc );
|
|
1623 |
+ if ( exc->error )
|
|
1624 |
+ return;
|
|
1625 |
+ |
|
1589 | 1626 |
exc->cvt[idx] = FT_DivFix( value, Current_Ratio( exc ) );
|
1590 | 1627 |
}
|
1591 | 1628 |
|
... | ... | @@ -1595,6 +1632,10 @@ |
1595 | 1632 |
FT_ULong idx,
|
1596 | 1633 |
FT_F26Dot6 value )
|
1597 | 1634 |
{
|
1635 |
+ Modify_CVT_Check( exc );
|
|
1636 |
+ if ( exc->error )
|
|
1637 |
+ return;
|
|
1638 |
+ |
|
1598 | 1639 |
exc->cvt[idx] = ADD_LONG( exc->cvt[idx], value );
|
1599 | 1640 |
}
|
1600 | 1641 |
|
... | ... | @@ -1604,6 +1645,10 @@ |
1604 | 1645 |
FT_ULong idx,
|
1605 | 1646 |
FT_F26Dot6 value )
|
1606 | 1647 |
{
|
1648 |
+ Modify_CVT_Check( exc );
|
|
1649 |
+ if ( exc->error )
|
|
1650 |
+ return;
|
|
1651 |
+ |
|
1607 | 1652 |
exc->cvt[idx] = ADD_LONG( exc->cvt[idx],
|
1608 | 1653 |
FT_DivFix( value, Current_Ratio( exc ) ) );
|
1609 | 1654 |
}
|
... | ... | @@ -3125,7 +3170,30 @@ |
3125 | 3170 |
ARRAY_BOUND_ERROR;
|
3126 | 3171 |
}
|
3127 | 3172 |
else
|
3173 |
+ {
|
|
3174 |
+ /* TT_RunIns sets origStorage and restores storage to origStorage */
|
|
3175 |
+ /* when done. */
|
|
3176 |
+ if ( exc->iniRange == tt_coderange_glyph &&
|
|
3177 |
+ exc->storage == exc->origStorage )
|
|
3178 |
+ {
|
|
3179 |
+ FT_ULong tmp = (FT_ULong)exc->glyfStoreSize;
|
|
3180 |
+ |
|
3181 |
+ |
|
3182 |
+ exc->error = Update_Max( exc->memory,
|
|
3183 |
+ &tmp,
|
|
3184 |
+ sizeof ( FT_Long ),
|
|
3185 |
+ (void*)&exc->glyfStorage,
|
|
3186 |
+ exc->storeSize );
|
|
3187 |
+ exc->glyfStoreSize = (FT_UShort)tmp;
|
|
3188 |
+ if ( exc->error )
|
|
3189 |
+ return;
|
|
3190 |
+ |
|
3191 |
+ FT_ARRAY_COPY( exc->glyfStorage, exc->storage, exc->glyfStoreSize );
|
|
3192 |
+ exc->storage = exc->glyfStorage;
|
|
3193 |
+ }
|
|
3194 |
+ |
|
3128 | 3195 |
exc->storage[I] = args[1];
|
3196 |
+ }
|
|
3129 | 3197 |
}
|
3130 | 3198 |
|
3131 | 3199 |
|
... | ... | @@ -3697,7 +3765,7 @@ |
3697 | 3765 |
|
3698 | 3766 |
|
3699 | 3767 |
/* FDEF is only allowed in `prep' or `fpgm' */
|
3700 |
- if ( exc->curRange == tt_coderange_glyph )
|
|
3768 |
+ if ( exc->iniRange == tt_coderange_glyph )
|
|
3701 | 3769 |
{
|
3702 | 3770 |
exc->error = FT_THROW( DEF_In_Glyf_Bytecode );
|
3703 | 3771 |
return;
|
... | ... | @@ -4133,7 +4201,7 @@ |
4133 | 4201 |
|
4134 | 4202 |
|
4135 | 4203 |
/* we enable IDEF only in `prep' or `fpgm' */
|
4136 |
- if ( exc->curRange == tt_coderange_glyph )
|
|
4204 |
+ if ( exc->iniRange == tt_coderange_glyph )
|
|
4137 | 4205 |
{
|
4138 | 4206 |
exc->error = FT_THROW( DEF_In_Glyf_Bytecode );
|
4139 | 4207 |
return;
|
... | ... | @@ -7842,6 +7910,10 @@ |
7842 | 7910 |
exc->func_move_cvt = Move_CVT;
|
7843 | 7911 |
}
|
7844 | 7912 |
|
7913 |
+ exc->origCvt = exc->cvt;
|
|
7914 |
+ exc->origStorage = exc->storage;
|
|
7915 |
+ exc->iniRange = exc->curRange;
|
|
7916 |
+ |
|
7845 | 7917 |
Compute_Funcs( exc );
|
7846 | 7918 |
Compute_Round( exc, (FT_Byte)exc->GS.round_state );
|
7847 | 7919 |
|
... | ... | @@ -8566,8 +8638,10 @@ |
8566 | 8638 |
|
8567 | 8639 |
/* increment instruction counter and check if we didn't */
|
8568 | 8640 |
/* run this program for too long (e.g. infinite loops). */
|
8569 |
- if ( ++ins_counter > TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES )
|
|
8570 |
- return FT_THROW( Execution_Too_Long );
|
|
8641 |
+ if ( ++ins_counter > TT_CONFIG_OPTION_MAX_RUNNABLE_OPCODES ) {
|
|
8642 |
+ exc->error = FT_THROW( Execution_Too_Long );
|
|
8643 |
+ goto LErrorLabel_;
|
|
8644 |
+ }
|
|
8571 | 8645 |
|
8572 | 8646 |
LSuiteLabel_:
|
8573 | 8647 |
if ( exc->IP >= exc->codeSize )
|
... | ... | @@ -8586,6 +8660,10 @@ |
8586 | 8660 |
FT_TRACE4(( " %ld instruction%s executed\n",
|
8587 | 8661 |
ins_counter,
|
8588 | 8662 |
ins_counter == 1 ? "" : "s" ));
|
8663 |
+ |
|
8664 |
+ exc->cvt = exc->origCvt;
|
|
8665 |
+ exc->storage = exc->origStorage;
|
|
8666 |
+ |
|
8589 | 8667 |
return FT_Err_Ok;
|
8590 | 8668 |
|
8591 | 8669 |
LErrorCodeOverflow_:
|
... | ... | @@ -8595,6 +8673,9 @@ |
8595 | 8673 |
if ( exc->error && !exc->instruction_trap )
|
8596 | 8674 |
FT_TRACE1(( " The interpreter returned error 0x%x\n", exc->error ));
|
8597 | 8675 |
|
8676 |
+ exc->cvt = exc->origCvt;
|
|
8677 |
+ exc->storage = exc->origStorage;
|
|
8678 |
+ |
|
8598 | 8679 |
return exc->error;
|
8599 | 8680 |
}
|
8600 | 8681 |
|
... | ... | @@ -175,6 +175,7 @@ FT_BEGIN_HEADER |
175 | 175 |
|
176 | 176 |
TT_GraphicsState GS; /* current graphics state */
|
177 | 177 |
|
178 |
+ FT_Int iniRange; /* initial code range number */
|
|
178 | 179 |
FT_Int curRange; /* current code range number */
|
179 | 180 |
FT_Byte* code; /* current code range */
|
180 | 181 |
FT_Long IP; /* current instruction pointer */
|
... | ... | @@ -187,6 +188,9 @@ FT_BEGIN_HEADER |
187 | 188 |
/* increment IP after ins. exec */
|
188 | 189 |
FT_ULong cvtSize;
|
189 | 190 |
FT_Long* cvt;
|
191 |
+ FT_ULong glyfCvtSize;
|
|
192 |
+ FT_Long* glyfCvt; /* cvt working copy for glyph */
|
|
193 |
+ FT_Long* origCvt;
|
|
190 | 194 |
|
191 | 195 |
FT_UInt glyphSize; /* glyph instructions buffer size */
|
192 | 196 |
FT_Byte* glyphIns; /* glyph instructions buffer */
|
... | ... | @@ -213,8 +217,11 @@ FT_BEGIN_HEADER |
213 | 217 |
TT_CodeRangeTable codeRangeTable; /* table of valid code ranges */
|
214 | 218 |
/* useful for the debugger */
|
215 | 219 |
|
216 |
- FT_UShort storeSize; /* size of current storage */
|
|
217 |
- FT_Long* storage; /* storage area */
|
|
220 |
+ FT_UShort storeSize; /* size of current storage */
|
|
221 |
+ FT_Long* storage; /* storage area */
|
|
222 |
+ FT_UShort glyfStoreSize;
|
|
223 |
+ FT_Long* glyfStorage; /* storage working copy for glyph */
|
|
224 |
+ FT_Long* origStorage;
|
|
218 | 225 |
|
219 | 226 |
FT_F26Dot6 period; /* values used for the */
|
220 | 227 |
FT_F26Dot6 phase; /* `SuperRounding' */
|