Commit 86c3c69c15dfc46238e2e0822876982b21aa53f9

Tomas Hoger 2011-09-11T09:08:40

Protect against loops in the prefix table. LZW decompressor did not sufficiently check codes read from the input LZW stream. A specially-crafted or corrupted input could create a loop in the prefix table, which leads to memory usage spikes, as there's no decompression stack size limit. * src/lzw/ftzopen.c (ft_lzwstate_io) <FT_LZW_PHASE_START>: First code in valid LZW stream must be 0..255. <FT_LZW_PHASE_CODE>: In the special KwKwK case, code == free_ent, code > free_ent is invalid.

diff --git a/ChangeLog b/ChangeLog
index b9ff243..e76c105 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2011-09-11  Tomas Hoger  <thoger@redhat.com>
+
+	Protect against loops in the prefix table.
+
+	LZW decompressor did not sufficiently check codes read from the
+	input LZW stream.  A specially-crafted or corrupted input could
+	create a loop in the prefix table, which leads to memory usage
+	spikes, as there's no decompression stack size limit.
+
+	* src/lzw/ftzopen.c (ft_lzwstate_io) <FT_LZW_PHASE_START>: First
+	code in valid LZW stream must be 0..255.
+	<FT_LZW_PHASE_CODE>: In the special KwKwK case, code == free_ent,
+	code > free_ent is invalid.
+
 2011-09-09  Werner Lemberg  <wl@gnu.org>
 
 	Better tracing of metrics.
diff --git a/src/lzw/ftzopen.c b/src/lzw/ftzopen.c
index 8bc65c8..b5a6226 100644
--- a/src/lzw/ftzopen.c
+++ b/src/lzw/ftzopen.c
@@ -8,7 +8,7 @@
 /*  be used to parse compressed PCF fonts, as found with many X11 server   */
 /*  distributions.                                                         */
 /*                                                                         */
-/*  Copyright 2005, 2006, 2007, 2009 by David Turner.                      */
+/*  Copyright 2005-2007, 2009, 2011 by David Turner.                       */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
 /*  modified, and distributed under the terms of the FreeType project      */
@@ -279,7 +279,7 @@
                            : state->max_free + 1;
 
         c = ft_lzwstate_get_code( state );
-        if ( c < 0 )
+        if ( c < 0 || c > 255 )
           goto Eof;
 
         old_code = old_char = (FT_UInt)c;
@@ -326,6 +326,10 @@
           /* special case for KwKwKwK */
           if ( code - 256U >= state->free_ent )
           {
+            /* corrupted LZW stream */
+            if ( code - 256U > state->free_ent )
+              goto Eof;
+
             FTLZW_STACK_PUSH( old_char );
             code = old_code;
           }