2 * Copyright (C)2021-2023 D. R. Commander. All Rights Reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
7 * - Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * - Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12 * - Neither the name of the libjpeg-turbo Project nor the names of its
13 * contributors may be used to endorse or promote products derived from this
14 * software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
29 #include <turbojpeg.h>
35 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
37 tjhandle handle = NULL;
38 unsigned char *dstBufs[1] = { NULL };
39 size_t dstSizes[1] = { 0 }, maxBufSize;
40 int width = 0, height = 0, jpegSubsamp, i;
41 tjtransform transforms[1];
42 #if defined(__has_feature) && __has_feature(memory_sanitizer)
43 char env[18] = "JSIMD_FORCENONE=1";
45 /* The libjpeg-turbo SIMD extensions produce false positives with
50 if ((handle = tj3Init(TJINIT_TRANSFORM)) == NULL)
53 /* We ignore the return value of tj3DecompressHeader(), because malformed
54 JPEG images that might expose issues in libjpeg-turbo might also have
55 header errors that cause tj3DecompressHeader() to fail. */
56 tj3DecompressHeader(handle, data, size);
57 width = tj3Get(handle, TJPARAM_JPEGWIDTH);
58 height = tj3Get(handle, TJPARAM_JPEGHEIGHT);
59 jpegSubsamp = tj3Get(handle, TJPARAM_SUBSAMP);
60 /* Let the transform options dictate the entropy coding algorithm. */
61 tj3Set(handle, TJPARAM_ARITHMETIC, 0);
62 tj3Set(handle, TJPARAM_PROGRESSIVE, 0);
63 tj3Set(handle, TJPARAM_OPTIMIZE, 0);
65 /* Ignore 0-pixel images and images larger than 1 Megapixel. Casting width
66 to (uint64_t) prevents integer overflow if width * height > INT_MAX. */
67 if (width < 1 || height < 1 || (uint64_t)width * height > 1048576)
70 tj3Set(handle, TJPARAM_SCANLIMIT, 500);
72 if (jpegSubsamp < 0 || jpegSubsamp >= TJ_NUMSAMP)
73 jpegSubsamp = TJSAMP_444;
75 memset(&transforms[0], 0, sizeof(tjtransform));
77 transforms[0].op = TJXOP_NONE;
78 transforms[0].options = TJXOPT_PROGRESSIVE | TJXOPT_COPYNONE;
80 (unsigned char *)malloc(tj3JPEGBufSize(width, height, jpegSubsamp));
84 maxBufSize = tj3JPEGBufSize(width, height, jpegSubsamp);
86 tj3Set(handle, TJPARAM_NOREALLOC, 1);
87 if (tj3Transform(handle, data, size, 1, dstBufs, dstSizes,
89 /* Touch all of the output pixels in order to catch uninitialized reads
90 when using MemorySanitizer. */
93 for (i = 0; i < dstSizes[0]; i++)
96 /* Prevent the code above from being optimized out. This test should
97 never be true, but the compiler doesn't know that. */
98 if (sum > 255 * maxBufSize)
105 transforms[0].r.w = (height + 1) / 2;
106 transforms[0].r.h = (width + 1) / 2;
107 transforms[0].op = TJXOP_TRANSPOSE;
108 transforms[0].options = TJXOPT_GRAY | TJXOPT_CROP | TJXOPT_COPYNONE |
111 (unsigned char *)malloc(tj3JPEGBufSize((height + 1) / 2, (width + 1) / 2,
116 maxBufSize = tj3JPEGBufSize((height + 1) / 2, (width + 1) / 2, jpegSubsamp);
118 if (tj3Transform(handle, data, size, 1, dstBufs, dstSizes,
122 for (i = 0; i < dstSizes[0]; i++)
123 sum += dstBufs[0][i];
125 if (sum > 255 * maxBufSize)
132 transforms[0].op = TJXOP_ROT90;
133 transforms[0].options = TJXOPT_TRIM | TJXOPT_ARITHMETIC;
135 (unsigned char *)malloc(tj3JPEGBufSize(height, width, jpegSubsamp));
139 maxBufSize = tj3JPEGBufSize(height, width, jpegSubsamp);
141 if (tj3Transform(handle, data, size, 1, dstBufs, dstSizes,
145 for (i = 0; i < dstSizes[0]; i++)
146 sum += dstBufs[0][i];
148 if (sum > 255 * maxBufSize)
155 transforms[0].op = TJXOP_NONE;
156 transforms[0].options = TJXOPT_PROGRESSIVE;
159 tj3Set(handle, TJPARAM_NOREALLOC, 0);
160 if (tj3Transform(handle, data, size, 1, dstBufs, dstSizes,
164 for (i = 0; i < dstSizes[0]; i++)
165 sum += dstBufs[0][i];
167 if (sum > 255 * maxBufSize)