/src/openjpeg/tests/fuzzers/opj_decompress_fuzzer_JP2.cpp
Line | Count | Source |
1 | | /* |
2 | | * The copyright in this software is being made available under the 2-clauses |
3 | | * BSD License, included below. This software may be subject to other third |
4 | | * party and contributor rights, including patent rights, and no such rights |
5 | | * are granted under this license. |
6 | | * |
7 | | * Copyright (c) 2017, IntoPix SA <contact@intopix.com> |
8 | | * All rights reserved. |
9 | | * |
10 | | * Redistribution and use in source and binary forms, with or without |
11 | | * modification, are permitted provided that the following conditions |
12 | | * are met: |
13 | | * 1. Redistributions of source code must retain the above copyright |
14 | | * notice, this list of conditions and the following disclaimer. |
15 | | * 2. Redistributions in binary form must reproduce the above copyright |
16 | | * notice, this list of conditions and the following disclaimer in the |
17 | | * documentation and/or other materials provided with the distribution. |
18 | | * |
19 | | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS' |
20 | | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
21 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
22 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
23 | | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | | * POSSIBILITY OF SUCH DAMAGE. |
30 | | */ |
31 | | |
32 | | #include <stddef.h> |
33 | | #include <stdint.h> |
34 | | #include <string.h> |
35 | | #include <limits.h> |
36 | | |
37 | | #include "openjpeg.h" |
38 | | |
39 | | extern "C" int LLVMFuzzerInitialize(int* argc, char*** argv); |
40 | | extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len); |
41 | | |
42 | | typedef struct { |
43 | | const uint8_t* pabyData; |
44 | | size_t nCurPos; |
45 | | size_t nLength; |
46 | | } MemFile; |
47 | | |
48 | | |
49 | | static void ErrorCallback(const char * msg, void *) |
50 | 20.2k | { |
51 | 20.2k | (void)msg; |
52 | | //fprintf(stderr, "%s\n", msg); |
53 | 20.2k | } |
54 | | |
55 | | |
56 | | static void WarningCallback(const char *, void *) |
57 | 29.4M | { |
58 | 29.4M | } |
59 | | |
60 | | static void InfoCallback(const char *, void *) |
61 | 71.7k | { |
62 | 71.7k | } |
63 | | |
64 | | static OPJ_SIZE_T ReadCallback(void* pBuffer, OPJ_SIZE_T nBytes, |
65 | | void *pUserData) |
66 | 26.4k | { |
67 | 26.4k | MemFile* memFile = (MemFile*)pUserData; |
68 | | //printf("want to read %d bytes at %d\n", (int)memFile->nCurPos, (int)nBytes); |
69 | 26.4k | if (memFile->nCurPos >= memFile->nLength) { |
70 | 8.58k | return -1; |
71 | 8.58k | } |
72 | 17.8k | if (memFile->nCurPos + nBytes >= memFile->nLength) { |
73 | 11.3k | size_t nToRead = memFile->nLength - memFile->nCurPos; |
74 | 11.3k | memcpy(pBuffer, memFile->pabyData + memFile->nCurPos, nToRead); |
75 | 11.3k | memFile->nCurPos = memFile->nLength; |
76 | 11.3k | return nToRead; |
77 | 11.3k | } |
78 | 6.55k | if (nBytes == 0) { |
79 | 0 | return -1; |
80 | 0 | } |
81 | 6.55k | memcpy(pBuffer, memFile->pabyData + memFile->nCurPos, nBytes); |
82 | 6.55k | memFile->nCurPos += nBytes; |
83 | 6.55k | return nBytes; |
84 | 6.55k | } |
85 | | |
86 | | static OPJ_BOOL SeekCallback(OPJ_OFF_T nBytes, void * pUserData) |
87 | 822 | { |
88 | 822 | MemFile* memFile = (MemFile*)pUserData; |
89 | | //printf("seek to %d\n", (int)nBytes); |
90 | 822 | memFile->nCurPos = nBytes; |
91 | 822 | return OPJ_TRUE; |
92 | 822 | } |
93 | | |
94 | | static OPJ_OFF_T SkipCallback(OPJ_OFF_T nBytes, void * pUserData) |
95 | 78 | { |
96 | 78 | MemFile* memFile = (MemFile*)pUserData; |
97 | 78 | memFile->nCurPos += nBytes; |
98 | 78 | return nBytes; |
99 | 78 | } |
100 | | |
101 | | |
102 | | int LLVMFuzzerInitialize(int* /*argc*/, char*** argv) |
103 | 3 | { |
104 | 3 | return 0; |
105 | 3 | } |
106 | | |
107 | | static const unsigned char jpc_header[] = {0xff, 0x4f}; |
108 | | static const unsigned char jp2_box_jp[] = {0x6a, 0x50, 0x20, 0x20}; /* 'jP ' */ |
109 | | |
110 | | int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t len) |
111 | 11.3k | { |
112 | | |
113 | 11.3k | OPJ_CODEC_FORMAT eCodecFormat; |
114 | 11.3k | if (len >= 4 + sizeof(jp2_box_jp) && |
115 | 11.3k | memcmp(buf + 4, jp2_box_jp, sizeof(jp2_box_jp)) == 0) { |
116 | 11.3k | eCodecFormat = OPJ_CODEC_JP2; |
117 | 11.3k | } else { |
118 | 42 | return 0; |
119 | 42 | } |
120 | | |
121 | 11.3k | opj_codec_t* pCodec = opj_create_decompress(eCodecFormat); |
122 | 11.3k | opj_set_info_handler(pCodec, InfoCallback, NULL); |
123 | 11.3k | opj_set_warning_handler(pCodec, WarningCallback, NULL); |
124 | 11.3k | opj_set_error_handler(pCodec, ErrorCallback, NULL); |
125 | | |
126 | 11.3k | opj_dparameters_t parameters; |
127 | 11.3k | opj_set_default_decoder_parameters(¶meters); |
128 | | |
129 | 11.3k | opj_setup_decoder(pCodec, ¶meters); |
130 | | |
131 | 11.3k | opj_stream_t *pStream = opj_stream_create(1024, OPJ_TRUE); |
132 | 11.3k | MemFile memFile; |
133 | 11.3k | memFile.pabyData = buf; |
134 | 11.3k | memFile.nLength = len; |
135 | 11.3k | memFile.nCurPos = 0; |
136 | 11.3k | opj_stream_set_user_data_length(pStream, len); |
137 | 11.3k | opj_stream_set_read_function(pStream, ReadCallback); |
138 | 11.3k | opj_stream_set_seek_function(pStream, SeekCallback); |
139 | 11.3k | opj_stream_set_skip_function(pStream, SkipCallback); |
140 | 11.3k | opj_stream_set_user_data(pStream, &memFile, NULL); |
141 | | |
142 | 11.3k | opj_image_t * psImage = NULL; |
143 | 11.3k | if (!opj_read_header(pStream, pCodec, &psImage)) { |
144 | 3.06k | opj_destroy_codec(pCodec); |
145 | 3.06k | opj_stream_destroy(pStream); |
146 | 3.06k | opj_image_destroy(psImage); |
147 | 3.06k | return 0; |
148 | 3.06k | } |
149 | | |
150 | 8.26k | OPJ_UINT32 width = psImage->x1 - psImage->x0; |
151 | 8.26k | OPJ_UINT32 height = psImage->y1 - psImage->y0; |
152 | | |
153 | | #if 0 |
154 | | // Reject too big images since that will require allocating a lot of |
155 | | // memory |
156 | | if (width != 0 && psImage->numcomps != 0 && |
157 | | (width > INT_MAX / psImage->numcomps || |
158 | | height > INT_MAX / (width * psImage->numcomps * sizeof(OPJ_UINT32)))) { |
159 | | opj_stream_destroy(pStream); |
160 | | opj_destroy_codec(pCodec); |
161 | | opj_image_destroy(psImage); |
162 | | |
163 | | return 0; |
164 | | } |
165 | | |
166 | | // Also reject too big tiles. |
167 | | // TODO: remove this limitation when subtile decoding no longer imply |
168 | | // allocation memory for whole tile |
169 | | opj_codestream_info_v2_t* pCodeStreamInfo = opj_get_cstr_info(pCodec); |
170 | | OPJ_UINT32 nTileW, nTileH; |
171 | | nTileW = pCodeStreamInfo->tdx; |
172 | | nTileH = pCodeStreamInfo->tdy; |
173 | | opj_destroy_cstr_info(&pCodeStreamInfo); |
174 | | if (nTileW > 2048 || nTileH > 2048) { |
175 | | opj_stream_destroy(pStream); |
176 | | opj_destroy_codec(pCodec); |
177 | | opj_image_destroy(psImage); |
178 | | |
179 | | return 0; |
180 | | } |
181 | | #endif |
182 | | |
183 | 8.26k | OPJ_UINT32 width_to_read = width; |
184 | 8.26k | if (width_to_read > 1024) { |
185 | 8.25k | width_to_read = 1024; |
186 | 8.25k | } |
187 | 8.26k | OPJ_UINT32 height_to_read = height; |
188 | 8.26k | if (height_to_read > 1024) { |
189 | 7.92k | height_to_read = 1024; |
190 | 7.92k | } |
191 | | |
192 | 8.26k | if (opj_set_decode_area(pCodec, psImage, |
193 | 8.26k | psImage->x0, psImage->y0, |
194 | 8.26k | psImage->x0 + width_to_read, |
195 | 8.26k | psImage->y0 + height_to_read)) { |
196 | 8.25k | if (opj_decode(pCodec, pStream, psImage)) { |
197 | | //printf("success\n"); |
198 | 5.22k | } |
199 | 8.25k | } |
200 | | |
201 | 8.26k | opj_end_decompress(pCodec, pStream); |
202 | 8.26k | opj_stream_destroy(pStream); |
203 | 8.26k | opj_destroy_codec(pCodec); |
204 | 8.26k | opj_image_destroy(psImage); |
205 | | |
206 | 8.26k | return 0; |
207 | 11.3k | } |