[sfnt] Prevent overrunning in `post' table parser. * src/sfnt/ttpost.c (load_post_names): Get the length of `post' table and pass the limit of `post' table to load_format_20() and load_format_25(). (load_format_20): Stop the parsing when we reached at the limit of `post' table. If more glyph names are required, they are filled by NULL names. See Savannah bug #31040.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
diff --git a/ChangeLog b/ChangeLog
index 2b3307d..7c5f017 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2010-09-19 suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
+
+ [sfnt] Prevent overrunning in `post' table parser.
+
+ * src/sfnt/ttpost.c (load_post_names): Get the length of
+ `post' table and pass the limit of `post' table to
+ load_format_20() and load_format_25().
+ (load_format_20): Stop the parsing when we reached at the
+ limit of `post' table. If more glyph names are required,
+ they are filled by NULL names. See Savannah bug #31040.
+
2010-09-17 suzuki toshiya <mpsuzuki@hiroshima-u.ac.jp>
[truetype] Don't duplicate size->twilight structure to be freed.
diff --git a/src/sfnt/ttpost.c b/src/sfnt/ttpost.c
index aa0bf1e..5059fd5 100644
--- a/src/sfnt/ttpost.c
+++ b/src/sfnt/ttpost.c
@@ -153,7 +153,8 @@
static FT_Error
load_format_20( TT_Face face,
- FT_Stream stream )
+ FT_Stream stream,
+ FT_ULong post_limit )
{
FT_Memory memory = stream->memory;
FT_Error error;
@@ -230,8 +231,29 @@
FT_UInt len;
- if ( FT_READ_BYTE ( len ) ||
- FT_NEW_ARRAY( name_strings[n], len + 1 ) ||
+ FT_TRACE7(( "load_format_20: %d byte left in post table\n",
+ post_limit - FT_STREAM_POS() ));
+
+ if ( FT_STREAM_POS() >= post_limit )
+ {
+ FT_ERROR(( "load_format_20:"
+ " all entries in post table is already parsed,"
+ " put NULL name for gid=%d\n", n ));
+ len = 0;
+ }
+ else if ( FT_READ_BYTE( len ) )
+ goto Fail1;
+
+ if ( len > 0 && FT_STREAM_POS() + len > post_limit )
+ {
+ FT_ERROR(( "load_format_20:"
+ " too large string length (%d)"
+ " truncate at the end of post table (%d byte left)\n",
+ len, post_limit - FT_STREAM_POS() ));
+ len = FT_MAX( 0, post_limit - FT_STREAM_POS() );
+ }
+
+ if ( FT_NEW_ARRAY( name_strings[n], len + 1 ) ||
FT_STREAM_READ ( name_strings[n], len ) )
goto Fail1;
@@ -271,7 +293,8 @@
static FT_Error
load_format_25( TT_Face face,
- FT_Stream stream )
+ FT_Stream stream,
+ FT_ULong post_limit )
{
FT_Memory memory = stream->memory;
FT_Error error;
@@ -338,16 +361,19 @@
FT_Stream stream;
FT_Error error;
FT_Fixed format;
+ FT_ULong post_len, post_limit;
/* get a stream for the face's resource */
stream = face->root.stream;
/* seek to the beginning of the PS names table */
- error = face->goto_table( face, TTAG_post, stream, 0 );
+ error = face->goto_table( face, TTAG_post, stream, &post_len );
if ( error )
goto Exit;
+ post_limit = FT_STREAM_POS() + post_len;
+
format = face->postscript.FormatType;
/* go to beginning of subtable */
@@ -356,9 +382,9 @@
/* now read postscript table */
if ( format == 0x00020000L )
- error = load_format_20( face, stream );
+ error = load_format_20( face, stream, post_limit );
else if ( format == 0x00028000L )
- error = load_format_25( face, stream );
+ error = load_format_25( face, stream, post_limit );
else
error = SFNT_Err_Invalid_File_Format;