summaryrefslogtreecommitdiff
path: root/src/gd_gif_in.c
diff options
context:
space:
mode:
authornlopess <none@none>2007-03-08 20:02:45 +0000
committernlopess <none@none>2007-03-08 20:02:45 +0000
commit63e8e503c495e510bd179649895d11eb45908c84 (patch)
tree391e06ca981066a5d1b68f0d213f5677dcf3617f /src/gd_gif_in.c
parent3fa454d1902fe611a7d4031353bb92093b34220f (diff)
downloadlibgd-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.c210
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 */
}
}