1 // Copyright 2014 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <limits.h>
6 #include <stdint.h>
7
8 #include <limits>
9 #include <type_traits>
10
11 #include "core/fxcodec/jpx/cjpx_decoder.h"
12 #include "core/fxcodec/jpx/jpx_decode_utils.h"
13 #include "core/fxcrt/fx_memcpy_wrappers.h"
14 #include "core/fxcrt/fx_memory.h"
15 #include "core/fxcrt/stl_util.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "third_party/libopenjpeg/opj_malloc.h"
18
19 namespace fxcodec {
20
21 static const OPJ_OFF_T kSkipError = static_cast<OPJ_OFF_T>(-1);
22 static const OPJ_SIZE_T kReadError = static_cast<OPJ_SIZE_T>(-1);
23
24 static const uint8_t kStreamData[] = {
25 0x00, 0x01, 0x02, 0x03,
26 0x84, 0x85, 0x86, 0x87, // Include some hi-bytes, too.
27 };
28
TEST(fxcodec,DecodeDataNullDecodeData)29 TEST(fxcodec, DecodeDataNullDecodeData) {
30 uint8_t buffer[16];
31 DecodeData* ptr = nullptr;
32
33 // Error codes, not segvs, should callers pass us a nullptr pointer.
34 EXPECT_EQ(kReadError, opj_read_from_memory(buffer, sizeof(buffer), ptr));
35 EXPECT_EQ(kSkipError, opj_skip_from_memory(1, ptr));
36 EXPECT_FALSE(opj_seek_from_memory(1, ptr));
37 }
38
TEST(fxcodec,DecodeDataNullStream)39 TEST(fxcodec, DecodeDataNullStream) {
40 DecodeData dd;
41 uint8_t buffer[16];
42
43 // Reads of size 0 do nothing but return an error code.
44 fxcrt::Fill(buffer, 0xbd);
45 EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 0, &dd));
46 EXPECT_EQ(0xbd, buffer[0]);
47
48 // Reads of nonzero size do nothing but return an error code.
49 fxcrt::Fill(buffer, 0xbd);
50 EXPECT_EQ(kReadError, opj_read_from_memory(buffer, sizeof(buffer), &dd));
51 EXPECT_EQ(0xbd, buffer[0]);
52
53 // Skips of size 0 always return an error code.
54 EXPECT_EQ(kSkipError, opj_skip_from_memory(0, &dd));
55
56 // Skips of nonzero size always return an error code.
57 EXPECT_EQ(kSkipError, opj_skip_from_memory(1, &dd));
58
59 // Seeks to 0 offset return in error.
60 EXPECT_FALSE(opj_seek_from_memory(0, &dd));
61
62 // Seeks to non-zero offsets return in error.
63 EXPECT_FALSE(opj_seek_from_memory(1, &dd));
64 }
65
TEST(fxcodec,DecodeDataZeroSize)66 TEST(fxcodec, DecodeDataZeroSize) {
67 DecodeData dd(pdfium::make_span(kStreamData).first(0u));
68 uint8_t buffer[16];
69
70 // Reads of size 0 do nothing but return an error code.
71 fxcrt::Fill(buffer, 0xbd);
72 EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 0, &dd));
73 EXPECT_EQ(0xbd, buffer[0]);
74
75 // Reads of nonzero size do nothing but return an error code.
76 fxcrt::Fill(buffer, 0xbd);
77 EXPECT_EQ(kReadError, opj_read_from_memory(buffer, sizeof(buffer), &dd));
78 EXPECT_EQ(0xbd, buffer[0]);
79
80 // Skips of size 0 always return an error code.
81 EXPECT_EQ(kSkipError, opj_skip_from_memory(0, &dd));
82
83 // Skips of nonzero size always return an error code.
84 EXPECT_EQ(kSkipError, opj_skip_from_memory(1, &dd));
85
86 // Seeks to 0 offset return in error.
87 EXPECT_FALSE(opj_seek_from_memory(0, &dd));
88
89 // Seeks to non-zero offsets return in error.
90 EXPECT_FALSE(opj_seek_from_memory(1, &dd));
91 }
92
TEST(fxcodec,DecodeDataReadInBounds)93 TEST(fxcodec, DecodeDataReadInBounds) {
94 uint8_t buffer[16];
95 {
96 DecodeData dd(kStreamData);
97
98 // Exact sized read in a single call.
99 fxcrt::Fill(buffer, 0xbd);
100 EXPECT_EQ(8u, opj_read_from_memory(buffer, sizeof(buffer), &dd));
101 EXPECT_EQ(0x00, buffer[0]);
102 EXPECT_EQ(0x01, buffer[1]);
103 EXPECT_EQ(0x02, buffer[2]);
104 EXPECT_EQ(0x03, buffer[3]);
105 EXPECT_EQ(0x84, buffer[4]);
106 EXPECT_EQ(0x85, buffer[5]);
107 EXPECT_EQ(0x86, buffer[6]);
108 EXPECT_EQ(0x87, buffer[7]);
109 EXPECT_EQ(0xbd, buffer[8]);
110 }
111 {
112 DecodeData dd(kStreamData);
113
114 // Simple read.
115 fxcrt::Fill(buffer, 0xbd);
116 EXPECT_EQ(2u, opj_read_from_memory(buffer, 2, &dd));
117 EXPECT_EQ(0x00, buffer[0]);
118 EXPECT_EQ(0x01, buffer[1]);
119 EXPECT_EQ(0xbd, buffer[2]);
120
121 // Read of size 0 doesn't affect things.
122 fxcrt::Fill(buffer, 0xbd);
123 EXPECT_EQ(0u, opj_read_from_memory(buffer, 0, &dd));
124 EXPECT_EQ(0xbd, buffer[0]);
125
126 // Read exactly up to end of data.
127 fxcrt::Fill(buffer, 0xbd);
128 EXPECT_EQ(6u, opj_read_from_memory(buffer, 6, &dd));
129 EXPECT_EQ(0x02, buffer[0]);
130 EXPECT_EQ(0x03, buffer[1]);
131 EXPECT_EQ(0x84, buffer[2]);
132 EXPECT_EQ(0x85, buffer[3]);
133 EXPECT_EQ(0x86, buffer[4]);
134 EXPECT_EQ(0x87, buffer[5]);
135 EXPECT_EQ(0xbd, buffer[6]);
136
137 // Read of size 0 at EOF is still an error.
138 fxcrt::Fill(buffer, 0xbd);
139 EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 0, &dd));
140 EXPECT_EQ(0xbd, buffer[0]);
141 }
142 }
143
TEST(fxcodec,DecodeDataReadBeyondBounds)144 TEST(fxcodec, DecodeDataReadBeyondBounds) {
145 uint8_t buffer[16];
146 {
147 DecodeData dd(kStreamData);
148
149 // Read beyond bounds in a single step.
150 fxcrt::Fill(buffer, 0xbd);
151 EXPECT_EQ(8u, opj_read_from_memory(buffer, sizeof(buffer) + 1, &dd));
152 EXPECT_EQ(0x00, buffer[0]);
153 EXPECT_EQ(0x01, buffer[1]);
154 EXPECT_EQ(0x02, buffer[2]);
155 EXPECT_EQ(0x03, buffer[3]);
156 EXPECT_EQ(0x84, buffer[4]);
157 EXPECT_EQ(0x85, buffer[5]);
158 EXPECT_EQ(0x86, buffer[6]);
159 EXPECT_EQ(0x87, buffer[7]);
160 EXPECT_EQ(0xbd, buffer[8]);
161 }
162 {
163 DecodeData dd(kStreamData);
164
165 // Read well beyond bounds in a single step.
166 fxcrt::Fill(buffer, 0xbd);
167 EXPECT_EQ(8u, opj_read_from_memory(
168 buffer, std::numeric_limits<OPJ_SIZE_T>::max(), &dd));
169 EXPECT_EQ(0x00, buffer[0]);
170 EXPECT_EQ(0x01, buffer[1]);
171 EXPECT_EQ(0x02, buffer[2]);
172 EXPECT_EQ(0x03, buffer[3]);
173 EXPECT_EQ(0x84, buffer[4]);
174 EXPECT_EQ(0x85, buffer[5]);
175 EXPECT_EQ(0x86, buffer[6]);
176 EXPECT_EQ(0x87, buffer[7]);
177 EXPECT_EQ(0xbd, buffer[8]);
178 }
179 {
180 DecodeData dd(kStreamData);
181
182 // Read of size 6 gets first 6 bytes.
183 // rest of buffer intact.
184 fxcrt::Fill(buffer, 0xbd);
185 EXPECT_EQ(6u, opj_read_from_memory(buffer, 6, &dd));
186 EXPECT_EQ(0x00, buffer[0]);
187 EXPECT_EQ(0x01, buffer[1]);
188 EXPECT_EQ(0x02, buffer[2]);
189 EXPECT_EQ(0x03, buffer[3]);
190 EXPECT_EQ(0x84, buffer[4]);
191 EXPECT_EQ(0x85, buffer[5]);
192 EXPECT_EQ(0xbd, buffer[6]);
193
194 // Read of size 6 gets remaining two bytes.
195 fxcrt::Fill(buffer, 0xbd);
196 EXPECT_EQ(2u, opj_read_from_memory(buffer, 6, &dd));
197 EXPECT_EQ(0x86, buffer[0]);
198 EXPECT_EQ(0x87, buffer[1]);
199 EXPECT_EQ(0xbd, buffer[2]);
200
201 // Read of 6 more gets nothing and leaves rest of buffer intact.
202 fxcrt::Fill(buffer, 0xbd);
203 EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 6, &dd));
204 EXPECT_EQ(0xbd, buffer[0]);
205 }
206 }
207
208 // Note: Some care needs to be taken here because the skip/seek functions
209 // take OPJ_OFF_T's as arguments, which are typically a signed type.
TEST(fxcodec,DecodeDataSkip)210 TEST(fxcodec, DecodeDataSkip) {
211 uint8_t buffer[16];
212 {
213 DecodeData dd(kStreamData);
214
215 // Skiping within buffer is allowed.
216 fxcrt::Fill(buffer, 0xbd);
217 EXPECT_EQ(1u, opj_skip_from_memory(1, &dd));
218 EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
219 EXPECT_EQ(0x01, buffer[0]);
220 EXPECT_EQ(0xbd, buffer[1]);
221
222 // Skiping 0 bytes changes nothing.
223 fxcrt::Fill(buffer, 0xbd);
224 EXPECT_EQ(0, opj_skip_from_memory(0, &dd));
225 EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
226 EXPECT_EQ(0x02, buffer[0]);
227 EXPECT_EQ(0xbd, buffer[1]);
228
229 // Skiping to EOS-1 is possible.
230 fxcrt::Fill(buffer, 0xbd);
231 EXPECT_EQ(4u, opj_skip_from_memory(4, &dd));
232 EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
233 EXPECT_EQ(0x87, buffer[0]);
234 EXPECT_EQ(0xbd, buffer[1]);
235
236 // Next read fails.
237 fxcrt::Fill(buffer, 0xbd);
238 EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 1, &dd));
239 EXPECT_EQ(0xbd, buffer[0]);
240 }
241 {
242 DecodeData dd(kStreamData);
243
244 // Skiping directly to EOS is allowed.
245 fxcrt::Fill(buffer, 0xbd);
246 EXPECT_EQ(8u, opj_skip_from_memory(8, &dd));
247
248 // Next read fails.
249 EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 1, &dd));
250 EXPECT_EQ(0xbd, buffer[0]);
251 }
252 {
253 DecodeData dd(kStreamData);
254
255 // Skipping beyond end of stream is allowed and returns full distance.
256 fxcrt::Fill(buffer, 0xbd);
257 EXPECT_EQ(9u, opj_skip_from_memory(9, &dd));
258
259 // Next read fails.
260 EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 1, &dd));
261 EXPECT_EQ(0xbd, buffer[0]);
262 }
263 {
264 DecodeData dd(kStreamData);
265
266 // Skipping way beyond EOS is allowd, doesn't wrap, and returns
267 // full distance.
268 fxcrt::Fill(buffer, 0xbd);
269 EXPECT_EQ(4u, opj_skip_from_memory(4, &dd));
270 EXPECT_EQ(std::numeric_limits<OPJ_OFF_T>::max(),
271 opj_skip_from_memory(std::numeric_limits<OPJ_OFF_T>::max(), &dd));
272
273 // Next read fails. If it succeeds, it may mean we wrapped.
274 EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 1, &dd));
275 EXPECT_EQ(0xbd, buffer[0]);
276 }
277 {
278 DecodeData dd(kStreamData);
279
280 // Negative skip within buffer not is allowed, position unchanged.
281 fxcrt::Fill(buffer, 0xbd);
282 EXPECT_EQ(4u, opj_skip_from_memory(4, &dd));
283 EXPECT_EQ(kSkipError, opj_skip_from_memory(-2, &dd));
284
285 // Next read succeeds as if nothing has happenned.
286 EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
287 EXPECT_EQ(0x84, buffer[0]);
288 EXPECT_EQ(0xbd, buffer[1]);
289
290 // Negative skip before buffer is not allowed, position unchanged.
291 fxcrt::Fill(buffer, 0xbd);
292 EXPECT_EQ(kSkipError, opj_skip_from_memory(-4, &dd));
293
294 // Next read succeeds as if nothing has happenned.
295 EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
296 EXPECT_EQ(0x85, buffer[0]);
297 EXPECT_EQ(0xbd, buffer[1]);
298 }
299 {
300 DecodeData dd(kStreamData);
301
302 // Negative skip way before buffer is not allowed, doesn't wrap
303 fxcrt::Fill(buffer, 0xbd);
304 EXPECT_EQ(4u, opj_skip_from_memory(4, &dd));
305 EXPECT_EQ(kSkipError,
306 opj_skip_from_memory(std::numeric_limits<OPJ_OFF_T>::min(), &dd));
307
308 // Next read succeeds. If it fails, it may mean we wrapped.
309 EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
310 EXPECT_EQ(0x84, buffer[0]);
311 EXPECT_EQ(0xbd, buffer[1]);
312 }
313 {
314 DecodeData dd(kStreamData);
315
316 // Negative skip after EOS isn't alowed, still EOS.
317 fxcrt::Fill(buffer, 0xbd);
318 EXPECT_EQ(8u, opj_skip_from_memory(8, &dd));
319 EXPECT_EQ(kSkipError, opj_skip_from_memory(-4, &dd));
320
321 // Next read fails.
322 EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 1, &dd));
323 EXPECT_EQ(0xbd, buffer[0]);
324 }
325 }
326
TEST(fxcodec,DecodeDataSeek)327 TEST(fxcodec, DecodeDataSeek) {
328 uint8_t buffer[16];
329 DecodeData dd(kStreamData);
330
331 // Seeking within buffer is allowed and read succeeds
332 fxcrt::Fill(buffer, 0xbd);
333 EXPECT_TRUE(opj_seek_from_memory(1, &dd));
334 EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
335 EXPECT_EQ(0x01, buffer[0]);
336 EXPECT_EQ(0xbd, buffer[1]);
337
338 // Seeking before start returns error leaving position unchanged.
339 fxcrt::Fill(buffer, 0xbd);
340 EXPECT_FALSE(opj_seek_from_memory(-1, &dd));
341 EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
342 EXPECT_EQ(0x02, buffer[0]);
343 EXPECT_EQ(0xbd, buffer[1]);
344
345 // Seeking way before start returns error leaving position unchanged.
346 fxcrt::Fill(buffer, 0xbd);
347 EXPECT_FALSE(
348 opj_seek_from_memory(std::numeric_limits<OPJ_OFF_T>::min(), &dd));
349 EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
350 EXPECT_EQ(0x03, buffer[0]);
351 EXPECT_EQ(0xbd, buffer[1]);
352
353 // Seeking exactly to EOS is allowed but read fails.
354 fxcrt::Fill(buffer, 0xbd);
355 EXPECT_TRUE(opj_seek_from_memory(8, &dd));
356 EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 1, &dd));
357 EXPECT_EQ(0xbd, buffer[0]);
358
359 // Seeking back to zero offset is allowed and read succeeds.
360 fxcrt::Fill(buffer, 0xbd);
361 EXPECT_TRUE(opj_seek_from_memory(0, &dd));
362 EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
363 EXPECT_EQ(0x00, buffer[0]);
364 EXPECT_EQ(0xbd, buffer[1]);
365
366 // Seeking beyond end of stream is allowed but read fails.
367 fxcrt::Fill(buffer, 0xbd);
368 EXPECT_TRUE(opj_seek_from_memory(16, &dd));
369 EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 1, &dd));
370 EXPECT_EQ(0xbd, buffer[0]);
371
372 // Seeking within buffer after seek past EOF restores good state.
373 fxcrt::Fill(buffer, 0xbd);
374 EXPECT_TRUE(opj_seek_from_memory(4, &dd));
375 EXPECT_EQ(1u, opj_read_from_memory(buffer, 1, &dd));
376 EXPECT_EQ(0x84, buffer[0]);
377 EXPECT_EQ(0xbd, buffer[1]);
378
379 // Seeking way beyond EOS is allowed, doesn't wrap, and read fails.
380 fxcrt::Fill(buffer, 0xbd);
381 EXPECT_TRUE(opj_seek_from_memory(std::numeric_limits<OPJ_OFF_T>::max(), &dd));
382 EXPECT_EQ(kReadError, opj_read_from_memory(buffer, 1, &dd));
383 EXPECT_EQ(0xbd, buffer[0]);
384 }
385
TEST(fxcodec,YUV420ToRGB)386 TEST(fxcodec, YUV420ToRGB) {
387 opj_image_comp_t u = {}; // Aggregate initialization.
388 static_assert(std::is_aggregate_v<decltype(u)>);
389 u.dx = 1;
390 u.dy = 1;
391 u.w = 16;
392 u.h = 16;
393 u.prec = 8;
394 u.bpp = 8;
395 opj_image_comp_t v = {}; // Aggregate initialization.
396 static_assert(std::is_aggregate_v<decltype(v)>);
397 v.dx = 1;
398 v.dy = 1;
399 v.w = 16;
400 v.h = 16;
401 v.prec = 8;
402 v.bpp = 8;
403 opj_image_comp_t y = {}; // Aggregate initialization.
404 static_assert(std::is_aggregate_v<decltype(y)>);
405 y.dx = 1;
406 y.dy = 1;
407 y.prec = 8;
408 y.bpp = 8;
409 opj_image_t img = {}; // Aggregate initialization.
410 static_assert(std::is_aggregate_v<decltype(img)>);
411 img.numcomps = 3;
412 img.color_space = OPJ_CLRSPC_SYCC;
413 img.comps = FX_Alloc(opj_image_comp_t, 3);
414 const struct {
415 OPJ_UINT32 w;
416 bool expected;
417 } cases[] = {{0, false}, {1, false}, {30, false}, {31, true},
418 {32, true}, {33, false}, {34, false}, {UINT_MAX, false}};
419 for (const auto& testcase : cases) {
420 y.w = testcase.w;
421 y.h = y.w;
422 img.x1 = y.w;
423 img.y1 = y.h;
424 y.data = static_cast<OPJ_INT32*>(
425 opj_image_data_alloc(y.w * y.h * sizeof(OPJ_INT32)));
426 v.data = static_cast<OPJ_INT32*>(
427 opj_image_data_alloc(v.w * v.h * sizeof(OPJ_INT32)));
428 u.data = static_cast<OPJ_INT32*>(
429 opj_image_data_alloc(u.w * u.h * sizeof(OPJ_INT32)));
430
431 UNSAFE_TODO({
432 FXSYS_memset(y.data, 1, y.w * y.h * sizeof(OPJ_INT32));
433 FXSYS_memset(u.data, 0, u.w * u.h * sizeof(OPJ_INT32));
434 FXSYS_memset(v.data, 0, v.w * v.h * sizeof(OPJ_INT32));
435 img.comps[0] = y;
436 img.comps[1] = u;
437 img.comps[2] = v;
438 CJPX_Decoder::Sycc420ToRgbForTesting(&img);
439 if (testcase.expected) {
440 EXPECT_EQ(img.comps[0].w, img.comps[1].w);
441 EXPECT_EQ(img.comps[0].h, img.comps[1].h);
442 EXPECT_EQ(img.comps[0].w, img.comps[2].w);
443 EXPECT_EQ(img.comps[0].h, img.comps[2].h);
444 } else {
445 EXPECT_NE(img.comps[0].w, img.comps[1].w);
446 EXPECT_NE(img.comps[0].h, img.comps[1].h);
447 EXPECT_NE(img.comps[0].w, img.comps[2].w);
448 EXPECT_NE(img.comps[0].h, img.comps[2].h);
449 }
450 opj_image_data_free(img.comps[0].data);
451 opj_image_data_free(img.comps[1].data);
452 opj_image_data_free(img.comps[2].data);
453 });
454 }
455 FX_Free(img.comps);
456 }
457
458 } // namespace fxcodec
459