Commit message: fix possible OOB write in gif2tiff.c
CVE: CVE-2013-4244
CWE: CWE-119
Vulnerability description: The LZW decompressor in the gif2tiff tool in libtiff 4.0.3 and earlier allows context-dependent attackers to cause a denial of service (out-of-bounds write and crash) or possibly execute arbitrary code via a crafted GIF image.

Project: libtiff

convert(void)
{
    int ch;
    char* mode = "w";

    if (!checksignature())
        return (-1);
    readscreen();
    while ((ch = getc(infile)) != ';' && ch != EOF) {
        switch (ch) {
            case '\0':  break;  /* this kludge for non-standard files */
            case ',':   if (!readgifimage(mode))
                           return (-1);
			mode = "a";		/* subsequent images append */
                        break;
            case '!':   readextension();
                        break;
            default:    fprintf(stderr, "illegal GIF block type\n");
                        return (-1);
        }
    }
    return (0);
}

Project: libtiff

main(int argc, char* argv[])
{
    extern int optind;
    extern char *optarg;
    int c, status;

    while ((c = getopt(argc, argv, "c:r:")) != -1)
	    switch (c) {
	    case 'c':		/* compression scheme */
		    if (!processCompressOptions(optarg))
			    usage();
		    break;
	    case 'r':		/* rows/strip */
		    rowsperstrip = atoi(optarg);
		    break;
	    case '?':
		    usage();
		    /*NOTREACHED*/
	    }
    if (argc - optind != 2)
	    usage();

    makegamtab(GIFGAMMA);
    filename = argv[optind];
    imagename = argv[optind+1];
    if ((infile = fopen(imagename, "rb")) != NULL) {
	int c;
	fclose(infile);
	printf("overwrite %s? ", imagename); fflush(stdout);
	c = getc(stdin);
	if (c != 'y' && c != 'Y')
	    return (1);
    }
    if ((infile = fopen(filename, "rb")) == NULL) {
	perror(filename);
	return (1);
    }
    status = convert();
    fclose(infile);
    return (status);
}

Project: libtiff

makegamtab(float gam)
{
    int i;

    for(i=0; i<256; i++) 
	gamtab[i] = (unsigned short) (IMAX*pow(i/255.0,gam)+0.5);
}

Project: libtiff

processCompressOptions(char* opt)
{
	if (streq(opt, "none"))
		compression = COMPRESSION_NONE;
	else if (streq(opt, "packbits"))
		compression = COMPRESSION_PACKBITS;
	else if (strneq(opt, "lzw", 3)) {
		char* cp = strchr(opt, ':');
		if (cp)
			predictor = atoi(cp+1);
		compression = COMPRESSION_LZW;
	} else if (strneq(opt, "zip", 3)) {
		char* cp = strchr(opt, ':');
		if (cp)
			predictor = atoi(cp+1);
		compression = COMPRESSION_DEFLATE;
	} else
		return (0);
	return (1);
}

Project: libtiff

rasterize(int interleaved, char* mode)
{
    register unsigned long row;
    unsigned char *newras;
    unsigned char *ras;
    TIFF *tif;
    tstrip_t strip;
    tsize_t stripsize;

    if ((newras = (unsigned char*) _TIFFmalloc(width*height+EXTRAFUDGE)) == NULL) {
        fprintf(stderr, "not enough memory for image\n");
        return;
    }
#define DRAWSEGMENT(offset, step) {			\
        for (row = offset; row < height; row += step) {	\
            _TIFFmemcpy(newras + row*width, ras, width);\
            ras += width;                            	\
        }						\
    }
    ras = raster;
    if (interleaved) {
        DRAWSEGMENT(0, 8);
        DRAWSEGMENT(4, 8);
        DRAWSEGMENT(2, 4);
        DRAWSEGMENT(1, 2);
    } else 
        DRAWSEGMENT(0, 1);
#undef DRAWSEGMENT

    tif = TIFFOpen(imagename, mode);
    if (!tif) {
	TIFFError(imagename,"Can not open output image");
	exit(-1);
    }
    TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, (uint32) width);
    TIFFSetField(tif, TIFFTAG_IMAGELENGTH, (uint32) height);
    TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE);
    TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
    TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
    TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 
	rowsperstrip = TIFFDefaultStripSize(tif, rowsperstrip));
    TIFFSetField(tif, TIFFTAG_COMPRESSION, compression);
    switch (compression) {
    case COMPRESSION_LZW:
    case COMPRESSION_DEFLATE:
	    if (predictor != 0)
		    TIFFSetField(tif, TIFFTAG_PREDICTOR, predictor);
	    break;
    }
    TIFFSetField(tif, TIFFTAG_COLORMAP, red, green, blue);
    TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
    strip = 0;
    stripsize = TIFFStripSize(tif);
    for (row=0; row<height; row += rowsperstrip) {
	if (rowsperstrip > height-row) {
	    rowsperstrip = height-row;
	    stripsize = TIFFVStripSize(tif, rowsperstrip);
	}
	if (TIFFWriteEncodedStrip(tif, strip, newras+row*width, stripsize) < 0)
	    break;
	strip++;
    }
    TIFFClose(tif);

    _TIFFfree(newras);
}

Project: libtiff

readextension(void)
{
    int count;
    char buf[255];

    (void) getc(infile);
    while ((count = getc(infile)))
        fread(buf, 1, count, infile);
}

Project: libtiff

readgifimage(char* mode)
{
    unsigned char buf[9];
    int local, interleaved;
    unsigned char localmap[256][3];
    int localbits;
    int status;

    if (fread(buf, 1, 9, infile) == 0) {
        perror(filename);
	return (0);
    }
    width = buf[4] + (buf[5] << 8);
    height = buf[6] + (buf[7] << 8);
    local = buf[8] & 0x80;
    interleaved = buf[8] & 0x40;

    if (local == 0 && global == 0) {
        fprintf(stderr, "no colormap present for image\n");
        return (0);
    }
    if ((raster = (unsigned char*) _TIFFmalloc(width*height+EXTRAFUDGE)) == NULL) {
        fprintf(stderr, "not enough memory for image\n");
        return (0);
    }
    if (local) {
        localbits = (buf[8] & 0x7) + 1;

        fprintf(stderr, "   local colors: %d\n", 1<<localbits);

        fread(localmap, 3, ((size_t)1)<<localbits, infile);
        initcolors(localmap, 1<<localbits);
    } else if (global) {
        initcolors(globalmap, 1<<globalbits);
    }
    if ((status = readraster()))
	rasterize(interleaved, mode);
    _TIFFfree(raster);
    return status;
}

Project: libtiff

readraster(void)
{
    unsigned char *fill = raster;
    unsigned char buf[255];
    register int bits=0;
    register unsigned long datum=0;
    register unsigned char *ch;
    register int count, code;
    int status = 1;

    datasize = getc(infile);
    if (datasize > 12)
	return 0;
    clear = 1 << datasize;
    eoi = clear + 1;
    avail = clear + 2;
    oldcode = -1;
    codesize = datasize + 1;
    codemask = (1 << codesize) - 1;
    for (code = 0; code < clear; code++) {
	prefix[code] = 0;
	suffix[code] = code;
    }
    stackp = stack;
    for (count = getc(infile); count > 0; count = getc(infile)) {
	fread(buf,1,count,infile);
	for (ch=buf; count-- > 0; ch++) {
	    datum += (unsigned long) *ch << bits;
	    bits += 8;
	    while (bits >= codesize) {
		code = datum & codemask;
		datum >>= codesize;
		bits -= codesize;
		if (code == eoi) {               /* This kludge put in */
		    goto exitloop;               /* because some GIF files*/
		}                                /* aren't standard */
		if (!process(code, &fill)) {
		    status = 0;
		    goto exitloop;
		}
	    }
	}
	if (fill >= raster + width*height) {
	    fprintf(stderr, "raster full before eoi code\n");
	    break;
	}
    }
exitloop:
    if (fill != raster + width*height)  {
	fprintf(stderr, "warning: wrong rastersize: %ld bytes\n",
						      (long) (fill-raster));
	fprintf(stderr, "         instead of %ld bytes\n",
						      (long) width*height);
    }
    return status;
}

Project: libtiff

readscreen(void)
{
    unsigned char buf[7];

    fread(buf,1,7,infile);
    global = buf[4] & 0x80;
    if (global) {
        globalbits = (buf[4] & 0x07) + 1;
        fread(globalmap,3,((size_t)1)<<globalbits,infile);
    }
}

Project: libtiff
File: tiff2bw.c

usage(void)
{
	char buf[BUFSIZ];
	int i;

	setbuf(stderr, buf);
        fprintf(stderr, "%s\n\n", TIFFGetVersion());
	for (i = 0; stuff[i] != NULL; i++)
		fprintf(stderr, "%s\n", stuff[i]);
	exit(-1);
}