aboutsummaryrefslogtreecommitdiff
path: root/turbojpeg.c
diff options
context:
space:
mode:
Diffstat (limited to 'turbojpeg.c')
-rw-r--r--turbojpeg.c84
1 files changed, 78 insertions, 6 deletions
diff --git a/turbojpeg.c b/turbojpeg.c
index 8260555b..793a3eed 100644
--- a/turbojpeg.c
+++ b/turbojpeg.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C)2009-2020 D. R. Commander. All Rights Reserved.
+ * Copyright (C)2009-2021 D. R. Commander. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -112,6 +112,32 @@ typedef struct _tjinstance {
boolean isInstanceError;
} tjinstance;
+struct my_progress_mgr {
+ struct jpeg_progress_mgr pub;
+ tjinstance *this;
+};
+typedef struct my_progress_mgr *my_progress_ptr;
+
+static void my_progress_monitor(j_common_ptr dinfo)
+{
+ my_error_ptr myerr = (my_error_ptr)dinfo->err;
+ my_progress_ptr myprog = (my_progress_ptr)dinfo->progress;
+
+ if (dinfo->is_decompressor) {
+ int scan_no = ((j_decompress_ptr)dinfo)->input_scan_number;
+
+ if (scan_no > 500) {
+ snprintf(myprog->this->errStr, JMSG_LENGTH_MAX,
+ "Progressive JPEG image has more than 500 scans");
+ snprintf(errStr, JMSG_LENGTH_MAX,
+ "Progressive JPEG image has more than 500 scans");
+ myprog->this->isInstanceError = TRUE;
+ myerr->warning = FALSE;
+ longjmp(myerr->setjmp_buffer, 1);
+ }
+ }
+}
+
static const int pixelsize[TJ_NUMSAMP] = { 3, 3, 3, 1, 3, 3 };
static const JXFORM_CODE xformtypes[TJ_NUMXOP] = {
@@ -178,6 +204,11 @@ static int cs2pf[JPEG_NUMCS] = {
this->isInstanceError = TRUE; THROWG(m) \
}
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+/* Private flag that triggers different TurboJPEG API behavior when fuzzing */
+#define TJFLAG_FUZZING (1 << 30)
+#endif
+
#define GET_INSTANCE(handle) \
tjinstance *this = (tjinstance *)handle; \
j_compress_ptr cinfo = NULL; \
@@ -689,7 +720,10 @@ DLLEXPORT int tjCompress2(tjhandle handle, const unsigned char *srcBuf,
jpeg_finish_compress(cinfo);
bailout:
- if (cinfo->global_state > CSTATE_START) jpeg_abort_compress(cinfo);
+ if (cinfo->global_state > CSTATE_START) {
+ if (alloc) (*cinfo->dest->term_destination) (cinfo);
+ jpeg_abort_compress(cinfo);
+ }
free(row_pointer);
if (this->jerr.warning) retval = -1;
this->jerr.stopOnWarning = FALSE;
@@ -1057,7 +1091,10 @@ DLLEXPORT int tjCompressFromYUVPlanes(tjhandle handle,
jpeg_finish_compress(cinfo);
bailout:
- if (cinfo->global_state > CSTATE_START) jpeg_abort_compress(cinfo);
+ if (cinfo->global_state > CSTATE_START) {
+ if (alloc) (*cinfo->dest->term_destination) (cinfo);
+ jpeg_abort_compress(cinfo);
+ }
for (i = 0; i < MAX_COMPONENTS; i++) {
free(tmpbuf[i]);
free(inbuf[i]);
@@ -1245,6 +1282,7 @@ DLLEXPORT int tjDecompress2(tjhandle handle, const unsigned char *jpegBuf,
{
JSAMPROW *row_pointer = NULL;
int i, retval = 0, jpegwidth, jpegheight, scaledw, scaledh;
+ struct my_progress_mgr progress;
GET_DINSTANCE(handle);
this->jerr.stopOnWarning = (flags & TJFLAG_STOPONWARNING) ? TRUE : FALSE;
@@ -1261,6 +1299,14 @@ DLLEXPORT int tjDecompress2(tjhandle handle, const unsigned char *jpegBuf,
else if (flags & TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
#endif
+ if (flags & TJFLAG_LIMITSCANS) {
+ MEMZERO(&progress, sizeof(struct my_progress_mgr));
+ progress.pub.progress_monitor = my_progress_monitor;
+ progress.this = this;
+ dinfo->progress = &progress.pub;
+ } else
+ dinfo->progress = NULL;
+
if (setjmp(this->jerr.setjmp_buffer)) {
/* If we get here, the JPEG code has signaled an error. */
retval = -1; goto bailout;
@@ -1579,6 +1625,7 @@ DLLEXPORT int tjDecompressToYUVPlanes(tjhandle handle,
JSAMPLE *_tmpbuf = NULL, *ptr;
JSAMPROW *outbuf[MAX_COMPONENTS], *tmpbuf[MAX_COMPONENTS];
int dctsize;
+ struct my_progress_mgr progress;
GET_DINSTANCE(handle);
this->jerr.stopOnWarning = (flags & TJFLAG_STOPONWARNING) ? TRUE : FALSE;
@@ -1600,6 +1647,14 @@ DLLEXPORT int tjDecompressToYUVPlanes(tjhandle handle,
else if (flags & TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
#endif
+ if (flags & TJFLAG_LIMITSCANS) {
+ MEMZERO(&progress, sizeof(struct my_progress_mgr));
+ progress.pub.progress_monitor = my_progress_monitor;
+ progress.this = this;
+ dinfo->progress = &progress.pub;
+ } else
+ dinfo->progress = NULL;
+
if (setjmp(this->jerr.setjmp_buffer)) {
/* If we get here, the JPEG code has signaled an error. */
retval = -1; goto bailout;
@@ -1837,7 +1892,8 @@ DLLEXPORT int tjTransform(tjhandle handle, const unsigned char *jpegBuf,
{
jpeg_transform_info *xinfo = NULL;
jvirt_barray_ptr *srccoefs, *dstcoefs;
- int retval = 0, i, jpegSubsamp, saveMarkers = 0;
+ int retval = 0, alloc = 1, i, jpegSubsamp, saveMarkers = 0;
+ struct my_progress_mgr progress;
GET_INSTANCE(handle);
this->jerr.stopOnWarning = (flags & TJFLAG_STOPONWARNING) ? TRUE : FALSE;
@@ -1854,6 +1910,14 @@ DLLEXPORT int tjTransform(tjhandle handle, const unsigned char *jpegBuf,
else if (flags & TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
#endif
+ if (flags & TJFLAG_LIMITSCANS) {
+ MEMZERO(&progress, sizeof(struct my_progress_mgr));
+ progress.pub.progress_monitor = my_progress_monitor;
+ progress.this = this;
+ dinfo->progress = &progress.pub;
+ } else
+ dinfo->progress = NULL;
+
if ((xinfo =
(jpeg_transform_info *)malloc(sizeof(jpeg_transform_info) * n)) == NULL)
THROW("tjTransform(): Memory allocation failure");
@@ -1916,7 +1980,7 @@ DLLEXPORT int tjTransform(tjhandle handle, const unsigned char *jpegBuf,
srccoefs = jpeg_read_coefficients(dinfo);
for (i = 0; i < n; i++) {
- int w, h, alloc = 1;
+ int w, h;
if (!xinfo[i].crop) {
w = dinfo->image_width; h = dinfo->image_height;
@@ -1974,7 +2038,10 @@ DLLEXPORT int tjTransform(tjhandle handle, const unsigned char *jpegBuf,
jpeg_finish_decompress(dinfo);
bailout:
- if (cinfo->global_state > CSTATE_START) jpeg_abort_compress(cinfo);
+ if (cinfo->global_state > CSTATE_START) {
+ if (alloc) (*cinfo->dest->term_destination) (cinfo);
+ jpeg_abort_compress(cinfo);
+ }
if (dinfo->global_state > DSTATE_START) jpeg_abort_decompress(dinfo);
free(xinfo);
if (this->jerr.warning) retval = -1;
@@ -2034,6 +2101,11 @@ DLLEXPORT unsigned char *tjLoadImage(const char *filename, int *width,
THROWG("tjLoadImage(): Unsupported file type");
src->input_file = file;
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ /* Refuse to load images larger than 1 Megapixel when fuzzing. */
+ if (flags & TJFLAG_FUZZING)
+ src->max_pixels = 1048576;
+#endif
(*src->start_input) (cinfo, src);
(*cinfo->mem->realize_virt_arrays) ((j_common_ptr)cinfo);