Imported Upstream version 3.0.1
[platform/upstream/libjpeg-turbo.git] / fuzz / transform.cc
1 /*
2  * Copyright (C)2021-2023 D. R. Commander.  All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
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.
15  *
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.
27  */
28
29 #include <turbojpeg.h>
30 #include <stdlib.h>
31 #include <stdint.h>
32 #include <string.h>
33
34
35 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
36 {
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";
44
45   /* The libjpeg-turbo SIMD extensions produce false positives with
46      MemorySanitizer. */
47   putenv(env);
48 #endif
49
50   if ((handle = tj3Init(TJINIT_TRANSFORM)) == NULL)
51     goto bailout;
52
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);
64
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)
68     goto bailout;
69
70   tj3Set(handle, TJPARAM_SCANLIMIT, 500);
71
72   if (jpegSubsamp < 0 || jpegSubsamp >= TJ_NUMSAMP)
73     jpegSubsamp = TJSAMP_444;
74
75   memset(&transforms[0], 0, sizeof(tjtransform));
76
77   transforms[0].op = TJXOP_NONE;
78   transforms[0].options = TJXOPT_PROGRESSIVE | TJXOPT_COPYNONE;
79   dstBufs[0] =
80     (unsigned char *)malloc(tj3JPEGBufSize(width, height, jpegSubsamp));
81   if (!dstBufs[0])
82     goto bailout;
83
84   maxBufSize = tj3JPEGBufSize(width, height, jpegSubsamp);
85
86   tj3Set(handle, TJPARAM_NOREALLOC, 1);
87   if (tj3Transform(handle, data, size, 1, dstBufs, dstSizes,
88                    transforms) == 0) {
89     /* Touch all of the output pixels in order to catch uninitialized reads
90        when using MemorySanitizer. */
91     int sum = 0;
92
93     for (i = 0; i < dstSizes[0]; i++)
94       sum += dstBufs[0][i];
95
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)
99       goto bailout;
100   }
101
102   free(dstBufs[0]);
103   dstBufs[0] = NULL;
104
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 |
109                           TJXOPT_OPTIMIZE;
110   dstBufs[0] =
111     (unsigned char *)malloc(tj3JPEGBufSize((height + 1) / 2, (width + 1) / 2,
112                                            jpegSubsamp));
113   if (!dstBufs[0])
114     goto bailout;
115
116   maxBufSize = tj3JPEGBufSize((height + 1) / 2, (width + 1) / 2, jpegSubsamp);
117
118   if (tj3Transform(handle, data, size, 1, dstBufs, dstSizes,
119                    transforms) == 0) {
120     int sum = 0;
121
122     for (i = 0; i < dstSizes[0]; i++)
123       sum += dstBufs[0][i];
124
125     if (sum > 255 * maxBufSize)
126       goto bailout;
127   }
128
129   free(dstBufs[0]);
130   dstBufs[0] = NULL;
131
132   transforms[0].op = TJXOP_ROT90;
133   transforms[0].options = TJXOPT_TRIM | TJXOPT_ARITHMETIC;
134   dstBufs[0] =
135     (unsigned char *)malloc(tj3JPEGBufSize(height, width, jpegSubsamp));
136   if (!dstBufs[0])
137     goto bailout;
138
139   maxBufSize = tj3JPEGBufSize(height, width, jpegSubsamp);
140
141   if (tj3Transform(handle, data, size, 1, dstBufs, dstSizes,
142                    transforms) == 0) {
143     int sum = 0;
144
145     for (i = 0; i < dstSizes[0]; i++)
146       sum += dstBufs[0][i];
147
148     if (sum > 255 * maxBufSize)
149       goto bailout;
150   }
151
152   free(dstBufs[0]);
153   dstBufs[0] = NULL;
154
155   transforms[0].op = TJXOP_NONE;
156   transforms[0].options = TJXOPT_PROGRESSIVE;
157   dstSizes[0] = 0;
158
159   tj3Set(handle, TJPARAM_NOREALLOC, 0);
160   if (tj3Transform(handle, data, size, 1, dstBufs, dstSizes,
161                    transforms) == 0) {
162     int sum = 0;
163
164     for (i = 0; i < dstSizes[0]; i++)
165       sum += dstBufs[0][i];
166
167     if (sum > 255 * maxBufSize)
168       goto bailout;
169   }
170
171 bailout:
172   free(dstBufs[0]);
173   tj3Destroy(handle);
174   return 0;
175 }