Hi, attached is a patch that fixes the described issues which I am going to upload as a 0-day NMU as there was no reaction on these bugs yet.
It will be also archived on: http://people.debian.org/~nion/nmu-diff/ghostscript-8.64~dfsg-1_8.64~dfsg-1.1.patch Kind regards Nico -- Nico Golde - http://www.ngolde.de - n...@jabber.ccc.de - GPG: 0x73647CFF For security reasons, all text in this mail is double-rot13 encrypted.
diff -u ghostscript-8.64~dfsg/debian/changelog ghostscript-8.64~dfsg/debian/changelog --- ghostscript-8.64~dfsg/debian/changelog +++ ghostscript-8.64~dfsg/debian/changelog @@ -1,3 +1,20 @@ +ghostscript (8.64~dfsg-1.1) unstable; urgency=high + + * Non-maintainer upload by the Security Team. + * This update fixes various security issues: + - CVE-2009-0792: multiple integer overflows in the icc library + can cause a heap-based buffer overflow possibly leading to arbitray + code execution. + - CVE-2009-0584/CVE-2009-0583: Multiple integer overflows causing an + application crash or possibly arbitrary code execution. + - CVE-2009-0196: heap-based buffer overflow in big2_decode_symbol_dict() + leading to arbitrary code execution via a crafted JBIG2 symbol + dictionary segment. + . + (Closes: #524915, #522416, #524803) + + -- Nico Golde <n...@debian.org> Wed, 22 Apr 2009 00:19:51 +0200 + ghostscript (8.64~dfsg-1) unstable; urgency=low * New upstream release. diff -u ghostscript-8.64~dfsg/debian/patches/00list ghostscript-8.64~dfsg/debian/patches/00list --- ghostscript-8.64~dfsg/debian/patches/00list +++ ghostscript-8.64~dfsg/debian/patches/00list @@ -8,0 +9,2 @@ +73_CVE-2009-0792_CVE-2009-0584_CVE-2009-0583 +74_CVE-2009-0196 only in patch2: unchanged: --- ghostscript-8.64~dfsg.orig/debian/patches/74_CVE-2009-0196.dpatch +++ ghostscript-8.64~dfsg/debian/patches/74_CVE-2009-0196.dpatch @@ -0,0 +1,26 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +## 74_CVE-2009-0196.dpatch by Nico Golde <n...@debian.org> +## +## All lines beginning with `## DP:' are a description of the patch. +## DP: CVE-2009-0196 + +...@dpatch@ +diff -urNad ghostscript-8.64~dfsg~/jbig2dec/jbig2_symbol_dict.c ghostscript-8.64~dfsg/jbig2dec/jbig2_symbol_dict.c +--- ghostscript-8.64~dfsg~/jbig2dec/jbig2_symbol_dict.c 2007-12-11 09:29:58.000000000 +0100 ++++ ghostscript-8.64~dfsg/jbig2dec/jbig2_symbol_dict.c 2009-04-21 23:57:26.000000000 +0200 +@@ -699,6 +699,15 @@ + exrunlength = params->SDNUMEXSYMS; + else + code = jbig2_arith_int_decode(IAEX, as, &exrunlength); ++ if (exrunlength > params->SDNUMEXSYMS - j) { ++ jbig2_error(ctx, JBIG2_SEVERITY_FATAL, segment->number, ++ "runlength too large in export symbol table (%d > %d - %d)\n", ++ exrunlength, params->SDNUMEXSYMS, j); ++ jbig2_sd_release(ctx, SDEXSYMS); ++ /* skip to the cleanup code and return SDEXSYMS = NULL */ ++ SDEXSYMS = NULL; ++ break; ++ } + for(k = 0; k < exrunlength; k++) + if (exflag) { + SDEXSYMS->glyphs[j++] = (i < m) ? only in patch2: unchanged: --- ghostscript-8.64~dfsg.orig/debian/patches/73_CVE-2009-0792_CVE-2009-0584_CVE-2009-0583.dpatch +++ ghostscript-8.64~dfsg/debian/patches/73_CVE-2009-0792_CVE-2009-0584_CVE-2009-0583.dpatch @@ -0,0 +1,1159 @@ +#! /bin/sh /usr/share/dpatch/dpatch-run +## 73_CVE-2009-0792.dpatch by Nico Golde <n...@debian.org> +## +## All lines beginning with `## DP:' are a description of the patch. +## DP: fixing various integer overflows + +...@dpatch@ +diff -urNad ghostscript-8.64~dfsg~/icclib/icc.c ghostscript-8.64~dfsg/icclib/icc.c +--- ghostscript-8.64~dfsg~/icclib/icc.c 2008-05-09 06:12:01.000000000 +0200 ++++ ghostscript-8.64~dfsg/icclib/icc.c 2009-04-22 01:44:37.000000000 +0200 +@@ -152,6 +152,8 @@ + * Various bug fixes and enhancements. + */ + ++#include <limits.h> ++#include <stdint.h> + #include <stdio.h> + #include <stdlib.h> + #include <stdarg.h> +@@ -313,8 +315,11 @@ + icmFileMem *p = (icmFileMem *)pp; + size_t len; + ++ if (count > 0 && size > SIZE_MAX / count) ++ return 0; ++ + len = size * count; +- if ((p->cur + len) >= p->end) { /* Too much */ ++ if (len > (p->end - p->cur)) { /* Too much */ + if (size > 0) + count = (p->end - p->cur)/size; + else +@@ -1634,6 +1639,8 @@ + + /* Allocate a file write buffer */ + len = p->get_size((icmBase *)p); ++ if (icp->errc) ++ return icp->errc; + if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) { + sprintf(icp->err,"icmUInt8Array_write malloc() failed"); + return icp->errc = 2; +@@ -1698,7 +1705,7 @@ + if (p->size != p->_size) { + if (p->data != NULL) + icp->al->free(icp->al, p->data); +- if ((p->data = (unsigned int *) icp->al->malloc(icp->al, p->size * sizeof(unsigned int))) == NULL) { ++ if ((p->data = (unsigned int *) icp->al->calloc(icp->al, p->size, sizeof(unsigned int))) == NULL) { + sprintf(icp->err,"icmUInt8Array_alloc: malloc() of icmUInt8Array data failed"); + return icp->errc = 2; + } +@@ -1749,6 +1756,10 @@ + icmUInt16Array *p = (icmUInt16Array *)pp; + unsigned int len = 0; + len += 8; /* 8 bytes for tag and padding */ ++ if (p->size > (UINT_MAX - len) / 2) { ++ p->icp->errc = 1; ++ return (unsigned int) -1; ++ } + len += p->size * 2; /* 2 bytes for each UInt16 */ + return len; + } +@@ -1821,6 +1832,8 @@ + + /* Allocate a file write buffer */ + len = p->get_size((icmBase *)p); ++ if (icp->errc) ++ return icp->errc; + if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) { + sprintf(icp->err,"icmUInt16Array_write malloc() failed"); + return icp->errc = 2; +@@ -1885,7 +1898,7 @@ + if (p->size != p->_size) { + if (p->data != NULL) + icp->al->free(icp->al, p->data); +- if ((p->data = (unsigned int *) icp->al->malloc(icp->al, p->size * sizeof(unsigned int))) == NULL) { ++ if ((p->data = (unsigned int *) icp->al->calloc(icp->al, p->size, sizeof(unsigned int))) == NULL) { + sprintf(icp->err,"icmUInt16Array_alloc: malloc() of icmUInt16Array data failed"); + return icp->errc = 2; + } +@@ -1936,6 +1949,10 @@ + icmUInt32Array *p = (icmUInt32Array *)pp; + unsigned int len = 0; + len += 8; /* 8 bytes for tag and padding */ ++ if (p->size > (UINT_MAX - len) / 4) { ++ p->icp->errc = 1; ++ return (unsigned int) -1; ++ } + len += p->size * 4; /* 4 bytes for each UInt32 */ + return len; + } +@@ -2008,6 +2025,8 @@ + + /* Allocate a file write buffer */ + len = p->get_size((icmBase *)p); ++ if (icp->errc) ++ return icp->errc; + if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) { + sprintf(icp->err,"icmUInt32Array_write malloc() failed"); + return icp->errc = 2; +@@ -2072,7 +2091,7 @@ + if (p->size != p->_size) { + if (p->data != NULL) + icp->al->free(icp->al, p->data); +- if ((p->data = (unsigned int *) icp->al->malloc(icp->al, p->size * sizeof(unsigned int))) == NULL) { ++ if ((p->data = (unsigned int *) icp->al->calloc(icp->al, p->size, sizeof(unsigned int))) == NULL) { + sprintf(icp->err,"icmUInt32Array_alloc: malloc() of icmUInt32Array data failed"); + return icp->errc = 2; + } +@@ -2123,6 +2142,10 @@ + icmUInt64Array *p = (icmUInt64Array *)pp; + unsigned int len = 0; + len += 8; /* 8 bytes for tag and padding */ ++ if (p->size > (UINT_MAX - len) / 8) { ++ p->icp->errc = 1; ++ return (unsigned int) -1; ++ } + len += p->size * 8; /* 8 bytes for each UInt64 */ + return len; + } +@@ -2195,6 +2218,8 @@ + + /* Allocate a file write buffer */ + len = p->get_size((icmBase *)p); ++ if (icp->errc) ++ return icp->errc; + if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) { + sprintf(icp->err,"icmUInt64Array_write malloc() failed"); + return icp->errc = 2; +@@ -2259,7 +2284,7 @@ + if (p->size != p->_size) { + if (p->data != NULL) + icp->al->free(icp->al, p->data); +- if ((p->data = (icmUint64 *) icp->al->malloc(icp->al, p->size * sizeof(icmUint64))) == NULL) { ++ if ((p->data = (icmUint64 *) icp->al->calloc(icp->al, p->size, sizeof(icmUint64))) == NULL) { + sprintf(icp->err,"icmUInt64Array_alloc: malloc() of icmUInt64Array data failed"); + return icp->errc = 2; + } +@@ -2310,6 +2335,10 @@ + icmU16Fixed16Array *p = (icmU16Fixed16Array *)pp; + unsigned int len = 0; + len += 8; /* 8 bytes for tag and padding */ ++ if (p->size > (UINT_MAX - len) / 4) { ++ p->icp->errc = 1; ++ return (unsigned int) -1; ++ } + len += p->size * 4; /* 4 byte for each U16Fixed16 */ + return len; + } +@@ -2382,6 +2411,8 @@ + + /* Allocate a file write buffer */ + len = p->get_size((icmBase *)p); ++ if (icp->errc) ++ return icp->errc; + if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) { + sprintf(icp->err,"icmU16Fixed16Array_write malloc() failed"); + return icp->errc = 2; +@@ -2446,7 +2477,7 @@ + if (p->size != p->_size) { + if (p->data != NULL) + icp->al->free(icp->al, p->data); +- if ((p->data = (double *) icp->al->malloc(icp->al, p->size * sizeof(double))) == NULL) { ++ if ((p->data = (double *) icp->al->calloc(icp->al, p->size, sizeof(double))) == NULL) { + sprintf(icp->err,"icmU16Fixed16Array_alloc: malloc() of icmU16Fixed16Array data failed"); + return icp->errc = 2; + } +@@ -2497,6 +2528,10 @@ + icmS15Fixed16Array *p = (icmS15Fixed16Array *)pp; + unsigned int len = 0; + len += 8; /* 8 bytes for tag and padding */ ++ if (p->size > (UINT_MAX - len) / 4) { ++ p->icp->errc = 1; ++ return (unsigned int) - 1; ++ } + len += p->size * 4; /* 4 byte for each S15Fixed16 */ + return len; + } +@@ -2569,6 +2604,8 @@ + + /* Allocate a file write buffer */ + len = p->get_size((icmBase *)p); ++ if (icp->errc) ++ return icp->errc; + if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) { + sprintf(icp->err,"icmS15Fixed16Array_write malloc() failed"); + return icp->errc = 2; +@@ -2633,7 +2670,7 @@ + if (p->size != p->_size) { + if (p->data != NULL) + icp->al->free(icp->al, p->data); +- if ((p->data = (double *) icp->al->malloc(icp->al, p->size * sizeof(double))) == NULL) { ++ if ((p->data = (double *) icp->al->calloc(icp->al, p->size, sizeof(double))) == NULL) { + sprintf(icp->err,"icmS15Fixed16Array_alloc: malloc() of icmS15Fixed16Array data failed"); + return icp->errc = 2; + } +@@ -2726,6 +2763,10 @@ + icmXYZArray *p = (icmXYZArray *)pp; + unsigned int len = 0; + len += 8; /* 8 bytes for tag and padding */ ++ if (p->size > (UINT_MAX - len) / 12) { ++ p->icp->errc = 1; ++ return (unsigned int) - 1; ++ } + len += p->size * 12; /* 12 bytes for each XYZ */ + return len; + } +@@ -2798,6 +2839,8 @@ + + /* Allocate a file write buffer */ + len = p->get_size((icmBase *)p); ++ if (icp->errc) ++ return icp->errc; + if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) { + sprintf(icp->err,"icmXYZArray_write malloc() failed"); + return icp->errc = 2; +@@ -2865,7 +2908,7 @@ + if (p->size != p->_size) { + if (p->data != NULL) + icp->al->free(icp->al, p->data); +- if ((p->data = (icmXYZNumber *) icp->al->malloc(icp->al, p->size * sizeof(icmXYZNumber))) == NULL) { ++ if ((p->data = (icmXYZNumber *) icp->al->calloc(icp->al, p->size, sizeof(icmXYZNumber))) == NULL) { + sprintf(icp->err,"icmXYZArray_alloc: malloc() of icmXYZArray data failed"); + return icp->errc = 2; + } +@@ -2939,7 +2982,7 @@ + rv |= 1; + } + ix = (int)floor(val); /* Coordinate */ +- if (ix > (p->size-2)) ++ if (ix < 0 || ix > (p->size-2)) + ix = (p->size-2); + w = val - (double)ix; /* weight */ + val = p->data[ix]; +@@ -2961,6 +3004,11 @@ + ) { + int i; + ++ if (size > INT_MAX - 2) ++ /* Although rt->size is unsigned long, the rt data ++ * structure uses int data types to store indices. */ ++ return 2; ++ + rt->size = size; /* Stash pointers to these away */ + rt->data = data; + +@@ -2979,7 +3027,7 @@ + rt->qscale = (double)rt->rsize/(rt->rmax - rt->rmin); /* Scale factor to quantize to */ + + /* Initialize the reverse lookup structures, and get overall min/max */ +- if ((rt->rlists = (int **) icp->al->calloc(icp->al, 1, rt->rsize * sizeof(int *))) == NULL) { ++ if ((rt->rlists = (int **) icp->al->calloc(icp->al, rt->rsize, sizeof(int *))) == NULL) { + return 2; + } + +@@ -2992,6 +3040,15 @@ + int t; + t = s; s = e; e = t; + } ++ /* s and e should both be in the range [0,rt->rsize] ++ * now, but let's not rely on floating point ++ * calculations -- double-check. */ ++ if (s < 0) ++ s = 0; ++ if (e < 0) ++ e = 0; ++ if (s >= rt->rsize) ++ s = rt->rsize-1; + if (e >= rt->rsize) + e = rt->rsize-1; + +@@ -3001,7 +3058,7 @@ + int nf; /* Next free slot */ + if (rt->rlists[j] == NULL) { /* No allocation */ + as = 5; /* Start with space for 5 */ +- if ((rt->rlists[j] = (int *) icp->al->malloc(icp->al, sizeof(int) * as)) == NULL) { ++ if ((rt->rlists[j] = (int *) icp->al->calloc(icp->al, sizeof(int), as)) == NULL) { + return 2; + } + rt->rlists[j][0] = as; +@@ -3010,6 +3067,9 @@ + as = rt->rlists[j][0]; /* Allocate space for this list */ + nf = rt->rlists[j][1]; /* Next free location in list */ + if (nf >= as) { /* need to expand space */ ++ if (as > INT_MAX / 2 / sizeof (int)) ++ return 2; ++ + as *= 2; + rt->rlists[j] = (int *) icp->al->realloc(icp->al,rt->rlists[j], sizeof(int) * as); + if (rt->rlists[j] == NULL) { +@@ -3061,7 +3121,7 @@ + val = rsize_1; + ix = (int)floor(val); /* Coordinate */ + +- if (ix > (rt->size-2)) ++ if (ix < 0 || ix > (rt->size-2)) + ix = (rt->size-2); + if (rt->rlists[ix] != NULL) { /* There is a list of fwd candidates */ + /* For each candidate forward range */ +@@ -3088,6 +3148,7 @@ + /* We have failed to find an exact value, so return the nearest value */ + /* (This is slow !) */ + val = fabs(ival - rt->data[0]); ++ /* rt->size is known to be < INT_MAX */ + for (k = 0, i = 1; i < rt->size; i++) { + double er; + er = fabs(ival - rt->data[i]); +@@ -3141,6 +3202,10 @@ + icmCurve *p = (icmCurve *)pp; + unsigned int len = 0; + len += 12; /* 12 bytes for tag, padding and count */ ++ if (p->size > (UINT_MAX - len) / 2) { ++ p->icp->errc = 1; ++ return (unsigned int) - 1; ++ } + len += p->size * 2; /* 2 bytes for each UInt16 */ + return len; + } +@@ -3238,6 +3303,8 @@ + + /* Allocate a file write buffer */ + len = p->get_size((icmBase *)p); ++ if (icp->errc) ++ return icp->errc; + if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) { + sprintf(icp->err,"icmCurve_write malloc() failed"); + return icp->errc = 2; +@@ -3347,7 +3414,7 @@ + if (p->size != p->_size) { + if (p->data != NULL) + icp->al->free(icp->al, p->data); +- if ((p->data = (double *) icp->al->malloc(icp->al, p->size * sizeof(double))) == NULL) { ++ if ((p->data = (double *) icp->al->calloc(icp->al, p->size, sizeof(double))) == NULL) { + sprintf(icp->err,"icmCurve_alloc: malloc() of icmCurve data failed"); + return icp->errc = 2; + } +@@ -3493,6 +3560,8 @@ + + /* Allocate a file write buffer */ + len = p->get_size((icmBase *)p); ++ if (icp->errc) ++ return icp->errc; + if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) { + sprintf(icp->err,"icmData_write malloc() failed"); + return icp->errc = 2; +@@ -3620,7 +3689,7 @@ + if (p->size != p->_size) { + if (p->data != NULL) + icp->al->free(icp->al, p->data); +- if ((p->data = (unsigned char *) icp->al->malloc(icp->al, p->size * sizeof(unsigned char))) == NULL) { ++ if ((p->data = (unsigned char *) icp->al->calloc(icp->al, p->size, sizeof(unsigned char))) == NULL) { + sprintf(icp->err,"icmData_alloc: malloc() of icmData data failed"); + return icp->errc = 2; + } +@@ -3745,6 +3814,8 @@ + + /* Allocate a file write buffer */ + len = p->get_size((icmBase *)p); ++ if (icp->errc) ++ return icp->errc; + if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) { + sprintf(icp->err,"icmText_write malloc() failed"); + return icp->errc = 2; +@@ -3834,7 +3905,7 @@ + if (p->size != p->_size) { + if (p->data != NULL) + icp->al->free(icp->al, p->data); +- if ((p->data = (char *) icp->al->malloc(icp->al, p->size * sizeof(char))) == NULL) { ++ if ((p->data = (char *) icp->al->calloc(icp->al, p->size, sizeof(char))) == NULL) { + sprintf(icp->err,"icmText_alloc: malloc() of icmText data failed"); + return icp->errc = 2; + } +@@ -4038,6 +4109,8 @@ + + /* Allocate a file write buffer */ + len = p->get_size((icmBase *)p); ++ if (icp->errc) ++ return icp->errc; + if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) { + sprintf(icp->err,"icmDateTimeNumber_write malloc() failed"); + return icp->errc = 2; +@@ -4128,11 +4201,15 @@ + /* icmLut object */ + + /* Utility function - raise one integer to an integer power */ +-static unsigned int uipow(unsigned int a, unsigned int b) { ++static int uipow(unsigned int a, unsigned int b, unsigned int *ret) { + unsigned int rv = 1; +- for (; b > 0; b--) ++ for (; b > 0; b--) { ++ if (a > 0 && rv > UINT_MAX / a) ++ return 1; + rv *= a; +- return rv; ++ } ++ *ret = rv; ++ return 0; + } + + /* - - - - - - - - - - - - - - - - */ +@@ -4242,7 +4319,7 @@ + rv |= 1; + } + ix = (int)floor(val); /* Grid coordinate */ +- if (ix > (p->inputEnt-2)) ++ if (ix < 0 || ix > (p->inputEnt-2)) + ix = (p->inputEnt-2); + w = val - (double)ix; /* weight */ + val = table[ix]; +@@ -4268,7 +4345,7 @@ + if (p->inputChan <= 8) { + gw = GW; /* Use stack allocation */ + } else { +- if ((gw = (double *) icp->al->malloc(icp->al, (1 << p->inputChan) * sizeof(double))) == NULL) { ++ if ((gw = (double *) icp->al->calloc(icp->al, (1 << p->inputChan), sizeof(double))) == NULL) { + sprintf(icp->err,"icmLut_lookup_clut: malloc() failed"); + return icp->errc = 2; + } +@@ -4301,7 +4378,7 @@ + rv |= 1; + } + x = (int)floor(val); /* Grid coordinate */ +- if (x > clutPoints_2) ++ if (x < 0 || x > clutPoints_2) + x = clutPoints_2; + co[e] = val - (double)x; /* 1.0 - weight */ + gp += x * p->dinc[e]; /* Add index offset for base of cube */ +@@ -4374,7 +4451,7 @@ + rv |= 1; + } + x = (int)floor(val); /* Grid coordinate */ +- if (x > clutPoints_2) ++ if (x < 0 || x > clutPoints_2) + x = clutPoints_2; + co[e] = val - (double)x; /* 1.0 - weight */ + gp += x * p->dinc[e]; /* Add index offset for base of cube */ +@@ -4447,7 +4524,7 @@ + rv |= 1; + } + ix = (int)floor(val); /* Grid coordinate */ +- if (ix > (p->outputEnt-2)) ++ if (ix < 0 || ix > (p->outputEnt-2)) + ix = (p->outputEnt-2); + w = val - (double)ix; /* weight */ + val = table[ix]; +@@ -4819,19 +4896,50 @@ + ) { + icmLut *p = (icmLut *)pp; + unsigned int len = 0; ++ unsigned int pw; + + if (p->ttype == icSigLut8Type) { + len += 48; /* tag and header */ ++ if (p->inputChan > 0 && ++ p->inputEnt > (UINT_MAX - len) / p->inputChan / 1) ++ goto overflow; ++ + len += 1 * (p->inputChan * p->inputEnt); +- len += 1 * (p->outputChan * uipow(p->clutPoints,p->inputChan)); ++ if (uipow(p->clutPoints,p->inputChan, &pw) || ++ (p->outputChan > 0 && ++ pw > (UINT_MAX - len) / p->outputChan / 1)) ++ goto overflow; ++ ++ len += 1 * (p->outputChan * pw); ++ if (p->outputChan > 0 && ++ p->outputEnt > (UINT_MAX - len) / p->outputChan / 1) ++ goto overflow; ++ + len += 1 * (p->outputChan * p->outputEnt); + } else { + len += 52; /* tag and header */ ++ if (p->inputChan > 0 && ++ p->inputEnt > (UINT_MAX - len) / p->inputChan / 2) ++ goto overflow; ++ + len += 2 * (p->inputChan * p->inputEnt); +- len += 2 * (p->outputChan * uipow(p->clutPoints,p->inputChan)); ++ if (uipow(p->clutPoints,p->inputChan, &pw) || ++ (p->outputChan > 0 && ++ pw > (UINT_MAX - len) / p->outputChan / 2)) ++ goto overflow; ++ ++ len += 2 * (p->outputChan * pw); ++ if (p->outputChan > 0 && ++ p->outputEnt > (UINT_MAX - len) / p->outputChan / 2) ++ goto overflow; ++ + len += 2 * (p->outputChan * p->outputEnt); + } + return len; ++ ++ overflow: ++ p->icp->errc = 1; ++ return (unsigned int) -1; + } + + /* read the object, return 0 on success, error code on fail */ +@@ -4844,6 +4952,7 @@ + icc *icp = p->icp; + int rv = 0; + unsigned long i, j, g, size; ++ unsigned int pw; + char *bp, *buf; + + if (len < 4) { +@@ -4904,6 +5013,11 @@ + return icp->errc = 1; + } + ++ if (p->clutPoints > 100) { ++ sprintf(icp->err,"icmLut_read: too many clutPoints"); ++ return icp->errc = 1; ++ } ++ + /* Read 3x3 transform matrix */ + for (j = 0; j < 3; j++) { /* Rows */ + for (i = 0; i < 3; i++) { /* Columns */ +@@ -4921,13 +5035,18 @@ + bp = buf+52; + } + +- if (len < icmLut_get_size((icmBase *)p)) { ++ if (len < icmLut_get_size((icmBase *)p) || icp->errc) { + sprintf(icp->err,"icmLut_read: Tag too small for contents"); + icp->al->free(icp->al, buf); + return icp->errc = 1; + } + + /* Read the input tables */ ++ if (p->inputEnt > 0 && p->inputChan > UINT_MAX / p->inputEnt) { ++ sprintf(icp->err,"icmLut_read: overflow"); ++ icp->al->free(icp->al, buf); ++ return icp->errc = 1; ++ } + size = (p->inputChan * p->inputEnt); + if ((rv = p->allocate((icmBase *)p)) != 0) { + icp->al->free(icp->al, buf); +@@ -4942,7 +5061,14 @@ + } + + /* Read the clut table */ +- size = (p->outputChan * uipow(p->clutPoints,p->inputChan)); ++ if (uipow(p->clutPoints,p->inputChan,&pw) || ++ (p->outputChan > 0 && ++ pw > UINT_MAX / p->outputChan)) { ++ sprintf(icp->err,"icmLut_read: overflow"); ++ icp->al->free(icp->al, buf); ++ return icp->errc = 1; ++ } ++ size = (p->outputChan * pw); + if ((rv = p->allocate((icmBase *)p)) != 0) { + icp->al->free(icp->al, buf); + return rv; +@@ -4956,6 +5082,11 @@ + } + + /* Read the output tables */ ++ if (p->outputChan > 0 && p->outputEnt > UINT_MAX / p->outputChan) { ++ sprintf(icp->err,"icmLut_read: overflow"); ++ icp->al->free(icp->al, buf); ++ return icp->errc = 1; ++ } + size = (p->outputChan * p->outputEnt); + if ((rv = p->allocate((icmBase *)p)) != 0) { + icp->al->free(icp->al, buf); +@@ -4995,12 +5126,14 @@ + icmLut *p = (icmLut *)pp; + icc *icp = p->icp; + unsigned long i,j; +- unsigned int len, size; ++ unsigned int len, size, pw; + char *bp, *buf; /* Buffer to write from */ + int rv = 0; + + /* Allocate a file write buffer */ + len = p->get_size((icmBase *)p); ++ if (icp->errc) ++ return icp->errc; + if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) { + sprintf(icp->err,"icmLut_write malloc() failed"); + return icp->errc = 2; +@@ -5066,6 +5199,11 @@ + } + + /* Write the input tables */ ++ if (p->inputEnt > 0 && p->inputChan > UINT_MAX / p->inputEnt) { ++ sprintf(icp->err,"icmLut_write: overflow"); ++ icp->al->free(icp->al, buf); ++ return icp->errc = 1; ++ } + size = (p->inputChan * p->inputEnt); + if (p->ttype == icSigLut8Type) { + for (i = 0; i < size; i++, bp += 1) { +@@ -5086,7 +5224,14 @@ + } + + /* Write the clut table */ +- size = (p->outputChan * uipow(p->clutPoints,p->inputChan)); ++ if (uipow(p->clutPoints,p->inputChan,&pw) || ++ (p->outputChan > 0 && ++ pw > UINT_MAX / p->outputChan)) { ++ sprintf(icp->err,"icmLut_write: overflow"); ++ icp->al->free(icp->al, buf); ++ return icp->errc = 1; ++ } ++ size = (p->outputChan * pw); + if (p->ttype == icSigLut8Type) { + for (i = 0; i < size; i++, bp += 1) { + if ((rv = write_DCS8Number(p->clutTable[i], bp)) != 0) { +@@ -5106,6 +5251,11 @@ + } + + /* Write the output tables */ ++ if (p->outputChan > 0 && p->outputEnt > UINT_MAX / p->outputChan) { ++ sprintf(icp->err,"icmLut_write: overflow"); ++ icp->al->free(icp->al, buf); ++ return icp->errc = 1; ++ } + size = (p->outputChan * p->outputEnt); + if (p->ttype == icSigLut8Type) { + for (i = 0; i < size; i++, bp += 1) { +@@ -5177,7 +5327,14 @@ + if (p->inputChan > MAX_CHAN) { + fprintf(op," !!Can't dump > %d input channel CLUT table!!\n",MAX_CHAN); + } else { +- size = (p->outputChan * uipow(p->clutPoints,p->inputChan)); ++ unsigned int pw; ++ if (uipow(p->clutPoints,p->inputChan,&pw) || ++ (p->outputChan > 0 && ++ pw > UINT_MAX / p->outputChan)) { ++ fprintf(op,"Would overflow.\n"); ++ return; ++ } ++ size = (p->outputChan * pw); + for (j = 0; j < p->inputChan; j++) + ii[j] = 0; + for (i = 0; i < size;) { +@@ -5216,7 +5373,7 @@ + static int icmLut_allocate( + icmBase *pp + ) { +- unsigned int i, j, g, size; ++ unsigned int i, j, g, size, pw; + icmLut *p = (icmLut *)pp; + icc *icp = p->icp; + +@@ -5231,6 +5388,10 @@ + return icp->errc = 1; + } + ++ if (p->inputEnt > 0 && p->inputChan > UINT_MAX / p->inputEnt) { ++ sprintf(icp->err,"icmLut_alloc: too many entries"); ++ return icp->errc = 1; ++ } + size = (p->inputChan * p->inputEnt); + if (size != p->inputTable_size) { + if (p->inputTable != NULL) +@@ -5241,7 +5402,13 @@ + } + p->inputTable_size = size; + } +- size = (p->outputChan * uipow(p->clutPoints,p->inputChan)); ++ if (uipow(p->clutPoints,p->inputChan,&pw) || ++ (p->outputChan > 0 && ++ pw > UINT_MAX / p->outputChan)) { ++ sprintf(icp->err,"icmLut_alloc: overflow"); ++ return icp->errc = 1; ++ } ++ size = (p->outputChan * pw); + if (size != p->clutTable_size) { + if (p->clutTable != NULL) + icp->al->free(icp->al, p->clutTable); +@@ -5251,6 +5418,10 @@ + } + p->clutTable_size = size; + } ++ if (p->outputChan > 0 && p->outputEnt > UINT_MAX / p->outputChan) { ++ sprintf(icp->err,"icmLut_alloc: overflow"); ++ return icp->errc = 1; ++ } + size = (p->outputChan * p->outputEnt); + if (size != p->outputTable_size) { + if (p->outputTable != NULL) +@@ -5441,6 +5612,8 @@ + + /* Allocate a file write buffer */ + len = p->get_size((icmBase *)p); ++ if (icp->errc) ++ return icp->errc; + if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) { + sprintf(icp->err,"icmMeasurement_write malloc() failed"); + return icp->errc = 2; +@@ -5712,13 +5885,20 @@ + len += p->nDeviceCoords * 1; /* bytes for each named color */ + } + } else { /* Named Color 2 */ ++ unsigned int col; + len += 8; /* 8 bytes for tag and padding */ + len += 4; /* 4 for vendor specific flags */ + len += 4; /* 4 for count of named colors */ + len += 4; /* 4 for number of device coords */ + len += 32; /* 32 for prefix of color names */ + len += 32; /* 32 for suffix of color names */ +- len += p->count * (32 + 6 + p->nDeviceCoords * 2); /* bytes for each named color */ ++ col = 32 + 6 + p->nDeviceCoords * 2; ++ if (p->nDeviceCoords > (UINT_MAX - (32 + 6)) / 2 || ++ (p->count > 0 && col > (UINT_MAX - len) / p->count)) { ++ p->icp->errc = 1; ++ return (unsigned int) -1; ++ } ++ len += p->count * col; /* bytes for each named color */ + } + return len; + } +@@ -5882,6 +6062,8 @@ + + /* Allocate a file write buffer */ + len = p->get_size((icmBase *)p); ++ if (icp->errc) ++ return icp->errc; + if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) { + sprintf(icp->err,"icmNamedColor_write malloc() failed"); + return icp->errc = 2; +@@ -6109,9 +6291,22 @@ + ) { + icmTextDescription *p = (icmTextDescription *)pp; + unsigned int len = 0; ++ if (p->size > UINT_MAX - (8 + 4 + 8)) { ++ p->icp->errc = 1; ++ return (unsigned int) -1; ++ } + len += 8; /* 8 bytes for tag and padding */ + len += 4 + p->size; /* Ascii string length + ascii string */ +- len += 8 + 2 * p->ucSize; /* Unicode language code + length + string */ ++ len += 8; /* Unicode language code + length */ ++ if (p->ucSize > (UINT_MAX - len) / 2) { ++ p->icp->errc = 1; ++ return (unsigned int) -1; ++ } ++ len += 2 * p->ucSize; /* Unicode string */ ++ if (len > (UINT_MAX - (3 + 67))) { ++ p->icp->errc = 1; ++ return (unsigned int) -1; ++ } + len += 3 + 67; /* ScriptCode code, length string */ + return len; + } +@@ -6294,6 +6489,8 @@ + + /* Allocate a file write buffer */ + len = p->get_size((icmBase *)p); ++ if (icp->errc) ++ return icp->errc; + if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) { + sprintf(icp->err,"icmTextDescription_write malloc() failed"); + return icp->errc = 2; +@@ -6535,7 +6732,7 @@ + if (p->size != p->_size) { + if (p->desc != NULL) + icp->al->free(icp->al, p->desc); +- if ((p->desc = (char *) icp->al->malloc(icp->al, p->size * sizeof(char))) == NULL) { ++ if ((p->desc = (char *) icp->al->calloc(icp->al, p->size, sizeof(char))) == NULL) { + sprintf(icp->err,"icmTextDescription_alloc: malloc() of Ascii description failed"); + return icp->errc = 2; + } +@@ -6544,7 +6741,7 @@ + if (p->ucSize != p->uc_size) { + if (p->ucDesc != NULL) + icp->al->free(icp->al, p->ucDesc); +- if ((p->ucDesc = (ORD16 *) icp->al->malloc(icp->al, p->ucSize * sizeof(ORD16))) == NULL) { ++ if ((p->ucDesc = (ORD16 *) icp->al->calloc(icp->al, p->ucSize, sizeof(ORD16))) == NULL) { + sprintf(icp->err,"icmTextDescription_alloc: malloc() of Unicode description failed"); + return icp->errc = 2; + } +@@ -6820,6 +7017,12 @@ + bp += 8; /* Skip padding */ + + p->count = read_UInt32Number(bp); /* Number of sequence descriptions */ ++ if (p->count > 1000) { ++ sprintf(icp->err,"icmProfileSequenceDesc_read: too many sequence descriptions"); ++ icp->al->free(icp->al, buf); ++ return icp->errc = 1; ++ } ++ + bp += 4; + + /* Read all the sequence descriptions */ +@@ -6852,6 +7055,8 @@ + + /* Allocate a file write buffer */ + len = p->get_size((icmBase *)p); ++ if (icp->errc) ++ return icp->errc; + if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) { + sprintf(icp->err,"icmProfileSequenceDesc_write malloc() failed"); + return icp->errc = 2; +@@ -6922,7 +7127,7 @@ + if (p->count != p->_count) { + if (p->data != NULL) + icp->al->free(icp->al, p->data); +- if ((p->data = (icmDescStruct *) icp->al->malloc(icp->al, p->count * sizeof(icmDescStruct))) == NULL) { ++ if ((p->data = (icmDescStruct *) icp->al->calloc(icp->al, p->count, sizeof(icmDescStruct))) == NULL) { + sprintf(icp->err,"icmProfileSequenceDesc_allocate Allocation of DescStruct array failed"); + return icp->errc = 2; + } +@@ -7041,6 +7246,8 @@ + + /* Allocate a file write buffer */ + len = p->get_size((icmBase *)p); ++ if (icp->errc) ++ return icp->errc; + if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) { + sprintf(icp->err,"icmSignature_write malloc() failed"); + return icp->errc = 2; +@@ -7156,6 +7363,10 @@ + icmScreening *p = (icmScreening *)pp; + unsigned int len = 0; + len += 16; /* 16 bytes for tag, padding, flag & channeles */ ++ if (p->channels > (UINT_MAX - len) / 12) { ++ p->icp->errc = 1; ++ return (unsigned int) -1; ++ } + len += p->channels * 12; /* 12 bytes for each channel */ + return len; + } +@@ -7235,6 +7446,8 @@ + + /* Allocate a file write buffer */ + len = p->get_size((icmBase *)p); ++ if (icp->errc) ++ return icp->errc; + if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) { + sprintf(icp->err,"icmScreening_write malloc() failed"); + return icp->errc = 2; +@@ -7315,7 +7528,7 @@ + if (p->channels != p->_channels) { + if (p->data != NULL) + icp->al->free(icp->al, p->data); +- if ((p->data = (icmScreeningData *) icp->al->malloc(icp->al, p->channels * sizeof(icmScreeningData))) == NULL) { ++ if ((p->data = (icmScreeningData *) icp->al->calloc(icp->al, p->channels, sizeof(icmScreeningData))) == NULL) { + sprintf(icp->err,"icmScreening_alloc: malloc() of icmScreening data failed"); + return icp->errc = 2; + } +@@ -7366,10 +7579,20 @@ + icmUcrBg *p = (icmUcrBg *)pp; + unsigned int len = 0; + len += 8; /* 8 bytes for tag and padding */ ++ if (p->UCRcount > (UINT_MAX - len - 4) / 2) ++ goto overflow; ++ + len += 4 + p->UCRcount * 2; /* Undercolor Removal */ ++ if (p->BGcount > (UINT_MAX - len - 4 - p->size) / 2) ++ goto overflow; ++ + len += 4 + p->BGcount * 2; /* Black Generation */ + len += p->size; /* Description string */ + return len; ++ ++ overflow: ++ p->icp->errc = 1; ++ return (unsigned int) -1; + } + + /* read the object, return 0 on success, error code on fail */ +@@ -7498,6 +7721,8 @@ + + /* Allocate a file write buffer */ + len = p->get_size((icmBase *)p); ++ if (icp->errc) ++ return icp->errc; + if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) { + sprintf(icp->err,"icmUcrBg_write malloc() failed"); + return icp->errc = 2; +@@ -7663,7 +7888,7 @@ + if (p->UCRcount != p->UCR_count) { + if (p->UCRcurve != NULL) + icp->al->free(icp->al, p->UCRcurve); +- if ((p->UCRcurve = (double *) icp->al->malloc(icp->al, p->UCRcount * sizeof(double))) == NULL) { ++ if ((p->UCRcurve = (double *) icp->al->calloc(icp->al, p->UCRcount, sizeof(double))) == NULL) { + sprintf(icp->err,"icmUcrBg_allocate: malloc() of UCR curve data failed"); + return icp->errc = 2; + } +@@ -7672,7 +7897,7 @@ + if (p->BGcount != p->BG_count) { + if (p->BGcurve != NULL) + icp->al->free(icp->al, p->BGcurve); +- if ((p->BGcurve = (double *) icp->al->malloc(icp->al, p->BGcount * sizeof(double))) == NULL) { ++ if ((p->BGcurve = (double *) icp->al->calloc(icp->al, p->BGcount, sizeof(double))) == NULL) { + sprintf(icp->err,"icmUcrBg_allocate: malloc() of BG curve data failed"); + return icp->errc = 2; + } +@@ -7681,7 +7906,7 @@ + if (p->size != p->_size) { + if (p->string != NULL) + icp->al->free(icp->al, p->string); +- if ((p->string = (char *) icp->al->malloc(icp->al, p->size * sizeof(char))) == NULL) { ++ if ((p->string = (char *) icp->al->calloc(icp->al, p->size, sizeof(char))) == NULL) { + sprintf(icp->err,"icmUcrBg_allocate: malloc() of string data failed"); + return icp->errc = 2; + } +@@ -7743,6 +7968,15 @@ + len += 2; /* 2 bytes for channels */ + len += 2; /* 2 for entry count */ + len += 2; /* 2 for entry size */ ++ if (p->u.table.entryCount > 0 && ++ p->u.table.entrySize > 0 && ++ p->u.table.channels > ++ (UINT_MAX - len) / ++ p->u.table.entryCount / ++ p->u.table.entrySize) { ++ p->icp->errc = 1; ++ return (unsigned int) -1; ++ } + len += ( p->u.table.channels * /* compute table size */ + p->u.table.entryCount * + p->u.table.entrySize ); +@@ -7762,10 +7996,11 @@ + ) { + icmVideoCardGamma *p = (icmVideoCardGamma *)pp; + icc *icp = p->icp; +- int rv, c; ++ int rv; + char *bp, *buf; + unsigned char *pchar; + unsigned short *pshort; ++ unsigned long c; + + if (len < 18) { + sprintf(icp->err,"icmVideoCardGamma_read: Tag too small to be legal"); +@@ -7803,6 +8038,16 @@ + p->u.table.channels = read_UInt16Number(bp+12); + p->u.table.entryCount = read_UInt16Number(bp+14); + p->u.table.entrySize = read_UInt16Number(bp+16); ++ if (p->u.table.entrySize > 65530 || p->u.table.entrySize == 0) { ++ sprintf(icp->err,"icmVideoCardGamma_read: Too many entries (or none)"); ++ return icp->errc = 1; ++ } ++ if (p->u.table.entryCount > 0 && p->u.table.entrySize > 0 && ++ p->u.table.channels > ++ UINT_MAX / p->u.table.entryCount / p->u.table.entrySize) { ++ sprintf(icp->err,"icmVideoCardGamma_read: Overflow reading tag"); ++ return icp->errc = 1; ++ } + if (len-18 < p->u.table.channels*p->u.table.entryCount*p->u.table.entrySize) { + sprintf(icp->err,"icmVideoCardGamma_read: Tag too small to be legal"); + return icp->errc = 1; +@@ -7871,6 +8116,8 @@ + + /* Allocate a file write buffer */ + len = p->get_size((icmBase *)p); ++ if (icp->errc) ++ return icp->errc; + if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) { + sprintf(icp->err,"icmViewingConditions_write malloc() failed"); + return icp->errc = 2; +@@ -8049,7 +8296,7 @@ + ) { + icmVideoCardGamma *p = (icmVideoCardGamma *)pp; + icc *icp = p->icp; +- int size; ++ unsigned int size; + + /* note: allocation is only relevant for table type + * and in that case the channels, entryCount, and entrySize +@@ -8059,6 +8306,11 @@ + if (p->tagType == icmVideoCardGammaTableType) { + if (p->u.table.data != NULL) + icp->al->free(icp->al, p->u.table.data); ++ if (p->u.table.entryCount > 0 && ++ p->u.table.channels > UINT_MAX / p->u.table.entryCount) { ++ sprintf(icp->err,"icmVideoCardGamma_alloc: table too large"); ++ return icp->errc = 1; ++ } + size = (p->u.table.channels * + p->u.table.entryCount); + switch (p->u.table.entrySize) { +@@ -8066,6 +8318,10 @@ + size *= sizeof(unsigned char); + break; + case 2: ++ if (size > UINT_MAX / sizeof(unsigned short)) { ++ sprintf(icp->err,"icmVideoCardGamma_alloc: table too large"); ++ return icp->errc = 1; ++ } + size *= sizeof(unsigned short); + break; + default: +@@ -8201,6 +8457,8 @@ + + /* Allocate a file write buffer */ + len = p->get_size((icmBase *)p); ++ if (icp->errc) ++ return icp->errc; + if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) { + sprintf(icp->err,"icmViewingConditions_write malloc() failed"); + return icp->errc = 2; +@@ -8433,6 +8691,8 @@ + + /* Allocate a file write buffer */ + len = p->get_size((icmBase *)p); ++ if (icp->errc) ++ return icp->errc; + if ((buf = (char *) icp->al->malloc(icp->al, len)) == NULL) { + sprintf(icp->err,"icmCrdInfo_write malloc() failed"); + return icp->errc = 2; +@@ -8585,7 +8845,7 @@ + if (p->ppsize != p->_ppsize) { + if (p->ppname != NULL) + icp->al->free(icp->al, p->ppname); +- if ((p->ppname = (char *) icp->al->malloc(icp->al, p->ppsize * sizeof(char))) == NULL) { ++ if ((p->ppname = (char *) icp->al->calloc(icp->al, p->ppsize, sizeof(char))) == NULL) { + sprintf(icp->err,"icmCrdInfo_alloc: malloc() of string data failed"); + return icp->errc = 2; + } +@@ -8595,7 +8855,7 @@ + if (p->crdsize[t] != p->_crdsize[t]) { + if (p->crdname[t] != NULL) + icp->al->free(icp->al, p->crdname[t]); +- if ((p->crdname[t] = (char *) icp->al->malloc(icp->al, p->crdsize[t] * sizeof(char))) == NULL) { ++ if ((p->crdname[t] = (char *) icp->al->calloc(icp->al, p->crdsize[t], sizeof(char))) == NULL) { + sprintf(icp->err,"icmCrdInfo_alloc: malloc() of CRD%d name string failed",t); + return icp->errc = 2; + } +@@ -8736,6 +8996,8 @@ + int rv = 0; + + len = p->get_size(p); ++ if (icp->errc) ++ return icp->errc; + if ((buf = (char *) icp->al->calloc(icp->al,1,len)) == NULL) { /* Zero it - some CMS are fussy */ + sprintf(icp->err,"icmHeader_write calloc() failed"); + return icp->errc = 2; +@@ -9245,13 +9507,23 @@ + } + + p->count = read_UInt32Number(tcbuf); /* Tag count */ ++ if (p->count > 100) { ++ sprintf(p->err,"icc_read: too many table tags"); ++ return p->errc = 1; ++ } + if (p->count > 0) { + char *bp, *buf; +- if ((p->data = (icmTag *) p->al->malloc(p->al, p->count * sizeof(icmTag))) == NULL) { ++ if ((p->data = (icmTag *) p->al->calloc(p->al, p->count, sizeof(icmTag))) == NULL) { + sprintf(p->err,"icc_read: Tag table malloc() failed"); + return p->errc = 2; + } + ++ if (p->count > (UINT_MAX - 4) / 12) { ++ sprintf(p->err,"icc_read: overflow"); ++ p->al->free(p->al, p->data); ++ p->data = NULL; ++ return p->errc = 1; ++ } + len = 4 + p->count * 12; + if ((buf = (char *) p->al->malloc(p->al, len)) == NULL) { + sprintf(p->err,"icc_read: Tag table read buffer malloc() failed"); +@@ -9281,6 +9553,14 @@ + return p->errc = 1; + } + p->data[i].size = read_UInt32Number(bp + 8); ++ if (p->data[i].offset + p->data[i].size > ++ p->header->size) { ++ sprintf(p->err,"icc_read: tag out of bounds"); ++ p->al->free(p->al, p->data); ++ p->data = NULL; ++ p->al->free(p->al, buf); ++ return p->errc = 1; ++ } + if ( p->fp->seek(p->fp, of + p->data[i].offset) != 0 + || p->fp->read(p->fp, tcbuf, 1, 4) != 4) { + sprintf(p->err,"icc_read: fseek() or fread() failed on tag headers"); +@@ -9321,8 +9601,14 @@ + } + + size += p->header->get_size(p->header); ++ if (p->errc) ++ return (unsigned int) -1; + + size = DO_ALIGN(size); ++ if (size == 0 || p->count > (UINT_MAX - 4 - size) / 12) { ++ p->errc = 1; ++ return (unsigned int) -1; ++ } + size += 4 + p->count * 12; /* Tag table length */ + + /* Reset touched flag for each tag type */ +@@ -9337,8 +9623,13 @@ + /* Get size for each tag type, skipping links */ + for (i = 0; i < p->count; i++) { + if (p->data[i].objp->touched == 0) { /* Not alllowed for previously */ ++ unsigned int obj_size; + size = DO_ALIGN(size); +- size += p->data[i].objp->get_size(p->data[i].objp); ++ obj_size = p->data[i].objp->get_size(p->data[i].objp); ++ if (size == 0 || p->errc || ++ obj_size > UINT_MAX - size) ++ return (unsigned int) -1; ++ size += obj_size; + p->data[i].objp->touched = 1; /* Don't account for this again */ + } + } +@@ -9373,9 +9664,19 @@ + } + + size += p->header->get_size(p->header); ++ if (p->errc) ++ return p->errc; + ++ if (p->count > (UINT_MAX - 4) / 12) { ++ sprintf(p->err,"icc_write: too many tags"); ++ return p->errc = 1; ++ } + len = 4 + p->count * 12; /* Tag table length */ + size = DO_ALIGN(size); ++ if (size == 0 || size > UINT_MAX - len) { ++ sprintf(p->err,"icc_write: overflow writing tag table"); ++ return p->errc = 1; ++ } + size += len; + + /* Allocate memory buffer for tag table */ +@@ -9406,6 +9707,12 @@ + size = DO_ALIGN(size); + p->data[i].offset = size; /* Profile relative target */ + p->data[i].size = p->data[i].objp->get_size(p->data[i].objp); ++ if (size == 0 || ++ p->errc || p->data[i].size > UINT_MAX - size) { ++ sprintf(p->err,"icc_write: internal error - overflow?"); ++ p->al->free(p->al, buf); ++ return p->errc; ++ } + size += p->data[i].size; + p->data[i].objp->touched = 1; /* Allocated space for it */ + } else { /* must be linked - copy allocation */ +@@ -9529,6 +9836,11 @@ + } + + /* Make space in tag table for new tag item */ ++ if (p->count > (UINT_MAX / sizeof(icmTag)) - 1) { ++ sprintf(p->err,"icc_add_tag: overflow"); ++ p->errc = 1; ++ return NULL; ++ } + if (p->data == NULL) + tp = p->al->malloc(p->al, (p->count+1) * sizeof(icmTag)); + else +@@ -9612,6 +9924,11 @@ + } + + /* Make space in tag table for new tag item */ ++ if (p->count > (UINT_MAX / sizeof(icmTag)) - 1) { ++ sprintf(p->err,"icc_link_tag: overflow"); ++ p->errc = 1; ++ return NULL; ++ } + if (p->data == NULL) + tp = p->al->malloc(p->al, (p->count+1) * sizeof(icmTag)); + else
pgpc9DnFrvFrE.pgp
Description: PGP signature