summaryrefslogtreecommitdiffstats
path: root/generic/tkImgPhoto.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tkImgPhoto.c')
-rw-r--r--generic/tkImgPhoto.c75
1 files changed, 49 insertions, 26 deletions
diff --git a/generic/tkImgPhoto.c b/generic/tkImgPhoto.c
index 9527c93..3e03f3d 100644
--- a/generic/tkImgPhoto.c
+++ b/generic/tkImgPhoto.c
@@ -886,6 +886,19 @@ ImgPhotoCmd(
break;
}
dataWidth = listObjc;
+ /*
+ * Memory allocation overflow protection.
+ * May not be able to trigger/ demo / test this.
+ */
+
+ if (dataWidth > (int)((UINT_MAX/3) / dataHeight)) {
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "photo image dimensions exceed Tcl memory limits", -1));
+ Tcl_SetErrorCode(interp, "TK", "IMAGE", "PHOTO",
+ "OVERFLOW", NULL);
+ break;
+ }
+
pixelPtr = ckalloc(dataWidth * dataHeight * 3);
block.pixelPtr = pixelPtr;
} else if (listObjc != dataWidth) {
@@ -2051,8 +2064,8 @@ static int
ToggleComplexAlphaIfNeeded(
PhotoMaster *mPtr)
{
- size_t len = MAX(mPtr->userWidth, mPtr->width) *
- MAX(mPtr->userHeight, mPtr->height) * 4;
+ size_t len = (size_t)MAX(mPtr->userWidth, mPtr->width) *
+ (size_t)MAX(mPtr->userHeight, mPtr->height) * 4;
unsigned char *c = mPtr->pix32;
unsigned char *end = c + len;
@@ -2062,6 +2075,9 @@ ToggleComplexAlphaIfNeeded(
*/
mPtr->flags &= ~COMPLEX_ALPHA;
+ if (c == NULL) {
+ return 0;
+ }
c += 3; /* Start at first alpha byte. */
for (; c < end; c += 4) {
if (*c && *c != 255) {
@@ -2192,6 +2208,10 @@ ImgPhotoSetSize(
height = masterPtr->userHeight;
}
+ if (width > INT_MAX / 4) {
+ /* Pitch overflows int */
+ return TCL_ERROR;
+ }
pitch = width * 4;
/*
@@ -2201,11 +2221,12 @@ ImgPhotoSetSize(
if ((width != masterPtr->width) || (height != masterPtr->height)
|| (masterPtr->pix32 == NULL)) {
- /*
- * Not a u-long, but should be one.
- */
+ unsigned newPixSize;
- unsigned /*long*/ newPixSize = (unsigned /*long*/) (height * pitch);
+ if (pitch && height > (int)(UINT_MAX / pitch)) {
+ return TCL_ERROR;
+ }
+ newPixSize = height * pitch;
/*
* Some mallocs() really hate allocating zero bytes. [Bug 619544]
@@ -2257,14 +2278,14 @@ ImgPhotoSetSize(
if ((masterPtr->pix32 != NULL)
&& ((width == masterPtr->width) || (width == validBox.width))) {
if (validBox.y > 0) {
- memset(newPix32, 0, (size_t) (validBox.y * pitch));
+ memset(newPix32, 0, ((size_t) validBox.y * pitch));
}
h = validBox.y + validBox.height;
if (h < height) {
- memset(newPix32 + h*pitch, 0, (size_t) ((height - h) * pitch));
+ memset(newPix32 + h*pitch, 0, ((size_t) (height - h) * pitch));
}
} else {
- memset(newPix32, 0, (size_t) (height * pitch));
+ memset(newPix32, 0, ((size_t)height * pitch));
}
if (masterPtr->pix32 != NULL) {
@@ -2281,7 +2302,7 @@ ImgPhotoSetSize(
offset = validBox.y * pitch;
memcpy(newPix32 + offset, masterPtr->pix32 + offset,
- (size_t) (validBox.height * pitch));
+ ((size_t)validBox.height * pitch));
} else if ((validBox.width > 0) && (validBox.height > 0)) {
/*
@@ -2292,7 +2313,7 @@ ImgPhotoSetSize(
srcPtr = masterPtr->pix32 + (validBox.y * masterPtr->width
+ validBox.x) * 4;
for (h = validBox.height; h > 0; h--) {
- memcpy(destPtr, srcPtr, (size_t) (validBox.width * 4));
+ memcpy(destPtr, srcPtr, ((size_t)validBox.width * 4));
destPtr += width * 4;
srcPtr += masterPtr->width * 4;
}
@@ -2772,7 +2793,7 @@ Tk_PhotoPutBlock(
&& (blockPtr->pitch == pitch)))
&& (compRule == TK_PHOTO_COMPOSITE_SET)) {
memmove(destLinePtr, blockPtr->pixelPtr + blockPtr->offset[0],
- (size_t) (height * width * 4));
+ ((size_t)height * width * 4));
/*
* We know there's an alpha offset and we're setting the data, so skip
@@ -2804,7 +2825,7 @@ Tk_PhotoPutBlock(
&& (blueOffset == 2) && (alphaOffset == 3)
&& (width <= blockPtr->width)
&& compRuleSet) {
- memcpy(destLinePtr, srcLinePtr, (size_t) (width * 4));
+ memcpy(destLinePtr, srcLinePtr, ((size_t)width * 4));
srcLinePtr += blockPtr->pitch;
destLinePtr += pitch;
continue;
@@ -3454,7 +3475,7 @@ Tk_PhotoBlank(
*/
memset(masterPtr->pix32, 0,
- (size_t) (masterPtr->width * masterPtr->height * 4));
+ ((size_t)masterPtr->width * masterPtr->height * 4));
for (instancePtr = masterPtr->instancePtr; instancePtr != NULL;
instancePtr = instancePtr->nextPtr) {
TkImgResetDither(instancePtr);
@@ -3683,6 +3704,9 @@ ImgGetPhoto(
break;
}
}
+ if (!alphaOffset) {
+ blockPtr->offset[3]= -1; /* Tell caller alpha need not be read */
+ }
greenOffset = blockPtr->offset[1] - blockPtr->offset[0];
blueOffset = blockPtr->offset[2] - blockPtr->offset[0];
if (((optPtr->options & OPT_BACKGROUND) && alphaOffset) ||
@@ -3696,6 +3720,10 @@ ImgGetPhoto(
if ((greenOffset||blueOffset) && !(optPtr->options & OPT_GRAYSCALE)) {
newPixelSize += 2;
}
+
+ if (blockPtr->height > (int)((UINT_MAX/newPixelSize)/blockPtr->width)) {
+ return NULL;
+ }
data = attemptckalloc(newPixelSize*blockPtr->width*blockPtr->height);
if (data == NULL) {
return NULL;
@@ -3803,9 +3831,6 @@ ImgGetPhoto(
blockPtr->offset[2] = 0;
blockPtr->offset[3]= 1;
}
- if (!alphaOffset) {
- blockPtr->offset[3]= -1;
- }
return data;
}
return NULL;
@@ -3835,32 +3860,30 @@ ImgStringWrite(
Tk_PhotoImageBlock *blockPtr)
{
int greenOffset, blueOffset;
- Tcl_DString data;
+ Tcl_Obj *data;
greenOffset = blockPtr->offset[1] - blockPtr->offset[0];
blueOffset = blockPtr->offset[2] - blockPtr->offset[0];
- Tcl_DStringInit(&data);
+ data = Tcl_NewObj();
if ((blockPtr->width > 0) && (blockPtr->height > 0)) {
- char *line = ckalloc((8 * blockPtr->width) + 2);
int row, col;
for (row=0; row<blockPtr->height; row++) {
+ Tcl_Obj *line = Tcl_NewObj();
unsigned char *pixelPtr = blockPtr->pixelPtr + blockPtr->offset[0]
+ row * blockPtr->pitch;
- char *linePtr = line;
for (col=0; col<blockPtr->width; col++) {
- sprintf(linePtr, " #%02x%02x%02x", *pixelPtr,
+ Tcl_AppendPrintfToObj(line, "%s#%02x%02x%02x",
+ col ? " " : "", *pixelPtr,
pixelPtr[greenOffset], pixelPtr[blueOffset]);
pixelPtr += blockPtr->pixelSize;
- linePtr += 8;
}
- Tcl_DStringAppendElement(&data, line+1);
+ Tcl_ListObjAppendElement(NULL, data, line);
}
- ckfree(line);
}
- Tcl_DStringResult(interp, &data);
+ Tcl_SetObjResult(interp, data);
return TCL_OK;
}