summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2015-05-18 18:59:54 (GMT)
committerdgp <dgp@users.sourceforge.net>2015-05-18 18:59:54 (GMT)
commitbc6490bcc6ca0eb4d50562f811e25949bda0701c (patch)
tree4629bfa9a478d4fbd3e32fea569819a645c50f21
parent348a58fe272f747f88db363b397cc98e8980e8e7 (diff)
parent54196211723b6c139157a3ab50b176f8f1dcd094 (diff)
downloadtk-bc6490bcc6ca0eb4d50562f811e25949bda0701c.zip
tk-bc6490bcc6ca0eb4d50562f811e25949bda0701c.tar.gz
tk-bc6490bcc6ca0eb4d50562f811e25949bda0701c.tar.bz2
[dece631375] Prevent overflows in photo image memory allocations.
-rw-r--r--generic/tkImgPhoto.c46
1 files changed, 33 insertions, 13 deletions
diff --git a/generic/tkImgPhoto.c b/generic/tkImgPhoto.c
index 73a06b7..fcb6d2f 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 > (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) {
@@ -2192,6 +2205,10 @@ ImgPhotoSetSize(
height = masterPtr->userHeight;
}
+ if (width > INT_MAX / 4) {
+ /* Pitch overflows int */
+ return TCL_ERROR;
+ }
pitch = width * 4;
/*
@@ -2201,11 +2218,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 > UINT_MAX / pitch) {
+ return TCL_ERROR;
+ }
+ newPixSize = height * pitch;
/*
* Some mallocs() really hate allocating zero bytes. [Bug 619544]
@@ -3699,6 +3717,10 @@ ImgGetPhoto(
if ((greenOffset||blueOffset) && !(optPtr->options & OPT_GRAYSCALE)) {
newPixelSize += 2;
}
+
+ if (blockPtr->height > (UINT_MAX/newPixelSize)/blockPtr->width) {
+ return NULL;
+ }
data = attemptckalloc(newPixelSize*blockPtr->width*blockPtr->height);
if (data == NULL) {
return NULL;
@@ -3835,32 +3857,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;
}