mirror of
https://github.com/libjpeg-turbo/libjpeg-turbo.git
synced 2026-01-18 13:31:21 +01:00
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:
@@ -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()
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
17
src/cjpeg.c
17
src/cjpeg.c
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user