Fuzz: Avoid using temporary files

- When built for fuzzing, expose special versions of tj3LoadImage*()
  that accept a FILE handle.

- Rename cjpeg_main() to cjpeg_fuzzer() and allow a FILE handle to be
  passed to it as well.

- Use fmemopen() to obtain a FILE handle from the fuzzer input data.
This commit is contained in:
DRC
2026-01-09 12:26:14 -05:00
parent e9b497016c
commit ea49d2278c
10 changed files with 152 additions and 98 deletions

View File

@@ -869,6 +869,7 @@ endif()
############################################################################### ###############################################################################
if(WITH_FUZZ) if(WITH_FUZZ)
add_definitions(-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
add_subdirectory(fuzz) add_subdirectory(fuzz)
endif() endif()

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C)2021, 2024 D. R. Commander. All Rights Reserved. * Copyright (C)2021, 2024, 2026 D. R. Commander. All Rights Reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
@@ -29,13 +29,10 @@
/* This fuzz target wraps cjpeg in order to test esoteric compression options /* This fuzz target wraps cjpeg in order to test esoteric compression options
as well as the GIF and Targa readers. */ as well as the GIF and Targa readers. */
#define main cjpeg_main
#define CJPEG_FUZZER #define CJPEG_FUZZER
extern "C" { extern "C" {
#include "../src/cjpeg.c" #include "../src/cjpeg.c"
} }
#undef main
#undef CJPEG_FUZZER
#include <stdint.h> #include <stdint.h>
#include <unistd.h> #include <unistd.h>
@@ -43,40 +40,36 @@ extern "C" {
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{ {
char filename[FILENAME_MAX] = { 0 };
char *argv1[] = { char *argv1[] = {
(char *)"cjpeg", (char *)"-dct", (char *)"float", (char *)"-memdst", (char *)"cjpeg", (char *)"-dct", (char *)"float", (char *)"-memdst",
(char *)"-optimize", (char *)"-quality", (char *)"100,99,98", (char *)"-optimize", (char *)"-quality", (char *)"100,99,98",
(char *)"-restart", (char *)"2", (char *)"-sample", (char *)"4x1,2x2,1x2", (char *)"-restart", (char *)"2", (char *)"-sample", (char *)"4x1,2x2,1x2",
(char *)"-targa", NULL (char *)"-targa"
}; };
char *argv2[] = { char *argv2[] = {
(char *)"cjpeg", (char *)"-arithmetic", (char *)"-dct", (char *)"float", (char *)"cjpeg", (char *)"-arithmetic", (char *)"-dct", (char *)"float",
(char *)"-memdst", (char *)"-quality", (char *)"90,80,70", (char *)"-rgb", (char *)"-memdst", (char *)"-quality", (char *)"90,80,70", (char *)"-rgb",
(char *)"-sample", (char *)"2x2", (char *)"-smooth", (char *)"50", (char *)"-sample", (char *)"2x2", (char *)"-smooth", (char *)"50",
(char *)"-targa", NULL (char *)"-targa"
}; };
int fd = -1; FILE *file = NULL;
snprintf(filename, FILENAME_MAX, "/tmp/libjpeg-turbo_cjpeg_fuzz.XXXXXX"); if ((file = fmemopen((void *)data, size, "r")) == NULL)
if ((fd = mkstemp(filename)) < 0 || write(fd, data, size) < 0)
goto bailout; goto bailout;
argv1[12] = argv2[13] = filename; fseek(file, 0, SEEK_SET);
cjpeg_fuzzer(12, argv1, file);
fseek(file, 0, SEEK_SET);
cjpeg_fuzzer(13, argv2, file);
cjpeg_main(13, argv1); argv1[11] = argv2[12] = NULL;
cjpeg_main(14, argv2);
argv1[12] = argv2[13] = NULL; fseek(file, 0, SEEK_SET);
argv1[11] = argv2[12] = filename; cjpeg_fuzzer(11, argv1, file);
fseek(file, 0, SEEK_SET);
cjpeg_main(12, argv1); cjpeg_fuzzer(12, argv2, file);
cjpeg_main(13, argv2);
bailout: bailout:
if (fd >= 0) { if (file) fclose(file);
close(fd);
if (strlen(filename) > 0) unlink(filename);
}
return 0; return 0;
} }

View File

@@ -33,6 +33,10 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
extern "C" unsigned char *
_tj3LoadImageFromFileHandle8(tjhandle handle, FILE *file, int *width,
int align, int *height, int *pixelFormat);
#define NUMTESTS 7 #define NUMTESTS 7
@@ -48,8 +52,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{ {
tjhandle handle = NULL; tjhandle handle = NULL;
unsigned char *srcBuf = NULL, *dstBuf = NULL; unsigned char *srcBuf = NULL, *dstBuf = NULL;
int width = 0, height = 0, fd = -1, ti; int width = 0, height = 0, ti;
char filename[FILENAME_MAX] = { 0 }; FILE *file = NULL;
struct test tests[NUMTESTS] = { struct test tests[NUMTESTS] = {
{ TJPF_RGB, TJSAMP_444, 100 }, { TJPF_RGB, TJSAMP_444, 100 },
{ TJPF_BGR, TJSAMP_422, 90 }, { TJPF_BGR, TJSAMP_422, 90 },
@@ -60,8 +64,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{ TJPF_CMYK, TJSAMP_440, 40 } { TJPF_CMYK, TJSAMP_440, 40 }
}; };
snprintf(filename, FILENAME_MAX, "/tmp/libjpeg-turbo_compress_fuzz.XXXXXX"); if ((file = fmemopen((void *)data, size, "r")) == NULL)
if ((fd = mkstemp(filename)) < 0 || write(fd, data, size) < 0)
goto bailout; goto bailout;
if ((handle = tj3Init(TJINIT_COMPRESS)) == NULL) if ((handle = tj3Init(TJINIT_COMPRESS)) == NULL)
@@ -83,8 +86,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
tj3Set(handle, TJPARAM_MAXPIXELS, 1048576); tj3Set(handle, TJPARAM_MAXPIXELS, 1048576);
/* tj3LoadImage8() will refuse to load images larger than 1 Megapixel, so /* tj3LoadImage8() will refuse to load images larger than 1 Megapixel, so
we don't need to check the width and height here. */ we don't need to check the width and height here. */
if ((srcBuf = tj3LoadImage8(handle, filename, &width, 1, &height, fseek(file, 0, SEEK_SET);
&pf)) == NULL) if ((srcBuf = _tj3LoadImageFromFileHandle8(handle, file, &width, 1,
&height, &pf)) == NULL)
continue; continue;
dstSize = maxBufSize = tj3JPEGBufSize(width, height, tests[ti].subsamp); dstSize = maxBufSize = tj3JPEGBufSize(width, height, tests[ti].subsamp);
@@ -118,10 +122,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
bailout: bailout:
tj3Free(dstBuf); tj3Free(dstBuf);
tj3Free(srcBuf); tj3Free(srcBuf);
if (fd >= 0) { if (file) fclose(file);
close(fd);
if (strlen(filename) > 0) unlink(filename);
}
tj3Destroy(handle); tj3Destroy(handle);
return 0; return 0;
} }

View File

@@ -33,6 +33,10 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
extern "C" short *
_tj3LoadImageFromFileHandle12(tjhandle handle, FILE *file, int *width,
int align, int *height, int *pixelFormat);
#define NUMTESTS 7 #define NUMTESTS 7
@@ -49,8 +53,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
tjhandle handle = NULL; tjhandle handle = NULL;
short *srcBuf = NULL; short *srcBuf = NULL;
unsigned char *dstBuf = NULL; unsigned char *dstBuf = NULL;
int width = 0, height = 0, fd = -1, ti; int width = 0, height = 0, ti;
char filename[FILENAME_MAX] = { 0 }; FILE *file = NULL;
struct test tests[NUMTESTS] = { struct test tests[NUMTESTS] = {
{ TJPF_RGB, TJSAMP_444, 100 }, { TJPF_RGB, TJSAMP_444, 100 },
{ TJPF_BGR, TJSAMP_422, 90 }, { TJPF_BGR, TJSAMP_422, 90 },
@@ -61,8 +65,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{ TJPF_CMYK, TJSAMP_440, 40 } { TJPF_CMYK, TJSAMP_440, 40 }
}; };
snprintf(filename, FILENAME_MAX, "/tmp/libjpeg-turbo_compress12_fuzz.XXXXXX"); if ((file = fmemopen((void *)data, size, "r")) == NULL)
if ((fd = mkstemp(filename)) < 0 || write(fd, data, size) < 0)
goto bailout; goto bailout;
if ((handle = tj3Init(TJINIT_COMPRESS)) == NULL) if ((handle = tj3Init(TJINIT_COMPRESS)) == NULL)
@@ -83,8 +86,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
tj3Set(handle, TJPARAM_MAXPIXELS, 1048576); tj3Set(handle, TJPARAM_MAXPIXELS, 1048576);
/* tj3LoadImage12() will refuse to load images larger than 1 Megapixel, so /* tj3LoadImage12() will refuse to load images larger than 1 Megapixel, so
we don't need to check the width and height here. */ we don't need to check the width and height here. */
if ((srcBuf = tj3LoadImage12(handle, filename, &width, 1, &height, fseek(file, 0, SEEK_SET);
&pf)) == NULL) if ((srcBuf = _tj3LoadImageFromFileHandle12(handle, file, &width, 1,
&height, &pf)) == NULL)
continue; continue;
dstSize = maxBufSize = tj3JPEGBufSize(width, height, tests[ti].subsamp); dstSize = maxBufSize = tj3JPEGBufSize(width, height, tests[ti].subsamp);
@@ -118,10 +122,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
bailout: bailout:
tj3Free(dstBuf); tj3Free(dstBuf);
tj3Free(srcBuf); tj3Free(srcBuf);
if (fd >= 0) { if (file) fclose(file);
close(fd);
if (strlen(filename) > 0) unlink(filename);
}
tj3Destroy(handle); tj3Destroy(handle);
return 0; return 0;
} }

View File

@@ -33,6 +33,10 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
extern "C" short *
_tj3LoadImageFromFileHandle12(tjhandle handle, FILE *file, int *width,
int align, int *height, int *pixelFormat);
#define NUMTESTS 7 #define NUMTESTS 7
@@ -48,8 +52,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
tjhandle handle = NULL; tjhandle handle = NULL;
short *srcBuf = NULL; short *srcBuf = NULL;
unsigned char *dstBuf = NULL; unsigned char *dstBuf = NULL;
int width = 0, height = 0, fd = -1, ti; int width = 0, height = 0, ti;
char filename[FILENAME_MAX] = { 0 }; FILE *file = NULL;
struct test tests[NUMTESTS] = { struct test tests[NUMTESTS] = {
{ TJPF_RGB, 12, 1, 0 }, { TJPF_RGB, 12, 1, 0 },
{ TJPF_BGR, 11, 2, 2 }, { TJPF_BGR, 11, 2, 2 },
@@ -60,8 +64,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{ TJPF_CMYK, 12, 7, 0 } { TJPF_CMYK, 12, 7, 0 }
}; };
snprintf(filename, FILENAME_MAX, "/tmp/libjpeg-turbo_compress_fuzz.XXXXXX"); if ((file = fmemopen((void *)data, size, "r")) == NULL)
if ((fd = mkstemp(filename)) < 0 || write(fd, data, size) < 0)
goto bailout; goto bailout;
if ((handle = tj3Init(TJINIT_COMPRESS)) == NULL) if ((handle = tj3Init(TJINIT_COMPRESS)) == NULL)
@@ -80,8 +83,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
tj3Set(handle, TJPARAM_MAXPIXELS, 1048576); tj3Set(handle, TJPARAM_MAXPIXELS, 1048576);
/* tj3LoadImage12() will refuse to load images larger than 1 Megapixel, so /* tj3LoadImage12() will refuse to load images larger than 1 Megapixel, so
we don't need to check the width and height here. */ we don't need to check the width and height here. */
if ((srcBuf = tj3LoadImage12(handle, filename, &width, 1, &height, fseek(file, 0, SEEK_SET);
&pf)) == NULL) if ((srcBuf = _tj3LoadImageFromFileHandle12(handle, file, &width, 1,
&height, &pf)) == NULL)
continue; continue;
dstSize = maxBufSize = tj3JPEGBufSize(width, height, TJSAMP_444); dstSize = maxBufSize = tj3JPEGBufSize(width, height, TJSAMP_444);
@@ -116,10 +120,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
bailout: bailout:
tj3Free(dstBuf); tj3Free(dstBuf);
tj3Free(srcBuf); tj3Free(srcBuf);
if (fd >= 0) { if (file) fclose(file);
close(fd);
if (strlen(filename) > 0) unlink(filename);
}
tj3Destroy(handle); tj3Destroy(handle);
return 0; return 0;
} }

View File

@@ -33,6 +33,10 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
extern "C" unsigned short *
_tj3LoadImageFromFileHandle16(tjhandle handle, FILE *file, int *width,
int align, int *height, int *pixelFormat);
#define NUMTESTS 7 #define NUMTESTS 7
@@ -48,8 +52,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
tjhandle handle = NULL; tjhandle handle = NULL;
unsigned short *srcBuf = NULL; unsigned short *srcBuf = NULL;
unsigned char *dstBuf = NULL; unsigned char *dstBuf = NULL;
int width = 0, height = 0, fd = -1, ti; int width = 0, height = 0, ti;
char filename[FILENAME_MAX] = { 0 }; FILE *file = NULL;
struct test tests[NUMTESTS] = { struct test tests[NUMTESTS] = {
{ TJPF_RGB, 16, 1, 0 }, { TJPF_RGB, 16, 1, 0 },
{ TJPF_BGR, 15, 2, 2 }, { TJPF_BGR, 15, 2, 2 },
@@ -60,8 +64,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{ TJPF_CMYK, 16, 7, 0 } { TJPF_CMYK, 16, 7, 0 }
}; };
snprintf(filename, FILENAME_MAX, "/tmp/libjpeg-turbo_compress_fuzz.XXXXXX"); if ((file = fmemopen((void *)data, size, "r")) == NULL)
if ((fd = mkstemp(filename)) < 0 || write(fd, data, size) < 0)
goto bailout; goto bailout;
if ((handle = tj3Init(TJINIT_COMPRESS)) == NULL) if ((handle = tj3Init(TJINIT_COMPRESS)) == NULL)
@@ -80,8 +83,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
tj3Set(handle, TJPARAM_MAXPIXELS, 1048576); tj3Set(handle, TJPARAM_MAXPIXELS, 1048576);
/* tj3LoadImage16() will refuse to load images larger than 1 Megapixel, so /* tj3LoadImage16() will refuse to load images larger than 1 Megapixel, so
we don't need to check the width and height here. */ we don't need to check the width and height here. */
if ((srcBuf = tj3LoadImage16(handle, filename, &width, 1, &height, fseek(file, 0, SEEK_SET);
&pf)) == NULL) if ((srcBuf = _tj3LoadImageFromFileHandle16(handle, file, &width, 1,
&height, &pf)) == NULL)
continue; continue;
dstSize = maxBufSize = tj3JPEGBufSize(width, height, TJSAMP_444); dstSize = maxBufSize = tj3JPEGBufSize(width, height, TJSAMP_444);
@@ -116,10 +120,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
bailout: bailout:
tj3Free(dstBuf); tj3Free(dstBuf);
tj3Free(srcBuf); tj3Free(srcBuf);
if (fd >= 0) { if (file) fclose(file);
close(fd);
if (strlen(filename) > 0) unlink(filename);
}
tj3Destroy(handle); tj3Destroy(handle);
return 0; return 0;
} }

View File

@@ -33,6 +33,10 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
extern "C" unsigned char *
_tj3LoadImageFromFileHandle8(tjhandle handle, FILE *file, int *width,
int align, int *height, int *pixelFormat);
#define NUMTESTS 7 #define NUMTESTS 7
@@ -47,8 +51,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{ {
tjhandle handle = NULL; tjhandle handle = NULL;
unsigned char *srcBuf = NULL, *dstBuf = NULL; unsigned char *srcBuf = NULL, *dstBuf = NULL;
int width = 0, height = 0, fd = -1, ti; int width = 0, height = 0, ti;
char filename[FILENAME_MAX] = { 0 }; FILE *file = NULL;
struct test tests[NUMTESTS] = { struct test tests[NUMTESTS] = {
{ TJPF_RGB, 8, 1, 0 }, { TJPF_RGB, 8, 1, 0 },
{ TJPF_BGR, 7, 2, 5 }, { TJPF_BGR, 7, 2, 5 },
@@ -59,8 +63,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{ TJPF_CMYK, 2, 7, 0 } { TJPF_CMYK, 2, 7, 0 }
}; };
snprintf(filename, FILENAME_MAX, "/tmp/libjpeg-turbo_compress_fuzz.XXXXXX"); if ((file = fmemopen((void *)data, size, "r")) == NULL)
if ((fd = mkstemp(filename)) < 0 || write(fd, data, size) < 0)
goto bailout; goto bailout;
if ((handle = tj3Init(TJINIT_COMPRESS)) == NULL) if ((handle = tj3Init(TJINIT_COMPRESS)) == NULL)
@@ -79,8 +82,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
tj3Set(handle, TJPARAM_MAXPIXELS, 1048576); tj3Set(handle, TJPARAM_MAXPIXELS, 1048576);
/* tj3LoadImage8() will refuse to load images larger than 1 Megapixel, so /* tj3LoadImage8() will refuse to load images larger than 1 Megapixel, so
we don't need to check the width and height here. */ we don't need to check the width and height here. */
if ((srcBuf = tj3LoadImage8(handle, filename, &width, 1, &height, fseek(file, 0, SEEK_SET);
&pf)) == NULL) if ((srcBuf = _tj3LoadImageFromFileHandle8(handle, file, &width, 1,
&height, &pf)) == NULL)
continue; continue;
dstSize = maxBufSize = tj3JPEGBufSize(width, height, TJSAMP_444); dstSize = maxBufSize = tj3JPEGBufSize(width, height, TJSAMP_444);
@@ -115,10 +119,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
bailout: bailout:
tj3Free(dstBuf); tj3Free(dstBuf);
tj3Free(srcBuf); tj3Free(srcBuf);
if (fd >= 0) { if (file) fclose(file);
close(fd);
if (strlen(filename) > 0) unlink(filename);
}
tj3Destroy(handle); tj3Destroy(handle);
return 0; return 0;
} }

View File

@@ -33,6 +33,10 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
extern "C" unsigned char *
_tj3LoadImageFromFileHandle8(tjhandle handle, FILE *file, int *width,
int align, int *height, int *pixelFormat);
#define NUMTESTS 6 #define NUMTESTS 6
@@ -48,8 +52,8 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{ {
tjhandle handle = NULL; tjhandle handle = NULL;
unsigned char *srcBuf = NULL, *dstBuf = NULL, *yuvBuf = NULL; unsigned char *srcBuf = NULL, *dstBuf = NULL, *yuvBuf = NULL;
int width = 0, height = 0, fd = -1, ti; int width = 0, height = 0, ti;
char filename[FILENAME_MAX] = { 0 }; FILE *file = NULL;
struct test tests[NUMTESTS] = { struct test tests[NUMTESTS] = {
{ TJPF_XBGR, TJSAMP_444, 100 }, { TJPF_XBGR, TJSAMP_444, 100 },
{ TJPF_XRGB, TJSAMP_422, 90 }, { TJPF_XRGB, TJSAMP_422, 90 },
@@ -59,8 +63,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{ TJPF_GRAY, TJSAMP_GRAY, 50 } { TJPF_GRAY, TJSAMP_GRAY, 50 }
}; };
snprintf(filename, FILENAME_MAX, "/tmp/libjpeg-turbo_compress_yuv_fuzz.XXXXXX"); if ((file = fmemopen((void *)data, size, "r")) == NULL)
if ((fd = mkstemp(filename)) < 0 || write(fd, data, size) < 0)
goto bailout; goto bailout;
if ((handle = tj3Init(TJINIT_COMPRESS)) == NULL) if ((handle = tj3Init(TJINIT_COMPRESS)) == NULL)
@@ -82,8 +85,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
tj3Set(handle, TJPARAM_MAXPIXELS, 1048576); tj3Set(handle, TJPARAM_MAXPIXELS, 1048576);
/* tj3LoadImage8() will refuse to load images larger than 1 Megapixel, so /* tj3LoadImage8() will refuse to load images larger than 1 Megapixel, so
we don't need to check the width and height here. */ we don't need to check the width and height here. */
if ((srcBuf = tj3LoadImage8(handle, filename, &width, 1, &height, fseek(file, 0, SEEK_SET);
&pf)) == NULL) if ((srcBuf = _tj3LoadImageFromFileHandle8(handle, file, &width, 1,
&height, &pf)) == NULL)
continue; continue;
dstSize = maxBufSize = tj3JPEGBufSize(width, height, tests[ti].subsamp); dstSize = maxBufSize = tj3JPEGBufSize(width, height, tests[ti].subsamp);
@@ -123,10 +127,7 @@ bailout:
tj3Free(dstBuf); tj3Free(dstBuf);
free(yuvBuf); free(yuvBuf);
tj3Free(srcBuf); tj3Free(srcBuf);
if (fd >= 0) { if (file) fclose(file);
close(fd);
if (strlen(filename) > 0) unlink(filename);
}
tj3Destroy(handle); tj3Destroy(handle);
return 0; return 0;
} }

View File

@@ -7,7 +7,7 @@
* Lossless JPEG Modifications: * Lossless JPEG Modifications:
* Copyright (C) 1999, Ken Murchison. * Copyright (C) 1999, Ken Murchison.
* libjpeg-turbo Modifications: * libjpeg-turbo Modifications:
* Copyright (C) 2010, 2013-2014, 2017, 2019-2022, 2024-2025, * Copyright (C) 2010, 2013-2014, 2017, 2019-2022, 2024-2026,
* D. R. Commander. * D. R. Commander.
* For conditions of distribution and use, see the accompanying README.ijg * For conditions of distribution and use, see the accompanying README.ijg
* file. * file.
@@ -162,7 +162,7 @@ struct my_error_mgr {
jmp_buf setjmp_buffer; jmp_buf setjmp_buffer;
}; };
void my_error_exit(j_common_ptr cinfo) static void my_error_exit(j_common_ptr cinfo)
{ {
struct my_error_mgr *myerr = (struct my_error_mgr *)cinfo->err; struct my_error_mgr *myerr = (struct my_error_mgr *)cinfo->err;
@@ -182,8 +182,6 @@ static void my_emit_message_fuzzer(j_common_ptr cinfo, int msg_level)
jpeg_abort_compress(&cinfo); \ jpeg_abort_compress(&cinfo); \
} \ } \
jpeg_destroy_compress(&cinfo); \ jpeg_destroy_compress(&cinfo); \
if (input_file != stdin && input_file != NULL) \
fclose(input_file); \
if (memdst) \ if (memdst) \
free(outbuffer); \ free(outbuffer); \
free(icc_profile); \ free(icc_profile); \
@@ -616,8 +614,13 @@ my_emit_message(j_common_ptr cinfo, int msg_level)
* The main program. * The main program.
*/ */
#ifdef CJPEG_FUZZER
static int
cjpeg_fuzzer(int argc, char **argv, FILE *input_file)
#else
int int
main(int argc, char **argv) main(int argc, char **argv)
#endif
{ {
struct jpeg_compress_struct cinfo; struct jpeg_compress_struct cinfo;
#ifdef CJPEG_FUZZER #ifdef CJPEG_FUZZER
@@ -629,7 +632,9 @@ main(int argc, char **argv)
struct cdjpeg_progress_mgr progress; struct cdjpeg_progress_mgr progress;
int file_index; int file_index;
cjpeg_source_ptr src_mgr; cjpeg_source_ptr src_mgr;
#ifndef CJPEG_FUZZER
FILE *input_file = NULL; FILE *input_file = NULL;
#endif
FILE *icc_file; FILE *icc_file;
JOCTET *icc_profile = NULL; JOCTET *icc_profile = NULL;
long icc_len = 0; long icc_len = 0;
@@ -696,6 +701,7 @@ main(int argc, char **argv)
} }
#endif /* TWO_FILE_COMMANDLINE */ #endif /* TWO_FILE_COMMANDLINE */
#ifndef CJPEG_FUZZER
/* Open the input file. */ /* Open the input file. */
if (file_index < argc) { if (file_index < argc) {
if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) { if ((input_file = fopen(argv[file_index], READ_BINARY)) == NULL) {
@@ -706,6 +712,7 @@ main(int argc, char **argv)
/* default input file is stdin */ /* default input file is stdin */
input_file = read_stdin(); input_file = read_stdin();
} }
#endif
/* Open the output file. */ /* Open the output file. */
if (outfilename != NULL) { if (outfilename != NULL) {
@@ -818,8 +825,10 @@ main(int argc, char **argv)
jpeg_destroy_compress(&cinfo); jpeg_destroy_compress(&cinfo);
/* Close files, if we opened them */ /* Close files, if we opened them */
#ifndef CJPEG_FUZZER
if (input_file != stdin) if (input_file != stdin)
fclose(input_file); fclose(input_file);
#endif
if (output_file != stdout && output_file != NULL) if (output_file != stdout && output_file != NULL)
fclose(output_file); fclose(output_file);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C)2009-2025 D. R. Commander. All Rights Reserved. * Copyright (C)2009-2026 D. R. Commander. All Rights Reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
@@ -290,8 +290,11 @@ bailout:
/*************************** Packed-Pixel Image I/O **************************/ /*************************** Packed-Pixel Image I/O **************************/
/* TurboJPEG 3.0+ */ /* TurboJPEG 3.0+ */
DLLEXPORT _JSAMPLE *GET_NAME(tj3LoadImage, BITS_IN_JSAMPLE) #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
(tjhandle handle, const char *filename, int *width, int align, int *height, static
#endif
_JSAMPLE *GET_NAME(_tj3LoadImageFromFileHandle, BITS_IN_JSAMPLE)
(tjhandle handle, FILE *file, int *width, int align, int *height,
int *pixelFormat) int *pixelFormat)
{ {
static const char FUNCTION_NAME[] = static const char FUNCTION_NAME[] =
@@ -306,12 +309,11 @@ DLLEXPORT _JSAMPLE *GET_NAME(tj3LoadImage, BITS_IN_JSAMPLE)
j_compress_ptr cinfo = NULL; j_compress_ptr cinfo = NULL;
cjpeg_source_ptr src; cjpeg_source_ptr src;
_JSAMPLE *dstBuf = NULL; _JSAMPLE *dstBuf = NULL;
FILE *file = NULL;
boolean invert; boolean invert;
GET_TJINSTANCE(handle, NULL) GET_TJINSTANCE(handle, NULL)
if (!filename || !width || align < 1 || !height || !pixelFormat || if (!file || !width || align < 1 || !height || !pixelFormat ||
*pixelFormat < TJPF_UNKNOWN || *pixelFormat >= TJ_NUMPF) *pixelFormat < TJPF_UNKNOWN || *pixelFormat >= TJ_NUMPF)
THROW("Invalid argument"); THROW("Invalid argument");
if ((align & (align - 1)) != 0) if ((align & (align - 1)) != 0)
@@ -324,13 +326,6 @@ DLLEXPORT _JSAMPLE *GET_NAME(tj3LoadImage, BITS_IN_JSAMPLE)
this2 = (tjinstance *)handle2; this2 = (tjinstance *)handle2;
cinfo = &this2->cinfo; cinfo = &this2->cinfo;
#ifdef _MSC_VER
if (fopen_s(&file, filename, "rb") || file == NULL)
#else
if ((file = fopen(filename, "rb")) == NULL)
#endif
THROW_UNIX("Cannot open input file");
if ((tempc = getc(file)) < 0 || ungetc(tempc, file) == EOF) if ((tempc = getc(file)) < 0 || ungetc(tempc, file) == EOF)
THROW_UNIX("Could not read input file") THROW_UNIX("Could not read input file")
else if (tempc == EOF) else if (tempc == EOF)
@@ -415,6 +410,56 @@ DLLEXPORT _JSAMPLE *GET_NAME(tj3LoadImage, BITS_IN_JSAMPLE)
bailout: bailout:
tj3Destroy(handle2); tj3Destroy(handle2);
if (retval < 0) { free(dstBuf); dstBuf = NULL; }
return dstBuf;
#else /* BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED) */
static const char ERROR_MSG[] =
"16-bit data precision requires lossless JPEG,\n"
"which was disabled at build time.";
_JSAMPLE *retval = NULL;
GET_TJINSTANCE(handle, NULL)
SNPRINTF(this->errStr, JMSG_LENGTH_MAX, "%s(): %s", FUNCTION_NAME,
ERROR_MSG);
this->isInstanceError = TRUE; THROWG(ERROR_MSG, NULL)
bailout:
return retval;
#endif
}
DLLEXPORT _JSAMPLE *GET_NAME(tj3LoadImage, BITS_IN_JSAMPLE)
(tjhandle handle, const char *filename, int *width, int align, int *height,
int *pixelFormat)
{
static const char FUNCTION_NAME[] =
GET_STRING(tj3LoadImage, BITS_IN_JSAMPLE);
#if BITS_IN_JSAMPLE != 16 || defined(C_LOSSLESS_SUPPORTED)
int retval = 0;
_JSAMPLE *dstBuf = NULL;
FILE *file = NULL;
GET_TJINSTANCE(handle, NULL)
if (!filename)
THROW("Invalid argument");
#ifdef _MSC_VER
if (fopen_s(&file, filename, "rb") || file == NULL)
#else
if ((file = fopen(filename, "rb")) == NULL)
#endif
THROW_UNIX("Cannot open input file");
dstBuf = GET_NAME(_tj3LoadImageFromFileHandle, BITS_IN_JSAMPLE)
(handle, file, width, align, height, pixelFormat);
bailout:
if (file) fclose(file); if (file) fclose(file);
if (retval < 0) { free(dstBuf); dstBuf = NULL; } if (retval < 0) { free(dstBuf); dstBuf = NULL; }
return dstBuf; return dstBuf;