avoid heap explosion in the case of malformed .Z font files related to bug #19910, but not a bugfix yet
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 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
diff --git a/ChangeLog b/ChangeLog
index 19c96dc..3f044a8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,9 +1,15 @@
-2007-06-20 Ismail Dönmez <ismail@pardus.org.tr>
+2007-05-22 David Turner <david@freetype.org>
+
+ * src/lzw/ftzopen.h, src/lzw/ftzopen.c: apply some "band-aid"
+ to avoid blowing up the heap in the case of malformed fonts.
+ related to bug #19910; *not* a real fix though...
+
+2007-05-20 Ismail Dönmez <ismail@pardus.org.tr>
* src/pshinter/pshrec.c (ps_mask_table_set_bits): Add `const'.
(ps_dimension_set_mask_bits): Remove `const'.
-2007-06-19 Werner Lemberg <wl@gnu.org>
+2007-05-19 Werner Lemberg <wl@gnu.org>
* src/sfnt/ttmtx.c (tt_face_get_metrics)
[!FT_CONFIG_OPTION_OLD_INTERNALS]: Another type-punning fix.
diff --git a/src/lzw/ftzopen.c b/src/lzw/ftzopen.c
index a9d25c5..f486d1b 100644
--- a/src/lzw/ftzopen.c
+++ b/src/lzw/ftzopen.c
@@ -87,6 +87,11 @@
FT_UInt old_size = state->stack_size;
FT_UInt new_size = old_size;
+ /* limit stack size to detect invalid files */
+ /* the magic number comes from the origin NetBSD zopen implementation */
+ if (state->stack_size >= 69001 )
+ return -1;
+
new_size = new_size + ( new_size >> 1 ) + 4;
if ( state->stack == state->stack_0 )
@@ -110,6 +115,7 @@
{
FT_UInt old_size = state->prefix_size;
FT_UInt new_size = old_size;
+ FT_UInt max_size = INT_MAX/(sizeof(FT_UShort)+sizeof(FT_Byte));
FT_Memory memory = state->memory;
FT_Error error;
@@ -119,6 +125,13 @@
else
new_size += new_size >> 2; /* don't grow too fast */
+ if (new_size < old_size || new_size > max_size)
+ {
+ new_size = max_size;
+ if (new_size == old_size)
+ return -1;
+ }
+
/*
* Note that the `suffix' array is located in the same memory block
* pointed to by `prefix'.
@@ -213,11 +226,11 @@
{
FT_ULong result = 0;
- FT_UInt num_bits = state->num_bits;
- FT_UInt free_ent = state->free_ent;
- FT_UInt old_char = state->old_char;
- FT_UInt old_code = state->old_code;
- FT_UInt in_code = state->in_code;
+ FT_UInt num_bits = state->num_bits;
+ FT_UInt free_ent = state->free_ent;
+ FT_UInt last_char = state->last_char;
+ FT_UInt old_code = state->old_code;
+ FT_UInt in_code = state->in_code;
if ( out_size == 0 )
@@ -255,15 +268,15 @@
if ( c < 0 )
goto Eof;
- old_code = old_char = (FT_UInt)c;
+ old_code = last_char = (FT_UInt)c;
if ( buffer )
- buffer[result] = (FT_Byte)old_char;
+ buffer[result] = (FT_Byte)last_char;
+
+ state->phase = FT_LZW_PHASE_CODE;
if ( ++result >= out_size )
goto Exit;
-
- state->phase = FT_LZW_PHASE_CODE;
}
/* fall-through */
@@ -303,7 +316,7 @@
/* special case for KwKwKwK */
if ( code - 256U >= free_ent )
{
- FTLZW_STACK_PUSH( old_char );
+ FTLZW_STACK_PUSH( last_char );
code = old_code;
}
@@ -314,8 +327,8 @@
}
}
- old_char = code;
- FTLZW_STACK_PUSH( old_char );
+ last_char = code;
+ FTLZW_STACK_PUSH( last_char );
state->phase = FT_LZW_PHASE_STACK;
}
@@ -344,7 +357,7 @@
FT_ASSERT( free_ent < state->prefix_size );
state->prefix[free_ent] = (FT_UShort)old_code;
- state->suffix[free_ent] = (FT_Byte) old_char;
+ state->suffix[free_ent] = (FT_Byte) last_char;
if ( ++free_ent == state->free_bits )
{
@@ -367,11 +380,11 @@
}
Exit:
- state->num_bits = num_bits;
- state->free_ent = free_ent;
- state->old_code = old_code;
- state->old_char = old_char;
- state->in_code = in_code;
+ state->num_bits = num_bits;
+ state->free_ent = free_ent;
+ state->old_code = old_code;
+ state->last_char = last_char;
+ state->in_code = in_code;
return result;
diff --git a/src/lzw/ftzopen.h b/src/lzw/ftzopen.h
index 8b1831b..220c1cc 100644
--- a/src/lzw/ftzopen.h
+++ b/src/lzw/ftzopen.h
@@ -128,7 +128,7 @@
FT_UInt free_ent; /* index of next free entry */
FT_UInt free_bits; /* if reached by free_ent, increment num_bits */
FT_UInt old_code;
- FT_UInt old_char;
+ FT_UInt last_char;
FT_UInt in_code;
FT_UShort* prefix; /* always dynamically allocated / reallocated */