real fix for bug #19910. the .Z format is really badly designed :-(
This commit is contained in:
parent
0d0365ec59
commit
3e2f953a10
|
@ -1,8 +1,8 @@
|
|||
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...
|
||||
* src/lzw/ftzopen.h, src/lzw/ftzopen.c: fix for bug #19910
|
||||
(heap blowup with very large .Z font file). The .Z format is
|
||||
*really* crappy :-(
|
||||
|
||||
2007-05-20 Ismail Dönmez <ismail@pardus.org.tr>
|
||||
|
||||
|
|
|
@ -23,59 +23,86 @@
|
|||
#include FT_INTERNAL_STREAM_H
|
||||
#include FT_INTERNAL_DEBUG_H
|
||||
|
||||
/* refill input buffer, return 0 on success, or -1 if eof */
|
||||
static int
|
||||
ft_lzwstate_refill( FT_LzwState state )
|
||||
{
|
||||
int result = -1;
|
||||
FT_ULong count;
|
||||
|
||||
if (state->in_eof)
|
||||
return -1;
|
||||
|
||||
if ( !state->in_eof )
|
||||
{
|
||||
FT_ULong count = FT_Stream_TryRead( state->source,
|
||||
state->in_buff,
|
||||
sizeof ( state->in_buff ) );
|
||||
count = FT_Stream_TryRead( state->source,
|
||||
state->buf_tab,
|
||||
state->num_bits ); /* WHY ?? */
|
||||
|
||||
state->in_cursor = state->in_buff;
|
||||
state->in_limit = state->in_buff + count;
|
||||
state->in_eof = FT_BOOL( count < sizeof ( state->in_buff ) );
|
||||
state->buf_size = (FT_UInt) count;
|
||||
state->buf_total += count;
|
||||
state->in_eof = FT_BOOL( count < state->num_bits );
|
||||
state->buf_offset = 0;
|
||||
state->buf_size = (state->buf_size << 3) - (state->num_bits-1);
|
||||
|
||||
if ( count > 0 )
|
||||
result = 0;
|
||||
}
|
||||
return result;
|
||||
if (count == 0) /* end of file */
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* return new code of 'num_bits', or -1 if eof */
|
||||
static FT_Int32
|
||||
ft_lzwstate_get_code( FT_LzwState state,
|
||||
FT_UInt num_bits )
|
||||
ft_lzwstate_get_code( FT_LzwState state )
|
||||
{
|
||||
FT_Int32 result = -1;
|
||||
FT_UInt32 pad = state->pad;
|
||||
FT_UInt pad_bits = state->pad_bits;
|
||||
FT_UInt num_bits = state->num_bits;
|
||||
FT_Int offset = state->buf_offset;
|
||||
FT_Byte* p;
|
||||
FT_Int result;
|
||||
|
||||
|
||||
while ( num_bits > pad_bits )
|
||||
if ( state->buf_clear ||
|
||||
offset >= state->buf_size ||
|
||||
state->free_ent >= state->free_bits )
|
||||
{
|
||||
if ( state->in_cursor >= state->in_limit &&
|
||||
ft_lzwstate_refill( state ) < 0 )
|
||||
goto Exit;
|
||||
|
||||
pad |= (FT_UInt32)(*state->in_cursor++) << pad_bits;
|
||||
pad_bits += 8;
|
||||
if ( state->free_ent >= state->free_bits )
|
||||
{
|
||||
state->num_bits = ++num_bits;
|
||||
state->free_bits = state->num_bits < state->max_bits
|
||||
? (FT_UInt)( ( 1UL << num_bits ) - 256 )
|
||||
: state->max_free + 1;
|
||||
}
|
||||
|
||||
result = (FT_Int32)( pad & LZW_MASK( num_bits ) );
|
||||
state->pad_bits = pad_bits - num_bits;
|
||||
state->pad = pad >> num_bits;
|
||||
if ( state->buf_clear )
|
||||
{
|
||||
state->num_bits = num_bits = LZW_INIT_BITS;
|
||||
state->free_bits = (FT_UInt)( ( 1UL << num_bits ) - 256 );
|
||||
state->buf_clear = 0;
|
||||
}
|
||||
|
||||
if ( ft_lzwstate_refill( state ) < 0 )
|
||||
return -1;
|
||||
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
state->buf_offset = offset + num_bits;
|
||||
|
||||
p = &state->buf_tab[offset >> 3];
|
||||
offset &= 7;
|
||||
result = *p++ >> offset;
|
||||
offset = 8-offset;
|
||||
num_bits -= offset;
|
||||
if (num_bits >= 8)
|
||||
{
|
||||
result |= *p++ << offset;
|
||||
offset += 8;
|
||||
num_bits -= 8;
|
||||
}
|
||||
if (num_bits > 0)
|
||||
result |= (*p & LZW_MASK(num_bits)) << offset;
|
||||
|
||||
Exit:
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* grow the character stack */
|
||||
static int
|
||||
ft_lzwstate_stack_grow( FT_LzwState state )
|
||||
|
@ -87,11 +114,6 @@
|
|||
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 )
|
||||
|
@ -115,7 +137,6 @@
|
|||
{
|
||||
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;
|
||||
|
||||
|
@ -125,13 +146,6 @@
|
|||
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'.
|
||||
|
@ -159,12 +173,11 @@
|
|||
FT_LOCAL_DEF( void )
|
||||
ft_lzwstate_reset( FT_LzwState state )
|
||||
{
|
||||
state->in_cursor = state->in_buff;
|
||||
state->in_limit = state->in_buff;
|
||||
state->in_eof = 0;
|
||||
state->pad_bits = 0;
|
||||
state->pad = 0;
|
||||
|
||||
state->buf_offset = 0;
|
||||
state->buf_size = 0;
|
||||
state->buf_clear = 0;
|
||||
state->buf_total = 0;
|
||||
state->stack_top = 0;
|
||||
state->num_bits = LZW_INIT_BITS;
|
||||
state->phase = FT_LZW_PHASE_START;
|
||||
|
@ -226,9 +239,7 @@
|
|||
{
|
||||
FT_ULong result = 0;
|
||||
|
||||
FT_UInt num_bits = state->num_bits;
|
||||
FT_UInt free_ent = state->free_ent;
|
||||
FT_UInt last_char = state->last_char;
|
||||
FT_UInt old_char = state->old_char;
|
||||
FT_UInt old_code = state->old_code;
|
||||
FT_UInt in_code = state->in_code;
|
||||
|
||||
|
@ -256,27 +267,27 @@
|
|||
if ( state->max_bits > LZW_MAX_BITS )
|
||||
goto Eof;
|
||||
|
||||
num_bits = LZW_INIT_BITS;
|
||||
free_ent = ( state->block_mode ? LZW_FIRST : LZW_CLEAR ) - 256;
|
||||
state->num_bits = LZW_INIT_BITS;
|
||||
state->free_ent = ( state->block_mode ? LZW_FIRST : LZW_CLEAR ) - 256;
|
||||
in_code = 0;
|
||||
|
||||
state->free_bits = num_bits < state->max_bits
|
||||
? (FT_UInt)( ( 1UL << num_bits ) - 256 )
|
||||
state->free_bits = state->num_bits < state->max_bits
|
||||
? (FT_UInt)( ( 1UL << state->num_bits ) - 256 )
|
||||
: state->max_free + 1;
|
||||
|
||||
c = ft_lzwstate_get_code( state, num_bits );
|
||||
c = ft_lzwstate_get_code( state );
|
||||
if ( c < 0 )
|
||||
goto Eof;
|
||||
|
||||
old_code = last_char = (FT_UInt)c;
|
||||
old_code = old_char = (FT_UInt)c;
|
||||
|
||||
if ( buffer )
|
||||
buffer[result] = (FT_Byte)last_char;
|
||||
|
||||
state->phase = FT_LZW_PHASE_CODE;
|
||||
buffer[result] = (FT_Byte)old_char;
|
||||
|
||||
if ( ++result >= out_size )
|
||||
goto Exit;
|
||||
|
||||
state->phase = FT_LZW_PHASE_CODE;
|
||||
}
|
||||
/* fall-through */
|
||||
|
||||
|
@ -287,7 +298,7 @@
|
|||
|
||||
|
||||
NextCode:
|
||||
c = ft_lzwstate_get_code( state, num_bits );
|
||||
c = ft_lzwstate_get_code( state );
|
||||
if ( c < 0 )
|
||||
goto Eof;
|
||||
|
||||
|
@ -295,14 +306,9 @@
|
|||
|
||||
if ( code == LZW_CLEAR && state->block_mode )
|
||||
{
|
||||
free_ent = ( LZW_FIRST - 1 ) - 256; /* why not LZW_FIRST-256 ? */
|
||||
num_bits = LZW_INIT_BITS;
|
||||
|
||||
state->free_bits = num_bits < state->max_bits
|
||||
? (FT_UInt)( ( 1UL << num_bits ) - 256 )
|
||||
: state->max_free + 1;
|
||||
|
||||
c = ft_lzwstate_get_code( state, num_bits );
|
||||
state->free_ent = ( LZW_FIRST - 1 ) - 256; /* why not LZW_FIRST-256 ? */
|
||||
state->buf_clear = 1;
|
||||
c = ft_lzwstate_get_code( state );
|
||||
if ( c < 0 )
|
||||
goto Eof;
|
||||
|
||||
|
@ -314,9 +320,9 @@
|
|||
if ( code >= 256U )
|
||||
{
|
||||
/* special case for KwKwKwK */
|
||||
if ( code - 256U >= free_ent )
|
||||
if ( code - 256U >= state->free_ent )
|
||||
{
|
||||
FTLZW_STACK_PUSH( last_char );
|
||||
FTLZW_STACK_PUSH( old_char );
|
||||
code = old_code;
|
||||
}
|
||||
|
||||
|
@ -327,8 +333,8 @@
|
|||
}
|
||||
}
|
||||
|
||||
last_char = code;
|
||||
FTLZW_STACK_PUSH( last_char );
|
||||
old_char = code;
|
||||
FTLZW_STACK_PUSH( old_char );
|
||||
|
||||
state->phase = FT_LZW_PHASE_STACK;
|
||||
}
|
||||
|
@ -348,25 +354,18 @@
|
|||
}
|
||||
|
||||
/* now create new entry */
|
||||
if ( free_ent < state->max_free )
|
||||
if ( state->free_ent < state->max_free )
|
||||
{
|
||||
if ( free_ent >= state->prefix_size &&
|
||||
if ( state->free_ent >= state->prefix_size &&
|
||||
ft_lzwstate_prefix_grow( state ) < 0 )
|
||||
goto Eof;
|
||||
|
||||
FT_ASSERT( free_ent < state->prefix_size );
|
||||
FT_ASSERT( state->free_ent < state->prefix_size );
|
||||
|
||||
state->prefix[free_ent] = (FT_UShort)old_code;
|
||||
state->suffix[free_ent] = (FT_Byte) last_char;
|
||||
state->prefix[state->free_ent] = (FT_UShort)old_code;
|
||||
state->suffix[state->free_ent] = (FT_Byte) old_char;
|
||||
|
||||
if ( ++free_ent == state->free_bits )
|
||||
{
|
||||
num_bits++;
|
||||
|
||||
state->free_bits = num_bits < state->max_bits
|
||||
? (FT_UInt)( ( 1UL << num_bits ) - 256 )
|
||||
: state->max_free + 1;
|
||||
}
|
||||
state->free_ent += 1;
|
||||
}
|
||||
|
||||
old_code = in_code;
|
||||
|
@ -380,10 +379,8 @@
|
|||
}
|
||||
|
||||
Exit:
|
||||
state->num_bits = num_bits;
|
||||
state->free_ent = free_ent;
|
||||
state->old_code = old_code;
|
||||
state->last_char = last_char;
|
||||
state->old_char = old_char;
|
||||
state->in_code = in_code;
|
||||
|
||||
return result;
|
||||
|
|
|
@ -112,13 +112,13 @@
|
|||
typedef struct _FT_LzwStateRec
|
||||
{
|
||||
FT_LzwPhase phase;
|
||||
|
||||
FT_Int in_eof;
|
||||
FT_Byte* in_cursor; /* current buffer pos */
|
||||
FT_Byte* in_limit; /* current buffer limit */
|
||||
|
||||
FT_UInt32 pad; /* a pad value where incoming bits were read */
|
||||
FT_Int pad_bits; /* number of meaningful bits in pad value */
|
||||
FT_Byte buf_tab[16];
|
||||
FT_Int buf_offset;
|
||||
FT_Int buf_size;
|
||||
FT_Bool buf_clear;
|
||||
FT_Int buf_total;
|
||||
|
||||
FT_UInt max_bits; /* max code bits, from file header */
|
||||
FT_Int block_mode; /* block mode flag, from file header */
|
||||
|
@ -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 last_char;
|
||||
FT_UInt old_char;
|
||||
FT_UInt in_code;
|
||||
|
||||
FT_UShort* prefix; /* always dynamically allocated / reallocated */
|
||||
|
@ -138,8 +138,6 @@
|
|||
FT_Byte* stack; /* character stack */
|
||||
FT_UInt stack_top;
|
||||
FT_UInt stack_size;
|
||||
|
||||
FT_Byte in_buff[FT_LZW_IN_BUFF_SIZE]; /* small read-buffer */
|
||||
FT_Byte stack_0[FT_LZW_DEFAULT_STACK_SIZE]; /* minimize heap alloc */
|
||||
|
||||
FT_Stream source; /* source stream */
|
||||
|
|
Loading…
Reference in New Issue