[cid] Fix scanning for `StartData' and `/sfnts' (#47892).

* src/cid/cidparse.c (STARTDATA, STARTDATA_LEN, SFNTS, SFNTS_LEN):
New macros.
(cid_parser_new): Fix and document algorithm.
This commit is contained in:
Werner Lemberg 2016-05-16 19:44:19 +02:00
parent a7d8bdbcfe
commit 09f0e0fcbe
2 changed files with 84 additions and 33 deletions

View File

@ -1,3 +1,11 @@
2016-05-16 Werner Lemberg <wl@gnu.org>
[cid] Fix scanning for `StartData' and `/sfnts' (#47892).
* src/cid/cidparse.c (STARTDATA, STARTDATA_LEN, SFNTS, SFNTS_LEN):
New macros.
(cid_parser_new): Fix and document algorithm.
2016-05-16 suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
[truetype] Improve the recursive reference detector.

View File

@ -47,6 +47,12 @@
/*************************************************************************/
#define STARTDATA "StartData"
#define STARTDATA_LEN ( sizeof ( STARTDATA ) - 1 )
#define SFNTS "/sfnts"
#define SFNTS_LEN ( sizeof ( SFNTS ) - 1 )
FT_LOCAL_DEF( FT_Error )
cid_parser_new( CID_Parser* parser,
FT_Stream stream,
@ -85,9 +91,29 @@
/* now, read the rest of the file until we find */
/* `StartData' or `/sfnts' */
{
FT_Byte buffer[256 + 10];
FT_ULong read_len = 256 + 10;
FT_Byte* p = buffer;
/*
* The algorithm is as follows (omitting the case with less than 256
* bytes to fill for simplicity).
*
* 1. Fill the buffer with 256 + STARTDATA_LEN bytes.
*
* 2. Search for the STARTDATA and SFNTS strings at positions
* buffer[0], buffer[1], ...,
* buffer[255 + STARTDATA_LEN - SFNTS_LEN].
*
* 3. Move the last STARTDATA_LEN bytes to buffer[0].
*
* 4. Fill the buffer with 256 bytes, starting at STARTDATA_LEN.
*
* 5. Repeat with step 2.
*
*/
FT_Byte buffer[256 + STARTDATA_LEN + 1];
/* values for the first loop */
FT_ULong read_len = 256 + STARTDATA_LEN;
FT_ULong read_offset = 0;
FT_Byte* p = buffer;
for ( offset = FT_STREAM_POS(); ; offset += 256 )
@ -96,40 +122,48 @@
stream_len = stream->size - FT_STREAM_POS();
if ( stream_len == 0 )
read_len = FT_MIN( read_len, stream_len );
if ( FT_STREAM_READ( p, read_len ) )
goto Exit;
/* ensure that we do not compare with data beyond the buffer */
p[read_len] = '\0';
limit = p + read_len - SFNTS_LEN;
for ( p = buffer; p < limit; p++ )
{
if ( p[0] == 'S' &&
ft_strncmp( (char*)p, STARTDATA, STARTDATA_LEN ) == 0 )
{
/* save offset of binary data after `StartData' */
offset += (FT_ULong)( p - buffer ) + STARTDATA_LEN;
goto Found;
}
else if ( p[1] == 's' &&
ft_strncmp( (char*)p, SFNTS, SFNTS_LEN ) == 0 )
{
offset += (FT_ULong)( p - buffer ) + SFNTS_LEN;
goto Found;
}
}
if ( read_offset + read_len < STARTDATA_LEN )
{
FT_TRACE2(( "cid_parser_new: no `StartData' keyword found\n" ));
error = FT_THROW( Invalid_File_Format );
goto Exit;
}
read_len = FT_MIN( read_len, stream_len );
if ( FT_STREAM_READ( p, read_len ) )
goto Exit;
FT_MEM_MOVE( buffer,
buffer + read_offset + read_len - STARTDATA_LEN,
STARTDATA_LEN );
if ( read_len < 256 )
p[read_len] = '\0';
limit = p + read_len - 10;
for ( p = buffer; p < limit; p++ )
{
if ( p[0] == 'S' && ft_strncmp( (char*)p, "StartData", 9 ) == 0 )
{
/* save offset of binary data after `StartData' */
offset += (FT_ULong)( p - buffer + 10 );
goto Found;
}
else if ( p[1] == 's' && ft_strncmp( (char*)p, "/sfnts", 6 ) == 0 )
{
offset += (FT_ULong)( p - buffer + 7 );
goto Found;
}
}
FT_MEM_MOVE( buffer, p, 10 );
read_len = 256;
p = buffer + 10;
/* values for the next loop */
read_len = 256;
read_offset = STARTDATA_LEN;
p = buffer + read_offset;
}
}
@ -165,7 +199,7 @@
limit = parser->root.limit;
cur = parser->root.cursor;
while ( cur < limit )
while ( cur < limit - SFNTS_LEN )
{
if ( parser->root.error )
{
@ -173,7 +207,9 @@
goto Exit;
}
if ( cur[0] == 'S' && ft_strncmp( (char*)cur, "StartData", 9 ) == 0 )
if ( cur[0] == 'S' &&
cur < limit - STARTDATA_LEN &&
ft_strncmp( (char*)cur, STARTDATA, STARTDATA_LEN ) == 0 )
{
if ( ft_strncmp( (char*)arg1, "(Hex)", 5 ) == 0 )
{
@ -191,7 +227,8 @@
goto Exit;
}
else if ( cur[1] == 's' && ft_strncmp( (char*)cur, "/sfnts", 6 ) == 0 )
else if ( cur[1] == 's' &&
ft_strncmp( (char*)cur, SFNTS, SFNTS_LEN ) == 0 )
{
FT_TRACE2(( "cid_parser_new: cannot handle Type 11 fonts\n" ));
error = FT_THROW( Unknown_File_Format );
@ -216,6 +253,12 @@
}
#undef STARTDATA
#undef STARTDATA_LEN
#undef SFNTS
#undef SFNTS_LEN
FT_LOCAL_DEF( void )
cid_parser_done( CID_Parser* parser )
{