/src/libjpeg-turbo.main/fuzz/transform.cc
Line  | Count  | Source (jump to first uncovered line)  | 
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  | 42.1k  | #define NUMXFORMS  3  | 
36  |  |  | 
37  |  |  | 
38  |  | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)  | 
39  | 5.51k  | { | 
40  | 5.51k  |   tjhandle handle = NULL;  | 
41  | 5.51k  |   unsigned char *dstBufs[NUMXFORMS] = { NULL, NULL, NULL }; | 
42  | 5.51k  |   size_t dstSizes[NUMXFORMS] = { 0, 0, 0 }, maxBufSize; | 
43  | 5.51k  |   int width = 0, height = 0, jpegSubsamp, i, t;  | 
44  | 5.51k  |   tjtransform transforms[NUMXFORMS];  | 
45  |  | #if defined(__has_feature) && __has_feature(memory_sanitizer)  | 
46  |  |   char env[18] = "JSIMD_FORCENONE=1";  | 
47  |  |  | 
48  |  |   /* The libjpeg-turbo SIMD extensions produce false positives with  | 
49  |  |      MemorySanitizer. */  | 
50  |  |   putenv(env);  | 
51  |  | #endif  | 
52  |  |  | 
53  | 5.51k  |   if ((handle = tj3Init(TJINIT_TRANSFORM)) == NULL)  | 
54  | 0  |     goto bailout;  | 
55  |  |  | 
56  | 5.51k  |   if (tj3DecompressHeader(handle, data, size) < 0)  | 
57  | 780  |     goto bailout;  | 
58  | 4.73k  |   width = tj3Get(handle, TJPARAM_JPEGWIDTH);  | 
59  | 4.73k  |   height = tj3Get(handle, TJPARAM_JPEGHEIGHT);  | 
60  | 4.73k  |   jpegSubsamp = tj3Get(handle, TJPARAM_SUBSAMP);  | 
61  |  |  | 
62  |  |   /* Ignore 0-pixel images and images larger than 1 Megapixel.  Casting width  | 
63  |  |      to (uint64_t) prevents integer overflow if width * height > INT_MAX. */  | 
64  | 4.73k  |   if (width < 1 || height < 1 || (uint64_t)width * height > 1048576)  | 
65  | 739  |     goto bailout;  | 
66  |  |  | 
67  | 3.99k  |   tj3Set(handle, TJPARAM_SCANLIMIT, 500);  | 
68  |  |  | 
69  | 3.99k  |   if (jpegSubsamp < 0 || jpegSubsamp >= TJ_NUMSAMP)  | 
70  | 184  |     jpegSubsamp = TJSAMP_444;  | 
71  |  |  | 
72  | 15.9k  |   for (t = 0; t < NUMXFORMS; t++)  | 
73  | 11.9k  |     memset(&transforms[t], 0, sizeof(tjtransform));  | 
74  |  |  | 
75  | 3.99k  |   transforms[0].op = TJXOP_NONE;  | 
76  | 3.99k  |   transforms[0].options = TJXOPT_PROGRESSIVE | TJXOPT_COPYNONE;  | 
77  | 3.99k  |   dstBufs[0] =  | 
78  | 3.99k  |     (unsigned char *)malloc(tj3JPEGBufSize(width, height, jpegSubsamp));  | 
79  | 3.99k  |   if (!dstBufs[0])  | 
80  | 0  |     goto bailout;  | 
81  |  |  | 
82  | 3.99k  |   transforms[1].r.w = (width + 1) / 2;  | 
83  | 3.99k  |   transforms[1].r.h = (height + 1) / 2;  | 
84  | 3.99k  |   transforms[1].op = TJXOP_TRANSPOSE;  | 
85  | 3.99k  |   transforms[1].options = TJXOPT_GRAY | TJXOPT_CROP | TJXOPT_COPYNONE;  | 
86  | 3.99k  |   dstBufs[1] =  | 
87  | 3.99k  |     (unsigned char *)malloc(tj3JPEGBufSize((width + 1) / 2, (height + 1) / 2,  | 
88  | 3.99k  |                                            TJSAMP_GRAY));  | 
89  | 3.99k  |   if (!dstBufs[1])  | 
90  | 0  |     goto bailout;  | 
91  |  |  | 
92  | 3.99k  |   transforms[2].op = TJXOP_ROT90;  | 
93  | 3.99k  |   transforms[2].options = TJXOPT_TRIM | TJXOPT_COPYNONE | TJXOPT_ARITHMETIC;  | 
94  | 3.99k  |   dstBufs[2] =  | 
95  | 3.99k  |     (unsigned char *)malloc(tj3JPEGBufSize(height, width, jpegSubsamp));  | 
96  | 3.99k  |   if (!dstBufs[2])  | 
97  | 0  |     goto bailout;  | 
98  |  |  | 
99  | 3.99k  |   maxBufSize = tj3JPEGBufSize(width, height, jpegSubsamp);  | 
100  |  |  | 
101  | 3.99k  |   tj3Set(handle, TJPARAM_NOREALLOC, 1);  | 
102  | 3.99k  |   if (tj3Transform(handle, data, size, NUMXFORMS, dstBufs, dstSizes,  | 
103  | 3.99k  |                    transforms) == 0) { | 
104  |  |     /* Touch all of the output pixels in order to catch uninitialized reads  | 
105  |  |        when using MemorySanitizer. */  | 
106  | 156  |     for (t = 0; t < NUMXFORMS; t++) { | 
107  | 117  |       int sum = 0;  | 
108  |  |  | 
109  | 859k  |       for (i = 0; i < dstSizes[t]; i++)  | 
110  | 859k  |         sum += dstBufs[t][i];  | 
111  |  |  | 
112  |  |       /* Prevent the code above from being optimized out.  This test should  | 
113  |  |          never be true, but the compiler doesn't know that. */  | 
114  | 117  |       if (sum > 255 * maxBufSize)  | 
115  | 0  |         goto bailout;  | 
116  | 117  |     }  | 
117  | 39  |   }  | 
118  |  |  | 
119  | 3.99k  |   transforms[0].options &= ~TJXOPT_COPYNONE;  | 
120  | 3.99k  |   transforms[0].options |= TJXOPT_OPTIMIZE;  | 
121  | 3.99k  |   free(dstBufs[0]);  | 
122  | 3.99k  |   dstBufs[0] = NULL;  | 
123  | 3.99k  |   dstSizes[0] = 0;  | 
124  |  |  | 
125  | 3.99k  |   tj3Set(handle, TJPARAM_NOREALLOC, 0);  | 
126  | 3.99k  |   if (tj3Transform(handle, data, size, 1, dstBufs, dstSizes,  | 
127  | 3.99k  |                    transforms) == 0) { | 
128  | 39  |     int sum = 0;  | 
129  |  |  | 
130  | 170k  |     for (i = 0; i < dstSizes[0]; i++)  | 
131  | 170k  |       sum += dstBufs[0][i];  | 
132  |  |  | 
133  | 39  |     if (sum > 255 * maxBufSize)  | 
134  | 0  |       goto bailout;  | 
135  | 39  |   }  | 
136  |  |  | 
137  | 5.51k  | bailout:  | 
138  | 22.0k  |   for (t = 0; t < NUMXFORMS; t++)  | 
139  | 16.5k  |     free(dstBufs[t]);  | 
140  | 5.51k  |   tj3Destroy(handle);  | 
141  | 5.51k  |   return 0;  | 
142  | 3.99k  | }  |