Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Catch images broken by AFL #975

Merged
merged 3 commits into from
Aug 8, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/bin/common/color.c
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,34 @@ void color_apply_icc_profile(opj_image_t *image)
prec = (int)image->comps[0].prec;

if (out_space == cmsSigRgbData) { /* enumCS 16 */
unsigned int i, nr_comp = image->numcomps;

if (nr_comp > 4) {
nr_comp = 4;
}
for (i = 1; i < nr_comp; ++i) { /* AFL test */
if (image->comps[0].dx != image->comps[i].dx) {
break;
}

if (image->comps[0].dy != image->comps[i].dy) {
break;
}

if (image->comps[0].prec != image->comps[i].prec) {
break;
}

if (image->comps[0].sgnd != image->comps[i].sgnd) {
break;
}

}
if (i != nr_comp) {
cmsCloseProfile(in_prof);
return;
}

if (prec <= 8) {
in_type = TYPE_RGB_8;
out_type = TYPE_RGB_8;
Expand Down
36 changes: 32 additions & 4 deletions src/bin/jp2/convert.c
Original file line number Diff line number Diff line change
Expand Up @@ -959,10 +959,11 @@ int imagetotga(opj_image_t * image, const char *outfile)
for (i = 0; i < image->numcomps - 1; i++) {
if ((image->comps[0].dx != image->comps[i + 1].dx)
|| (image->comps[0].dy != image->comps[i + 1].dy)
|| (image->comps[0].prec != image->comps[i + 1].prec)) {
|| (image->comps[0].prec != image->comps[i + 1].prec)
|| (image->comps[0].sgnd != image->comps[i + 1].sgnd)) {
fclose(fdest);
fprintf(stderr,
"Unable to create a tga file with such J2K image charateristics.");
"Unable to create a tga file with such J2K image charateristics.\n");
return 1;
}
}
Expand Down Expand Up @@ -2343,7 +2344,7 @@ static int imagetoraw_common(opj_image_t * image, const char *outfile,
{
FILE *rawFile = NULL;
size_t res;
unsigned int compno;
unsigned int compno, numcomps;
int w, h, fails;
int line, row, curr, mask;
int *ptr;
Expand All @@ -2355,6 +2356,33 @@ static int imagetoraw_common(opj_image_t * image, const char *outfile,
return 1;
}

numcomps = image->numcomps;

if (numcomps > 4) {
numcomps = 4;
}

for (compno = 1; compno < numcomps; ++compno) {
if (image->comps[0].dx != image->comps[compno].dx) {
break;
}
if (image->comps[0].dy != image->comps[compno].dy) {
break;
}
if (image->comps[0].prec != image->comps[compno].prec) {
break;
}
if (image->comps[0].sgnd != image->comps[compno].sgnd) {
break;
}
}
if (compno != numcomps) {
fprintf(stderr,
"imagetoraw_common: All components shall have the same subsampling, same bit depth, same sign.\n");
fprintf(stderr, "\tAborting\n");
return 1;
}

rawFile = fopen(outfile, "wb");
if (!rawFile) {
fprintf(stderr, "Failed to open %s for writing !!\n", outfile);
Expand Down Expand Up @@ -2466,7 +2494,7 @@ static int imagetoraw_common(opj_image_t * image, const char *outfile,
}
}
} else if (image->comps[compno].prec <= 32) {
fprintf(stderr, "More than 16 bits per component no handled yet\n");
fprintf(stderr, "More than 16 bits per component not handled yet\n");
goto fin;
} else {
fprintf(stderr, "Error: invalid precision: %d\n", image->comps[compno].prec);
Expand Down
11 changes: 9 additions & 2 deletions src/bin/jp2/convertbmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -832,15 +832,18 @@ int imagetobmp(opj_image_t * image, const char *outfile)
int adjustR, adjustG, adjustB;

if (image->comps[0].prec < 8) {
fprintf(stderr, "Unsupported number of components: %d\n", image->comps[0].prec);
fprintf(stderr, "imagetobmp: Unsupported precision: %d\n",
image->comps[0].prec);
return 1;
}
if (image->numcomps >= 3 && image->comps[0].dx == image->comps[1].dx
&& image->comps[1].dx == image->comps[2].dx
&& image->comps[0].dy == image->comps[1].dy
&& image->comps[1].dy == image->comps[2].dy
&& image->comps[0].prec == image->comps[1].prec
&& image->comps[1].prec == image->comps[2].prec) {
&& image->comps[1].prec == image->comps[2].prec
&& image->comps[0].sgnd == image->comps[1].sgnd
&& image->comps[1].sgnd == image->comps[2].sgnd) {

/* -->> -->> -->> -->>
24 bits color
Expand Down Expand Up @@ -974,6 +977,10 @@ int imagetobmp(opj_image_t * image, const char *outfile)
fprintf(stderr, "ERROR -> failed to open %s for writing\n", outfile);
return 1;
}
if (image->numcomps > 1) {
fprintf(stderr, "imagetobmp: only first component of %d is used.\n",
image->numcomps);
}
w = (int)image->comps[0].w;
h = (int)image->comps[0].h;

Expand Down
130 changes: 97 additions & 33 deletions src/bin/jp2/converttif.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>

#ifndef OPJ_HAVE_LIBTIFF
# error OPJ_HAVE_LIBTIFF_NOT_DEFINED
Expand All @@ -50,6 +51,7 @@
#include <tiffio.h>
#include "openjpeg.h"
#include "convert.h"
#include "opj_inttypes.h"

/* -->> -->> -->> -->>

Expand Down Expand Up @@ -564,20 +566,18 @@ static void tif_32sto16u(const OPJ_INT32* pSrc, OPJ_UINT16* pDst,

int imagetotif(opj_image_t * image, const char *outfile)
{
int width, height;
int bps, adjust, sgnd;
int tiPhoto;
TIFF *tif;
tdata_t buf;
tsize_t strip_size;
uint32 width, height, bps, tiPhoto;
int adjust, sgnd;
int64_t strip_size, rowStride, TIFF_MAX;
OPJ_UINT32 i, numcomps;
OPJ_SIZE_T rowStride;
OPJ_INT32* buffer32s = NULL;
OPJ_INT32 const* planes[4];
convert_32s_PXCX cvtPxToCx = NULL;
convert_32sXXx_C1R cvt32sToTif = NULL;

bps = (int)image->comps[0].prec;
bps = (uint32)image->comps[0].prec;
planes[0] = image->comps[0].data;

numcomps = image->numcomps;
Expand Down Expand Up @@ -686,33 +686,46 @@ int imagetotif(opj_image_t * image, const char *outfile)
break;
}
sgnd = (int)image->comps[0].sgnd;
adjust = sgnd ? 1 << (image->comps[0].prec - 1) : 0;
width = (int)image->comps[0].w;
height = (int)image->comps[0].h;
adjust = sgnd ? (int)(1 << (image->comps[0].prec - 1)) : 0;
width = (uint32)image->comps[0].w;
height = (uint32)image->comps[0].h;

TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, width);
TIFFSetField(tif, TIFFTAG_IMAGELENGTH, height);
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, numcomps);
TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, (uint32)numcomps);
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps);
TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);
TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, tiPhoto);
TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, 1);
if (sizeof(tsize_t) == 4) {
TIFF_MAX = INT_MAX;
} else {
TIFF_MAX = UINT_MAX;
}
strip_size = (int64_t)TIFFStripSize(tif);

strip_size = TIFFStripSize(tif);
rowStride = ((OPJ_SIZE_T)width * numcomps * (OPJ_SIZE_T)bps + 7U) / 8U;
if (rowStride != (OPJ_SIZE_T)strip_size) {
if ((int64_t)width > (int64_t)(TIFF_MAX / numcomps) ||
(int64_t)(width * numcomps) > (int64_t)(TIFF_MAX / bps) ||
(int64_t)(width * numcomps) > (int64_t)(TIFF_MAX / (int64_t)sizeof(
OPJ_INT32))) {
fprintf(stderr, "Buffer overflow\n");
TIFFClose(tif);
return 1;
}
rowStride = (int64_t)((width * numcomps * bps + 7U) / 8U);
if (rowStride != strip_size) {
fprintf(stderr, "Invalid TIFF strip size\n");
TIFFClose(tif);
return 1;
}
buf = _TIFFmalloc(strip_size);
buf = malloc((OPJ_SIZE_T)strip_size);
if (buf == NULL) {
TIFFClose(tif);
return 1;
}
buffer32s = (OPJ_INT32 *)malloc((OPJ_SIZE_T)width * numcomps * sizeof(
OPJ_INT32));
buffer32s = (OPJ_INT32 *)malloc((OPJ_SIZE_T)(width * numcomps * sizeof(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With your new version, uint32 overflow might occur on both 32 and 64 bit builds. In the previous version, it would only occur on 32 bit builds. So checking for width > UINT_MAX / numcomps || width * numcomps > UINT_MAX / sizeof(OPJ_INT32) might be needed

OPJ_INT32)));
if (buffer32s == NULL) {
_TIFFfree(buf);
TIFFClose(tif);
Expand All @@ -722,7 +735,7 @@ int imagetotif(opj_image_t * image, const char *outfile)
for (i = 0; i < image->comps[0].h; ++i) {
cvtPxToCx(planes, buffer32s, (OPJ_SIZE_T)width, adjust);
cvt32sToTif(buffer32s, (OPJ_BYTE *)buf, (OPJ_SIZE_T)width * numcomps);
(void)TIFFWriteEncodedStrip(tif, i, (void*)buf, strip_size);
(void)TIFFWriteEncodedStrip(tif, i, (void*)buf, (tsize_t)strip_size);
planes[0] += width;
planes[1] += width;
planes[2] += width;
Expand Down Expand Up @@ -1235,20 +1248,18 @@ opj_image_t* tiftoimage(const char *filename, opj_cparameters_t *parameters)
TIFF *tif;
tdata_t buf;
tstrip_t strip;
tsize_t strip_size;
int64_t strip_size, rowStride, TIFF_MAX;
int j, currentPlane, numcomps = 0, w, h;
OPJ_COLOR_SPACE color_space = OPJ_CLRSPC_UNKNOWN;
opj_image_cmptparm_t cmptparm[4]; /* RGBA */
opj_image_t *image = NULL;
int has_alpha = 0;
unsigned short tiBps, tiPhoto, tiSf, tiSpp, tiPC;
unsigned int tiWidth, tiHeight;
uint32 tiBps, tiPhoto, tiSf, tiSpp, tiPC, tiWidth, tiHeight;
OPJ_BOOL is_cinema = OPJ_IS_CINEMA(parameters->rsiz);
convert_XXx32s_C1R cvtTifTo32s = NULL;
convert_32s_CXPX cvtCxToPx = NULL;
OPJ_INT32* buffer32s = NULL;
OPJ_INT32* planes[4];
OPJ_SIZE_T rowStride;

tif = TIFFOpen(filename, "r");

Expand All @@ -1269,20 +1280,33 @@ opj_image_t* tiftoimage(const char *filename, opj_cparameters_t *parameters)
w = (int)tiWidth;
h = (int)tiHeight;

if (tiBps > 16U) {
fprintf(stderr, "tiftoimage: Bits=%d, Only 1 to 16 bits implemented\n", tiBps);
fprintf(stderr, "\tAborting\n");
if (tiSpp == 0 || tiSpp > 4) { /* should be 1 ... 4 */
fprintf(stderr, "tiftoimage: Bad value for samples per pixel == %hu.\n"
"\tAborting.\n", tiSpp);
TIFFClose(tif);
return NULL;
}
if (tiBps > 16U || tiBps == 0) {
fprintf(stderr, "tiftoimage: Bad values for Bits == %d.\n"
"\tMax. 16 Bits are allowed here.\n\tAborting.\n", tiBps);
TIFFClose(tif);
return NULL;
}
if (tiPhoto != PHOTOMETRIC_MINISBLACK && tiPhoto != PHOTOMETRIC_RGB) {
fprintf(stderr,
"tiftoimage: Bad color format %d.\n\tOnly RGB(A) and GRAY(A) has been implemented\n",
"tiftoimage: Bad color format %d.\n\tOnly RGB(A) and GRAY(A) has been implemented\n\tAborting.\n",
(int) tiPhoto);
fprintf(stderr, "\tAborting\n");
TIFFClose(tif);
return NULL;
}
if (tiWidth == 0 || tiHeight == 0) {
fprintf(stderr, "tiftoimage: Bad values for width(%u) "
"and/or height(%u)\n\tAborting.\n", tiWidth, tiHeight);
TIFFClose(tif);
return NULL;
}
w = (int)tiWidth;
h = (int)tiHeight;

switch (tiBps) {
case 1:
Expand Down Expand Up @@ -1405,24 +1429,54 @@ opj_image_t* tiftoimage(const char *filename, opj_cparameters_t *parameters)
image->y0 = (OPJ_UINT32)parameters->image_offset_y0;
image->x1 = !image->x0 ? (OPJ_UINT32)(w - 1) * (OPJ_UINT32)subsampling_dx + 1 :
image->x0 + (OPJ_UINT32)(w - 1) * (OPJ_UINT32)subsampling_dx + 1;
if (image->x1 <= image->x0) {
fprintf(stderr, "tiftoimage: Bad value for image->x1(%d) vs. "
"image->x0(%d)\n\tAborting.\n", image->x1, image->x0);
TIFFClose(tif);
opj_image_destroy(image);
return NULL;
}
image->y1 = !image->y0 ? (OPJ_UINT32)(h - 1) * (OPJ_UINT32)subsampling_dy + 1 :
image->y0 + (OPJ_UINT32)(h - 1) * (OPJ_UINT32)subsampling_dy + 1;
if (image->y1 <= image->y0) {
fprintf(stderr, "tiftoimage: Bad value for image->y1(%d) vs. "
"image->y0(%d)\n\tAborting.\n", image->y1, image->y0);
TIFFClose(tif);
opj_image_destroy(image);
return NULL;
}

for (j = 0; j < numcomps; j++) {
planes[j] = image->comps[j].data;
}
image->comps[numcomps - 1].alpha = (OPJ_UINT16)(1 - (numcomps & 1));

strip_size = TIFFStripSize(tif);
strip_size = (int64_t)TIFFStripSize(tif);

buf = _TIFFmalloc(strip_size);
buf = malloc((OPJ_SIZE_T)strip_size);
if (buf == NULL) {
TIFFClose(tif);
opj_image_destroy(image);
return NULL;
}
rowStride = ((OPJ_SIZE_T)w * tiSpp * tiBps + 7U) / 8U;
buffer32s = (OPJ_INT32 *)malloc((OPJ_SIZE_T)w * tiSpp * sizeof(OPJ_INT32));
if (sizeof(tsize_t) == 4) {
TIFF_MAX = INT_MAX;
} else {
TIFF_MAX = UINT_MAX;
}
if ((int64_t)tiWidth > (int64_t)(TIFF_MAX / tiSpp) ||
(int64_t)(tiWidth * tiSpp) > (int64_t)(TIFF_MAX / tiBps) ||
(int64_t)(tiWidth * tiSpp) > (int64_t)(TIFF_MAX / (int64_t)sizeof(OPJ_INT32))) {
fprintf(stderr, "Buffer overflow\n");
_TIFFfree(buf);
TIFFClose(tif);
opj_image_destroy(image);
return NULL;
}

rowStride = (int64_t)((tiWidth * tiSpp * tiBps + 7U) / 8U);
buffer32s = (OPJ_INT32 *)malloc((OPJ_SIZE_T)(tiWidth * tiSpp * sizeof(
OPJ_INT32)));
if (buffer32s == NULL) {
_TIFFfree(buf);
TIFFClose(tif);
Expand All @@ -1438,9 +1492,19 @@ opj_image_t* tiftoimage(const char *filename, opj_cparameters_t *parameters)
/* Read the Image components */
for (; (h > 0) && (strip < TIFFNumberOfStrips(tif)); strip++) {
const OPJ_UINT8 *dat8;
OPJ_SIZE_T ssize;

ssize = (OPJ_SIZE_T)TIFFReadEncodedStrip(tif, strip, buf, strip_size);
int64_t ssize;

ssize = (int64_t)TIFFReadEncodedStrip(tif, strip, buf, (tsize_t)strip_size);

if (ssize < 1 || ssize > strip_size) {
fprintf(stderr, "tiftoimage: Bad value for ssize(%" PRId64 ") "
"vs. strip_size(%" PRId64 ").\n\tAborting.\n", ssize, strip_size);
_TIFFfree(buf);
_TIFFfree(buffer32s);
TIFFClose(tif);
opj_image_destroy(image);
return NULL;
}
dat8 = (const OPJ_UINT8*)buf;

while (ssize >= rowStride) {
Expand Down
2 changes: 1 addition & 1 deletion src/bin/jp2/opj_decompress.c
Original file line number Diff line number Diff line change
Expand Up @@ -1722,7 +1722,7 @@ int main(int argc, char **argv)
}
free(dirptr);
}
if (numDecompressedImages && !(parameters.quiet)) {
if (numDecompressedImages && !failed && !(parameters.quiet)) {
fprintf(stdout, "decode time: %d ms\n",
(int)((tCumulative * 1000.0) / (OPJ_FLOAT64)numDecompressedImages));
}
Expand Down
Loading