diff options
author | DRC <information@libjpeg-turbo.org> | 2019-09-11 14:27:47 -0700 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2019-09-11 14:27:47 -0700 |
commit | 5dcc997bd6f6f465490c94ade2aef535e51a706d (patch) | |
tree | 74ff998f72c18bdf7efba586b9b4a7a2f4075df9 /tjbench.c | |
parent | 84c056eda93933da06d287573efd1f9eeb54bd33 (diff) | |
parent | 2596ecc57d8227273c2adf17409a6d7035db7de4 (diff) | |
download | libjpeg-turbo-5dcc997bd6f6f465490c94ade2aef535e51a706d.tar.gz |
[RESTRICT AUTOMERGE] TurboJPEG: Properly handle gigapixel images am: d8b95103b9
am: 2596ecc57d
Change-Id: I42527bac385e72154fea81324d76181618f1e39d
Diffstat (limited to 'tjbench.c')
-rw-r--r-- | tjbench.c | 123 |
1 files changed, 70 insertions, 53 deletions
@@ -32,27 +32,28 @@ #include <ctype.h> #include <math.h> #include <errno.h> +#include <limits.h> #include <cdjpeg.h> #include "./tjutil.h" #include "./turbojpeg.h" -#define _throw(op, err) { \ +#define THROW(op, err) { \ printf("ERROR in line %d while %s:\n%s\n", __LINE__, op, err); \ retval = -1; goto bailout; \ } -#define _throwunix(m) _throw(m, strerror(errno)) +#define THROW_UNIX(m) THROW(m, strerror(errno)) char tjErrorStr[JMSG_LENGTH_MAX] = "\0", tjErrorMsg[JMSG_LENGTH_MAX] = "\0"; int tjErrorLine = -1, tjErrorCode = -1; -#define _throwtjg(m) { \ +#define THROW_TJG(m) { \ printf("ERROR in line %d while %s:\n%s\n", __LINE__, m, \ tjGetErrorStr2(NULL)); \ retval = -1; goto bailout; \ } -#define _throwtj(m) { \ +#define THROW_TJ(m) { \ int _tjErrorCode = tjGetErrorCode(handle); \ char *_tjErrorStr = tjGetErrorStr2(handle); \ \ @@ -157,11 +158,14 @@ int decomp(unsigned char *srcBuf, unsigned char **jpegBuf, } if ((handle = tjInitDecompress()) == NULL) - _throwtj("executing tjInitDecompress()"); + THROW_TJ("executing tjInitDecompress()"); if (dstBuf == NULL) { - if ((dstBuf = (unsigned char *)malloc(pitch * scaledh)) == NULL) - _throwunix("allocating destination buffer"); + if ((unsigned long long)pitch * (unsigned long long)scaledh > + (unsigned long long)((size_t)-1)) + THROW("allocating destination buffer", "Image is too large"); + if ((dstBuf = (unsigned char *)malloc((size_t)pitch * scaledh)) == NULL) + THROW_UNIX("allocating destination buffer"); dstBufAlloc = 1; } /* Set the destination buffer to gray so we know whether the decompressor @@ -171,10 +175,12 @@ int decomp(unsigned char *srcBuf, unsigned char **jpegBuf, if (doYUV) { int width = doTile ? tilew : scaledw; int height = doTile ? tileh : scaledh; - int yuvSize = tjBufSizeYUV2(width, yuvPad, height, subsamp); + unsigned long yuvSize = tjBufSizeYUV2(width, yuvPad, height, subsamp); + if (yuvSize == (unsigned long)-1) + THROW_TJ("allocating YUV buffer"); if ((yuvBuf = (unsigned char *)malloc(yuvSize)) == NULL) - _throwunix("allocating YUV buffer"); + THROW_UNIX("allocating YUV buffer"); memset(yuvBuf, 127, yuvSize); } @@ -197,16 +203,16 @@ int decomp(unsigned char *srcBuf, unsigned char **jpegBuf, if (tjDecompressToYUV2(handle, jpegBuf[tile], jpegSize[tile], yuvBuf, width, yuvPad, height, flags) == -1) - _throwtj("executing tjDecompressToYUV2()"); + THROW_TJ("executing tjDecompressToYUV2()"); startDecode = getTime(); if (tjDecodeYUV(handle, yuvBuf, yuvPad, subsamp, dstPtr2, width, pitch, height, pf, flags) == -1) - _throwtj("executing tjDecodeYUV()"); + THROW_TJ("executing tjDecodeYUV()"); if (iter >= 0) elapsedDecode += getTime() - startDecode; } else if (tjDecompress2(handle, jpegBuf[tile], jpegSize[tile], dstPtr2, width, pitch, height, pf, flags) == -1) - _throwtj("executing tjDecompress2()"); + THROW_TJ("executing tjDecompress2()"); } } elapsed += getTime() - start; @@ -220,7 +226,7 @@ int decomp(unsigned char *srcBuf, unsigned char **jpegBuf, } if (doYUV) elapsed -= elapsedDecode; - if (tjDestroy(handle) == -1) _throwtj("executing tjDestroy()"); + if (tjDestroy(handle) == -1) THROW_TJ("executing tjDestroy()"); handle = NULL; if (quiet) { @@ -260,19 +266,19 @@ int decomp(unsigned char *srcBuf, unsigned char **jpegBuf, qualStr, sizeStr, ext); if (tjSaveImage(tempStr, dstBuf, scaledw, 0, scaledh, pf, flags) == -1) - _throwtjg("saving bitmap"); + THROW_TJG("saving bitmap"); ptr = strrchr(tempStr, '.'); snprintf(ptr, 1024 - (ptr - tempStr), "-err.%s", ext); if (srcBuf && sf.num == 1 && sf.denom == 1) { if (!quiet) printf("Compression error written to %s.\n", tempStr); if (subsamp == TJ_GRAYSCALE) { - int index, index2; + unsigned long index, index2; for (row = 0, index = 0; row < h; row++, index += pitch) { for (col = 0, index2 = index; col < w; col++, index2 += ps) { - int rindex = index2 + tjRedOffset[pf]; - int gindex = index2 + tjGreenOffset[pf]; - int bindex = index2 + tjBlueOffset[pf]; + unsigned long rindex = index2 + tjRedOffset[pf]; + unsigned long gindex = index2 + tjGreenOffset[pf]; + unsigned long bindex = index2 + tjBlueOffset[pf]; int y = (int)((double)srcBuf[rindex] * 0.299 + (double)srcBuf[gindex] * 0.587 + (double)srcBuf[bindex] * 0.114 + 0.5); @@ -291,7 +297,7 @@ int decomp(unsigned char *srcBuf, unsigned char **jpegBuf, abs(dstBuf[pitch * row + col] - srcBuf[pitch * row + col]); } if (tjSaveImage(tempStr, dstBuf, w, 0, h, pf, flags) == -1) - _throwtjg("saving bitmap"); + THROW_TJG("saving bitmap"); } bailout: @@ -313,14 +319,17 @@ int fullTest(unsigned char *srcBuf, int w, int h, int subsamp, int jpegQual, *srcPtr2; double start, elapsed, elapsedEncode; int totalJpegSize = 0, row, col, i, tilew = w, tileh = h, retval = 0; - int iter, yuvSize = 0; - unsigned long *jpegSize = NULL; + int iter; + unsigned long *jpegSize = NULL, yuvSize = 0; int ps = tjPixelSize[pf]; int ntilesw = 1, ntilesh = 1, pitch = w * ps; const char *pfStr = pixFormatStr[pf]; - if ((tmpBuf = (unsigned char *)malloc(pitch * h)) == NULL) - _throwunix("allocating temporary image buffer"); + if ((unsigned long long)pitch * (unsigned long long)h > + (unsigned long long)((size_t)-1)) + THROW("allocating temporary image buffer", "Image is too large"); + if ((tmpBuf = (unsigned char *)malloc((size_t)pitch * h)) == NULL) + THROW_UNIX("allocating temporary image buffer"); if (!quiet) printf(">>>>> %s (%s) <--> JPEG %s Q%d <<<<<\n", pfStr, @@ -336,18 +345,20 @@ int fullTest(unsigned char *srcBuf, int w, int h, int subsamp, int jpegQual, if ((jpegBuf = (unsigned char **)malloc(sizeof(unsigned char *) * ntilesw * ntilesh)) == NULL) - _throwunix("allocating JPEG tile array"); + THROW_UNIX("allocating JPEG tile array"); memset(jpegBuf, 0, sizeof(unsigned char *) * ntilesw * ntilesh); if ((jpegSize = (unsigned long *)malloc(sizeof(unsigned long) * ntilesw * ntilesh)) == NULL) - _throwunix("allocating JPEG size array"); + THROW_UNIX("allocating JPEG size array"); memset(jpegSize, 0, sizeof(unsigned long) * ntilesw * ntilesh); if ((flags & TJFLAG_NOREALLOC) != 0) for (i = 0; i < ntilesw * ntilesh; i++) { + if (tjBufSize(tilew, tileh, subsamp) > (unsigned long)INT_MAX) + THROW("getting buffer size", "Image is too large"); if ((jpegBuf[i] = (unsigned char *) tjAlloc(tjBufSize(tilew, tileh, subsamp))) == NULL) - _throwunix("allocating JPEG tiles"); + THROW_UNIX("allocating JPEG tiles"); } /* Compression test */ @@ -358,12 +369,14 @@ int fullTest(unsigned char *srcBuf, int w, int h, int subsamp, int jpegQual, for (i = 0; i < h; i++) memcpy(&tmpBuf[pitch * i], &srcBuf[w * ps * i], w * ps); if ((handle = tjInitCompress()) == NULL) - _throwtj("executing tjInitCompress()"); + THROW_TJ("executing tjInitCompress()"); if (doYUV) { yuvSize = tjBufSizeYUV2(tilew, yuvPad, tileh, subsamp); + if (yuvSize == (unsigned long)-1) + THROW_TJ("allocating YUV buffer"); if ((yuvBuf = (unsigned char *)malloc(yuvSize)) == NULL) - _throwunix("allocating YUV buffer"); + THROW_UNIX("allocating YUV buffer"); memset(yuvBuf, 127, yuvSize); } @@ -387,17 +400,17 @@ int fullTest(unsigned char *srcBuf, int w, int h, int subsamp, int jpegQual, if (tjEncodeYUV3(handle, srcPtr2, width, pitch, height, pf, yuvBuf, yuvPad, subsamp, flags) == -1) - _throwtj("executing tjEncodeYUV3()"); + THROW_TJ("executing tjEncodeYUV3()"); if (iter >= 0) elapsedEncode += getTime() - startEncode; if (tjCompressFromYUV(handle, yuvBuf, width, yuvPad, height, subsamp, &jpegBuf[tile], &jpegSize[tile], jpegQual, flags) == -1) - _throwtj("executing tjCompressFromYUV()"); + THROW_TJ("executing tjCompressFromYUV()"); } else { if (tjCompress2(handle, srcPtr2, width, pitch, height, pf, &jpegBuf[tile], &jpegSize[tile], subsamp, jpegQual, flags) == -1) - _throwtj("executing tjCompress2()"); + THROW_TJ("executing tjCompress2()"); } totalJpegSize += jpegSize[tile]; } @@ -413,7 +426,7 @@ int fullTest(unsigned char *srcBuf, int w, int h, int subsamp, int jpegQual, } if (doYUV) elapsed -= elapsedEncode; - if (tjDestroy(handle) == -1) _throwtj("executing tjDestroy()"); + if (tjDestroy(handle) == -1) THROW_TJ("executing tjDestroy()"); handle = NULL; if (quiet == 1) printf("%-5d %-5d ", tilew, tileh); @@ -436,7 +449,7 @@ int fullTest(unsigned char *srcBuf, int w, int h, int subsamp, int jpegQual, if (doYUV) { printf("Encode YUV --> Frame rate: %f fps\n", (double)iter / elapsedEncode); - printf(" Output image size: %d bytes\n", yuvSize); + printf(" Output image size: %lu bytes\n", yuvSize); printf(" Compression ratio: %f:1\n", (double)(w * h * ps) / (double)yuvSize); printf(" Throughput: %f Megapixels/sec\n", @@ -460,9 +473,9 @@ int fullTest(unsigned char *srcBuf, int w, int h, int subsamp, int jpegQual, snprintf(tempStr, 1024, "%s_%s_Q%d.jpg", fileName, subName[subsamp], jpegQual); if ((file = fopen(tempStr, "wb")) == NULL) - _throwunix("opening reference image"); + THROW_UNIX("opening reference image"); if (fwrite(jpegBuf[0], jpegSize[0], 1, file) != 1) - _throwunix("writing reference image"); + THROW_UNIX("writing reference image"); fclose(file); file = NULL; if (!quiet) printf("Reference image written to %s\n", tempStr); } @@ -521,28 +534,28 @@ int decompTest(char *fileName) int tw, th, ttilew, ttileh, tntilesw, tntilesh, tsubsamp; if ((file = fopen(fileName, "rb")) == NULL) - _throwunix("opening file"); + THROW_UNIX("opening file"); if (fseek(file, 0, SEEK_END) < 0 || (srcSize = ftell(file)) == (unsigned long)-1) - _throwunix("determining file size"); + THROW_UNIX("determining file size"); if ((srcBuf = (unsigned char *)malloc(srcSize)) == NULL) - _throwunix("allocating memory"); + THROW_UNIX("allocating memory"); if (fseek(file, 0, SEEK_SET) < 0) - _throwunix("setting file position"); + THROW_UNIX("setting file position"); if (fread(srcBuf, srcSize, 1, file) < 1) - _throwunix("reading JPEG data"); + THROW_UNIX("reading JPEG data"); fclose(file); file = NULL; temp = strrchr(fileName, '.'); if (temp != NULL) *temp = '\0'; if ((handle = tjInitTransform()) == NULL) - _throwtj("executing tjInitTransform()"); + THROW_TJ("executing tjInitTransform()"); if (tjDecompressHeader3(handle, srcBuf, srcSize, &w, &h, &subsamp, &cs) == -1) - _throwtj("executing tjDecompressHeader3()"); + THROW_TJ("executing tjDecompressHeader3()"); if (w < 1 || h < 1) - _throw("reading JPEG header", "Invalid image dimensions"); + THROW("reading JPEG header", "Invalid image dimensions"); if (cs == TJCS_YCCK || cs == TJCS_CMYK) { pf = TJPF_CMYK; ps = tjPixelSize[pf]; } @@ -570,18 +583,21 @@ int decompTest(char *fileName) if ((jpegBuf = (unsigned char **)malloc(sizeof(unsigned char *) * ntilesw * ntilesh)) == NULL) - _throwunix("allocating JPEG tile array"); + THROW_UNIX("allocating JPEG tile array"); memset(jpegBuf, 0, sizeof(unsigned char *) * ntilesw * ntilesh); if ((jpegSize = (unsigned long *)malloc(sizeof(unsigned long) * ntilesw * ntilesh)) == NULL) - _throwunix("allocating JPEG size array"); + THROW_UNIX("allocating JPEG size array"); memset(jpegSize, 0, sizeof(unsigned long) * ntilesw * ntilesh); - if ((flags & TJFLAG_NOREALLOC) != 0 || !doTile) + if ((flags & TJFLAG_NOREALLOC) != 0 && + (doTile || xformOp != TJXOP_NONE || xformOpt != 0 || customFilter)) for (i = 0; i < ntilesw * ntilesh; i++) { + if (tjBufSize(tilew, tileh, subsamp) > (unsigned long)INT_MAX) + THROW("getting buffer size", "Image is too large"); if ((jpegBuf[i] = (unsigned char *) tjAlloc(tjBufSize(tilew, tileh, subsamp))) == NULL) - _throwunix("allocating JPEG tiles"); + THROW_UNIX("allocating JPEG tiles"); } tw = w; th = h; ttilew = tilew; ttileh = tileh; @@ -601,7 +617,7 @@ int decompTest(char *fileName) if (doTile || xformOp != TJXOP_NONE || xformOpt != 0 || customFilter) { if ((t = (tjtransform *)malloc(sizeof(tjtransform) * ntilesw * ntilesh)) == NULL) - _throwunix("allocating image transform array"); + THROW_UNIX("allocating image transform array"); if (xformOp == TJXOP_TRANSPOSE || xformOp == TJXOP_TRANSVERSE || xformOp == TJXOP_ROT90 || xformOp == TJXOP_ROT270) { @@ -647,7 +663,7 @@ int decompTest(char *fileName) start = getTime(); if (tjTransform(handle, srcBuf, srcSize, tntilesw * tntilesh, jpegBuf, jpegSize, t, flags) == -1) - _throwtj("executing tjTransform()"); + THROW_TJ("executing tjTransform()"); elapsed += getTime() - start; if (iter >= 0) { iter++; @@ -684,7 +700,7 @@ int decompTest(char *fileName) } } else { if (quiet == 1) printf("N/A N/A "); - tjFree(jpegBuf[0]); + if(jpegBuf[0]) tjFree(jpegBuf[0]); jpegBuf[0] = NULL; decompsrc = 1; } @@ -699,7 +715,8 @@ int decompTest(char *fileName) } else if (quiet == 1) printf("N/A\n"); for (i = 0; i < ntilesw * ntilesh; i++) { - tjFree(jpegBuf[i]); jpegBuf[i] = NULL; + if(jpegBuf[i]) tjFree(jpegBuf[i]); + jpegBuf[i] = NULL; } free(jpegBuf); jpegBuf = NULL; if (jpegSize) { free(jpegSize); jpegSize = NULL; } @@ -803,7 +820,7 @@ int main(int argc, char *argv[]) int minArg = 2, retval = 0, subsamp = -1; if ((scalingFactors = tjGetScalingFactors(&nsf)) == NULL || nsf == 0) - _throw("executing tjGetScalingFactors()", tjGetErrorStr()); + THROW("executing tjGetScalingFactors()", tjGetErrorStr()); if (argc < minArg) usage(argv[0]); @@ -961,7 +978,7 @@ int main(int argc, char *argv[]) if (!decompOnly) { if ((srcBuf = tjLoadImage(argv[1], &w, 1, &h, &pf, flags)) == NULL) - _throwtjg("loading bitmap"); + THROW_TJG("loading bitmap"); temp = strrchr(argv[1], '.'); if (temp != NULL) *temp = '\0'; } |