[type1] Directly search for eexec in private dict
This code originally just searched for `eexec`. This was later modified to check that the `eexec` found is valid (not in a string or comment). This was done by searching for `eexec` as before and then, for each `eexec` found, searching from the beginning using the correct parsing to see if the `eexec` was still found. If the private dictionary is large and contains many copies of `eexec` which are not valid, the initial part of the private dictionary is scanned once for each, potentially leading to n^2 parsing time. Instead of finding an initial `eexec` and then re-parsing to discover if it is valid, drop the initial search for `eexec` and just parse to find a valid `eexec`. This is strictly faster since the validation must happen anyway and avoids restarting from the beginning each time an `eexec` is found in the data. * src/type1/t1parse.c (T1_Get_Private_Dict): avoid n^2 parsing Bug: https://bugs.chromium.org/p/chromium/issues/detail?id=1328883
This commit is contained in:
parent
d6fc8c6ba0
commit
9079521002
|
@ -330,50 +330,25 @@
|
|||
/* the private dict. Otherwise, simply overwrite into the base */
|
||||
/* dictionary block in the heap. */
|
||||
|
||||
/* first of all, look at the `eexec' keyword */
|
||||
/* First look for the `eexec' keyword. Ensure `eexec' is real -- */
|
||||
/* it could be in a comment or string (as e.g. in u003043t.gsf */
|
||||
/* from ghostscript). */
|
||||
FT_Byte* cur = parser->base_dict;
|
||||
FT_Byte* limit = cur + parser->base_len;
|
||||
FT_Pointer pos_lf;
|
||||
FT_Bool test_cr;
|
||||
|
||||
|
||||
Again:
|
||||
for (;;)
|
||||
{
|
||||
if ( cur[0] == 'e' &&
|
||||
cur + 9 < limit ) /* 9 = 5 letters for `eexec' + */
|
||||
/* whitespace + 4 chars */
|
||||
{
|
||||
if ( cur[1] == 'e' &&
|
||||
cur[2] == 'x' &&
|
||||
cur[3] == 'e' &&
|
||||
cur[4] == 'c' )
|
||||
break;
|
||||
}
|
||||
cur++;
|
||||
if ( cur >= limit )
|
||||
{
|
||||
FT_ERROR(( "T1_Get_Private_Dict:"
|
||||
" could not find `eexec' keyword\n" ));
|
||||
error = FT_THROW( Invalid_File_Format );
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* check whether `eexec' was real -- it could be in a comment */
|
||||
/* or string (as e.g. in u003043t.gsf from ghostscript) */
|
||||
|
||||
parser->root.cursor = parser->base_dict;
|
||||
/* set limit to `eexec' + whitespace + 4 characters */
|
||||
parser->root.limit = cur + 10;
|
||||
parser->root.limit = parser->base_dict + parser->base_len;
|
||||
|
||||
cur = parser->root.cursor;
|
||||
limit = parser->root.limit;
|
||||
|
||||
while ( cur < limit )
|
||||
{
|
||||
if ( cur[0] == 'e' &&
|
||||
cur + 5 < limit )
|
||||
/* 9 = 5 letters for `eexec' + whitespace + 4 chars */
|
||||
if ( cur[0] == 'e' && cur + 9 < limit )
|
||||
{
|
||||
if ( cur[1] == 'e' &&
|
||||
cur[2] == 'x' &&
|
||||
|
@ -389,21 +364,9 @@
|
|||
cur = parser->root.cursor;
|
||||
}
|
||||
|
||||
/* we haven't found the correct `eexec'; go back and continue */
|
||||
/* searching */
|
||||
|
||||
cur = limit;
|
||||
limit = parser->base_dict + parser->base_len;
|
||||
|
||||
if ( cur >= limit )
|
||||
{
|
||||
FT_ERROR(( "T1_Get_Private_Dict:"
|
||||
" premature end in private dictionary\n" ));
|
||||
error = FT_THROW( Invalid_File_Format );
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
goto Again;
|
||||
FT_ERROR(( "T1_Get_Private_Dict: could not find `eexec' keyword\n" ));
|
||||
error = FT_THROW( Invalid_File_Format );
|
||||
goto Exit;
|
||||
|
||||
/* now determine where to write the _encrypted_ binary private */
|
||||
/* dictionary. We overwrite the base dictionary for disk-based */
|
||||
|
|
Loading…
Reference in New Issue