--- Begin Message ---
Package: argyll
Severity: grave
Tags: security
Let's welcome argyll in the archive with an RC security bug :-)
argyll embeds a copy of icclib, which has recently been fixed in
a DSA for ghostscript. I'm attaching the patch from the DSA, please
pass it to argyll upstream and the maintainer of debian-multimedia.org
Cheers,
Moritz
-- System Information:
Debian Release: squeeze/sid
APT prefers unstable
APT policy: (500, 'unstable')
Architecture: i386 (i686)
Kernel: Linux 2.6.29-1-686 (SMP w/1 CPU core)
Locale: LANG=C, lc_ctype=de_de.iso-8859...@euro (charmap=ISO-8859-15)
Shell: /bin/sh linked to /bin/bash
#! /bin/sh /usr/share/dpatch/dpatch-run
@DPATCH@
--- ../old/ghostscript-8.62.dfsg.1/icclib/icc.c 2006-05-24 18:23:16.000000000 +0000
+++ ghostscript-8.62.dfsg.1/icclib/icc.c 2009-03-14 12:55:13.000000000 +0000
@@ -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;
}
@@ -3001,7 +3044,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;
@@ -3141,6 +3184,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 +3285,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 +3396,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 +3542,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;
@@ -3745,6 +3796,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;
@@ -4038,6 +4091,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 +4183,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;
}
/* - - - - - - - - - - - - - - - - */
@@ -4268,7 +4327,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;
}
@@ -4819,19 +4878,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 +4934,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 +4995,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 +5017,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 +5043,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 +5064,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 +5108,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 +5181,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 +5206,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 +5233,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 +5309,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 +5355,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 +5370,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 +5384,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 +5400,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 +5594,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 +5867,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 +6044,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 +6273,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 +6471,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;
@@ -6544,7 +6723,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 +6999,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 +7037,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 +7109,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 +7228,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 +7345,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 +7428,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 +7510,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 +7561,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 +7703,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 +7870,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 +7879,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;
}
@@ -7743,6 +7950,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 +7978,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 +8020,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 +8098,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 +8278,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 +8288,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 +8300,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 +8439,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 +8673,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;
@@ -8736,6 +8978,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 +9489,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");
@@ -9274,6 +9528,14 @@
p->data[i].sig = (icTagSignature)read_SInt32Number(bp + 0);
p->data[i].offset = read_UInt32Number(bp + 4);
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");
@@ -9314,8 +9576,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 */
@@ -9330,8 +9598,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 */
}
}
@@ -9366,9 +9639,19 @@
}
size += p->header->get_size(p->header);
+ if (p->errc)
+ return p->errc;
+ if (p->count > (UINT_MAX - 4 - len) / 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 */
@@ -9399,6 +9682,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 */
@@ -9522,6 +9811,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
@@ -9605,6 +9899,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
--- End Message ---