diff options
author | nlopess <none@none> | 2007-03-08 20:02:45 +0000 |
---|---|---|
committer | nlopess <none@none> | 2007-03-08 20:02:45 +0000 |
commit | 63e8e503c495e510bd179649895d11eb45908c84 (patch) | |
tree | 391e06ca981066a5d1b68f0d213f5677dcf3617f /src/gd_gif_in.c | |
parent | 3fa454d1902fe611a7d4031353bb92093b34220f (diff) | |
download | libgd-63e8e503c495e510bd179649895d11eb45908c84.tar.gz |
MFB: fix bug #52: Reading GIF images is not thread safe (static usage in private functions)
Diffstat (limited to 'src/gd_gif_in.c')
-rw-r--r-- | src/gd_gif_in.c | 210 |
1 files changed, 110 insertions, 100 deletions
diff --git a/src/gd_gif_in.c b/src/gd_gif_in.c index c76a7cb..a4c77f3 100644 --- a/src/gd_gif_in.c +++ b/src/gd_gif_in.c @@ -68,11 +68,29 @@ static struct { } Gif89 = { -1, -1, -1, 0 }; #endif +#define STACK_SIZE ((1<<(MAX_LWZ_BITS))*2) + +typedef struct { + unsigned char buf[280]; + int curbit, lastbit, done, last_byte; +} CODE_STATIC_DATA; + +typedef struct { + int fresh; + int code_size, set_code_size; + int max_code, max_code_size; + int firstcode, oldcode; + int clear_code, end_code; + int table[2][(1<< MAX_LWZ_BITS)]; + int stack[STACK_SIZE], *sp; + CODE_STATIC_DATA scd; +} LZW_STATIC_DATA; + static int ReadColorMap (gdIOCtx *fd, int number, unsigned char (*buffer)[256]); static int DoExtension (gdIOCtx *fd, int label, int *Transparent, int *ZeroDataBlockP); static int GetDataBlock (gdIOCtx *fd, unsigned char *buf, int *ZeroDataBlockP); -static int GetCode (gdIOCtx *fd, int code_size, int flag, int *ZeroDataBlockP); -static int LWZReadByte (gdIOCtx *fd, int flag, int input_code_size, int *ZeroDataBlockP); +static int GetCode (gdIOCtx *fd, CODE_STATIC_DATA *scd, int code_size, int flag, int *ZeroDataBlockP); +static int LWZReadByte (gdIOCtx *fd, LZW_STATIC_DATA *sd, char flag, int input_code_size, int *ZeroDataBlockP); static void ReadImage (gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap)[256], int interlace, int *ZeroDataBlockP); /*1.4//, int ignore); */ @@ -249,10 +267,11 @@ ReadColorMap(gdIOCtx *fd, int number, unsigned char (*buffer)[256]) static int DoExtension(gdIOCtx *fd, int label, int *Transparent, int *ZeroDataBlockP) { - static unsigned char buf[256]; + unsigned char buf[256]; switch (label) { case 0xf9: /* Graphic Control Extension */ + memset(buf, 0, 4); /* initialize a few bytes in the case the next function fails */ (void) GetDataBlock(fd, (unsigned char*) buf, ZeroDataBlockP); #if 0 Gif89.disposal = (buf[0] >> 2) & 0x7; @@ -311,120 +330,110 @@ GetDataBlock(gdIOCtx *fd, unsigned char *buf, int *ZeroDataBlockP) } static int -GetCode_(gdIOCtx *fd, int code_size, int flag, int *ZeroDataBlockP) +GetCode_(gdIOCtx *fd, CODE_STATIC_DATA *scd, int code_size, int flag, int *ZeroDataBlockP) { - static unsigned char buf[280]; - static int curbit, lastbit, done, last_byte; - int i, j, ret; - unsigned char count; + int i, j, ret; + unsigned char count; if (flag) { - curbit = 0; - lastbit = 0; - done = FALSE; + scd->curbit = 0; + scd->lastbit = 0; + scd->last_byte = 0; + scd->done = FALSE; return 0; } - if ( (curbit+code_size) >= lastbit) { - if (done) { - if (curbit >= lastbit) { + if ( (scd->curbit + code_size) >= scd->lastbit) { + if (scd->done) { + if (scd->curbit >= scd->lastbit) { /* Oh well */ } return -1; } - buf[0] = buf[last_byte-2]; - buf[1] = buf[last_byte-1]; + scd->buf[0] = scd->buf[scd->last_byte-2]; + scd->buf[1] = scd->buf[scd->last_byte-1]; - if ((count = GetDataBlock(fd, &buf[2], ZeroDataBlockP)) <= 0) - done = TRUE; + if ((count = GetDataBlock(fd, &scd->buf[2], ZeroDataBlockP)) <= 0) + scd->done = TRUE; - last_byte = 2 + count; - curbit = (curbit - lastbit) + 16; - lastbit = (2+count)*8 ; + scd->last_byte = 2 + count; + scd->curbit = (scd->curbit - scd->lastbit) + 16; + scd->lastbit = (2+count)*8 ; } ret = 0; - for (i = curbit, j = 0; j < code_size; ++i, ++j) - ret |= ((buf[ i / 8 ] & (1 << (i % 8))) != 0) << j; + for (i = scd->curbit, j = 0; j < code_size; ++i, ++j) + ret |= ((scd->buf[ i / 8 ] & (1 << (i % 8))) != 0) << j; - curbit += code_size; + scd->curbit += code_size; return ret; } static int -GetCode(gdIOCtx *fd, int code_size, int flag, int *ZeroDataBlockP) +GetCode(gdIOCtx *fd, CODE_STATIC_DATA *scd, int code_size, int flag, int *ZeroDataBlockP) { int rv; - rv = GetCode_(fd,code_size,flag, ZeroDataBlockP); + rv = GetCode_(fd, scd, code_size,flag, ZeroDataBlockP); if (VERBOSE) printf("[GetCode(,%d,%d) returning %d]\n",code_size,flag,rv); return(rv); } -#define STACK_SIZE ((1<<(MAX_LWZ_BITS))*2) static int -LWZReadByte_(gdIOCtx *fd, int flag, int input_code_size, int *ZeroDataBlockP) +LWZReadByte_(gdIOCtx *fd, LZW_STATIC_DATA *sd, char flag, int input_code_size, int *ZeroDataBlockP) { - static int fresh = FALSE; - int code, incode; - static int code_size, set_code_size; - static int max_code, max_code_size; - static int firstcode, oldcode; - static int clear_code, end_code; - static int table[2][(1<< MAX_LWZ_BITS)]; - static int stack[STACK_SIZE], *sp; - register int i; + int code, incode, i; if (flag) { - set_code_size = input_code_size; - code_size = set_code_size+1; - clear_code = 1 << set_code_size ; - end_code = clear_code + 1; - max_code_size = 2*clear_code; - max_code = clear_code+2; - - GetCode(fd, 0, TRUE, ZeroDataBlockP); + sd->set_code_size = input_code_size; + sd->code_size = sd->set_code_size+1; + sd->clear_code = 1 << sd->set_code_size ; + sd->end_code = sd->clear_code + 1; + sd->max_code_size = 2*sd->clear_code; + sd->max_code = sd->clear_code+2; + + GetCode(fd, &sd->scd, 0, TRUE, ZeroDataBlockP); - fresh = TRUE; + sd->fresh = TRUE; - for (i = 0; i < clear_code; ++i) { - table[0][i] = 0; - table[1][i] = i; + for (i = 0; i < sd->clear_code; ++i) { + sd->table[0][i] = 0; + sd->table[1][i] = i; } for (; i < (1<<MAX_LWZ_BITS); ++i) - table[0][i] = table[1][0] = 0; + sd->table[0][i] = sd->table[1][0] = 0; - sp = stack; + sd->sp = sd->stack; return 0; - } else if (fresh) { - fresh = FALSE; + } else if (sd->fresh) { + sd->fresh = FALSE; do { - firstcode = oldcode = - GetCode(fd, code_size, FALSE, ZeroDataBlockP); - } while (firstcode == clear_code); - return firstcode; + sd->firstcode = sd->oldcode = + GetCode(fd, &sd->scd, sd->code_size, FALSE, ZeroDataBlockP); + } while (sd->firstcode == sd->clear_code); + return sd->firstcode; } - if (sp > stack) - return *--sp; + if (sd->sp > sd->stack) + return *--sd->sp; - while ((code = GetCode(fd, code_size, FALSE, ZeroDataBlockP)) >= 0) { - if (code == clear_code) { - for (i = 0; i < clear_code; ++i) { - table[0][i] = 0; - table[1][i] = i; + while ((code = GetCode(fd, &sd->scd, sd->code_size, FALSE, ZeroDataBlockP)) >= 0) { + if (code == sd->clear_code) { + for (i = 0; i < sd->clear_code; ++i) { + sd->table[0][i] = 0; + sd->table[1][i] = i; } for (; i < (1<<MAX_LWZ_BITS); ++i) - table[0][i] = table[1][i] = 0; - code_size = set_code_size+1; - max_code_size = 2*clear_code; - max_code = clear_code+2; - sp = stack; - firstcode = oldcode = - GetCode(fd, code_size, FALSE, ZeroDataBlockP); - return firstcode; - } else if (code == end_code) { + sd->table[0][i] = sd->table[1][i] = 0; + sd->code_size = sd->set_code_size+1; + sd->max_code_size = 2*sd->clear_code; + sd->max_code = sd->clear_code+2; + sd->sp = sd->stack; + sd->firstcode = sd->oldcode = + GetCode(fd, &sd->scd, sd->code_size, FALSE, ZeroDataBlockP); + return sd->firstcode; + } else if (code == sd->end_code) { int count; unsigned char buf[260]; @@ -440,55 +449,55 @@ LWZReadByte_(gdIOCtx *fd, int flag, int input_code_size, int *ZeroDataBlockP) incode = code; - if (sp == (stack + STACK_SIZE)) { + if (sd->sp == (sd->stack + STACK_SIZE)) { /* Bad compressed data stream */ return -1; } - if (code >= max_code) { - *sp++ = firstcode; - code = oldcode; + if (code >= sd->max_code) { + *sd->sp++ = sd->firstcode; + code = sd->oldcode; } - while (code >= clear_code) { - if (sp == (stack + STACK_SIZE)) { + while (code >= sd->clear_code) { + if (sd->sp == (sd->stack + STACK_SIZE)) { /* Bad compressed data stream */ return -1; } - *sp++ = table[1][code]; - if (code == table[0][code]) { + *sd->sp++ = sd->table[1][code]; + if (code == sd->table[0][code]) { /* Oh well */ } - code = table[0][code]; + code = sd->table[0][code]; } - *sp++ = firstcode = table[1][code]; + *sd->sp++ = sd->firstcode = sd->table[1][code]; - if ((code = max_code) <(1<<MAX_LWZ_BITS)) { - table[0][code] = oldcode; - table[1][code] = firstcode; - ++max_code; - if ((max_code >= max_code_size) && - (max_code_size < (1<<MAX_LWZ_BITS))) { - max_code_size *= 2; - ++code_size; + if ((code = sd->max_code) <(1<<MAX_LWZ_BITS)) { + sd->table[0][code] = sd->oldcode; + sd->table[1][code] = sd->firstcode; + ++sd->max_code; + if ((sd->max_code >= sd->max_code_size) && + (sd->max_code_size < (1<<MAX_LWZ_BITS))) { + sd->max_code_size *= 2; + ++sd->code_size; } } - oldcode = incode; + sd->oldcode = incode; - if (sp > stack) - return *--sp; + if (sd->sp > sd->stack) + return *--sd->sp; } return code; } static int -LWZReadByte(gdIOCtx *fd, int flag, int input_code_size, int *ZeroDataBlockP) +LWZReadByte(gdIOCtx *fd, LZW_STATIC_DATA *sd, char flag, int input_code_size, int *ZeroDataBlockP) { int rv; - rv = LWZReadByte_(fd,flag,input_code_size, ZeroDataBlockP); + rv = LWZReadByte_(fd, sd, flag, input_code_size, ZeroDataBlockP); if (VERBOSE) printf("[LWZReadByte(,%d,%d) returning %d]\n",flag,input_code_size,rv); return(rv); } @@ -500,6 +509,7 @@ ReadImage(gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap) int v; int xpos = 0, ypos = 0, pass = 0; int i; + LZW_STATIC_DATA sd; /* ** Initialize the Compression routines @@ -521,7 +531,7 @@ ReadImage(gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap) } /* Many (perhaps most) of these colors will remain marked open. */ im->colorsTotal = gdMaxColors; - if (LWZReadByte(fd, TRUE, c, ZeroDataBlockP) < 0) { + if (LWZReadByte(fd, &sd, TRUE, c, ZeroDataBlockP) < 0) { return; } @@ -530,12 +540,12 @@ ReadImage(gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap) ** REMOVED For 1.4 */ /*if (ignore) { */ - /* while (LWZReadByte(fd, FALSE, c) >= 0) */ + /* while (LWZReadByte(fd, &sd, FALSE, c) >= 0) */ /* ; */ /* return; */ /*} */ - while ((v = LWZReadByte(fd,FALSE,c, ZeroDataBlockP)) >= 0 ) { + while ((v = LWZReadByte(fd, &sd, FALSE, c, ZeroDataBlockP)) >= 0 ) { /* This how we recognize which colors are actually used. */ if (im->open[v]) { im->open[v] = 0; @@ -577,7 +587,7 @@ ReadImage(gdImagePtr im, gdIOCtx *fd, int len, int height, unsigned char (*cmap) } fini: - if (LWZReadByte(fd,FALSE,c, ZeroDataBlockP)>=0) { + if (LWZReadByte(fd, &sd, FALSE, c, ZeroDataBlockP) >=0) { /* Ignore extra */ } } |