FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/jpegxl_parse.c
Date: 2024-07-17 14:05:47
Exec Total Coverage
Lines: 163 287 56.8%
Functions: 9 11 81.8%
Branches: 101 246 41.1%

Line Branch Exec Source
1 /*
2 * JPEG XL Header Parser
3 * Copyright (c) 2023 Leo Izen <leo.izen@gmail.com>
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include <stdint.h>
23
24 #include "bytestream.h"
25 #define UNCHECKED_BITSTREAM_READER 0
26 #define BITSTREAM_READER_LE
27 #include "get_bits.h"
28 #include "jpegxl.h"
29 #include "jpegxl_parse.h"
30
31 /* read a U32(c_i + u(u_i)) */
32 72 static av_always_inline uint32_t jxl_u32(GetBitContext *gb,
33 uint32_t c0, uint32_t c1, uint32_t c2, uint32_t c3,
34 uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3)
35 {
36 72 const uint32_t constants[4] = {c0, c1, c2, c3};
37 72 const uint32_t ubits [4] = {u0, u1, u2, u3};
38 72 uint32_t ret, choice = get_bits(gb, 2);
39
40 72 ret = constants[choice];
41
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 38 times.
72 if (ubits[choice])
42 34 ret += get_bits_long(gb, ubits[choice]);
43
44 72 return ret;
45 }
46
47 static av_always_inline uint32_t jxl_enum(GetBitContext *gb)
48 {
49 return jxl_u32(gb, 0, 1, 2, 18, 0, 0, 4, 6);
50 }
51
52 /* read a U64() */
53 10 static uint64_t jxl_u64(GetBitContext *gb)
54 {
55 10 uint64_t shift = 12, ret;
56
57
1/4
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 10 times.
10 switch (get_bits(gb, 2)) {
58 case 1:
59 ret = 1 + get_bits(gb, 4);
60 break;
61 case 2:
62 ret = 17 + get_bits(gb, 8);
63 break;
64 case 3:
65 ret = get_bits(gb, 12);
66 while (get_bits1(gb)) {
67 if (shift < 60) {
68 ret |= (uint64_t)get_bits(gb, 8) << shift;
69 shift += 8;
70 } else {
71 ret |= (uint64_t)get_bits(gb, 4) << shift;
72 break;
73 }
74 }
75 break;
76 10 default:
77 10 ret = 0;
78 }
79
80 10 return ret;
81 }
82
83 31 static uint32_t jpegxl_width_from_ratio(uint32_t height, int ratio)
84 {
85 31 uint64_t height64 = height; /* avoid integer overflow */
86
4/8
✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 14 times.
31 switch (ratio) {
87 11 case 1:
88 11 return height;
89 case 2:
90 return (uint32_t)((height64 * 12) / 10);
91 3 case 3:
92 3 return (uint32_t)((height64 * 4) / 3);
93 3 case 4:
94 3 return (uint32_t)((height64 * 3) / 2);
95 case 5:
96 return (uint32_t)((height64 * 16) / 9);
97 case 6:
98 return (uint32_t)((height64 * 5) / 4);
99 case 7:
100 return (uint32_t)(height64 * 2);
101 14 default:
102 14 break;
103 }
104
105 14 return 0; /* manual width */
106 }
107
108 /**
109 * validate a Jpeg XL Size Header
110 * @return >= 0 upon valid size, < 0 upon invalid size found
111 */
112 31 static int jpegxl_read_size_header(GetBitContext *gb, FFJXLMetadata *meta, int validate)
113 {
114 uint32_t width, height;
115
116
2/2
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 17 times.
31 if (get_bits1(gb)) {
117 /* small size header */
118 14 height = (get_bits(gb, 5) + 1) << 3;
119 14 width = jpegxl_width_from_ratio(height, get_bits(gb, 3));
120
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
14 if (!width)
121 width = (get_bits(gb, 5) + 1) << 3;
122 } else {
123 /* large size header */
124 17 height = 1 + jxl_u32(gb, 0, 0, 0, 0, 9, 13, 18, 30);
125 17 width = jpegxl_width_from_ratio(height, get_bits(gb, 3));
126
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 3 times.
17 if (!width)
127 14 width = 1 + jxl_u32(gb, 0, 0, 0, 0, 9, 13, 18, 30);
128 }
129
4/6
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
31 if (validate && (width > (1 << 18) || height > (1 << 18)
130
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 || (width >> 4) * (height >> 4) > (1 << 20)))
131 return AVERROR_INVALIDDATA;
132
133
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 3 times.
31 if (meta) {
134 28 meta->width = meta->coded_width = width;
135 28 meta->height = meta->coded_height = height;
136 }
137
138 31 return 0;
139 }
140
141 /**
142 * validate a Jpeg XL Preview Header
143 * @return >= 0 upon valid size, < 0 upon invalid size found
144 */
145 static int jpegxl_read_preview_header(GetBitContext *gb, int validate)
146 {
147 uint32_t width, height;
148
149 if (get_bits1(gb)) {
150 /* coded height and width divided by eight */
151 height = jxl_u32(gb, 16, 32, 1, 33, 0, 0, 5, 9) << 3;
152 width = jpegxl_width_from_ratio(height, get_bits(gb, 3));
153 if (!width)
154 width = jxl_u32(gb, 16, 32, 1, 33, 0, 0, 5, 9) << 3;
155 } else {
156 /* full height and width coded */
157 height = jxl_u32(gb, 1, 65, 321, 1345, 6, 8, 10, 12);
158 width = jpegxl_width_from_ratio(height, get_bits(gb, 3));
159 if (!width)
160 width = jxl_u32(gb, 1, 65, 321, 1345, 6, 8, 10, 12);
161 }
162 if (validate && (width > 4096 || height > 4096))
163 return AVERROR_INVALIDDATA;
164
165 return 0;
166 }
167
168 /**
169 * get a Jpeg XL BitDepth Header. These cannot be invalid.
170 */
171 10 static void jpegxl_get_bit_depth(GetBitContext *gb, FFJXLMetadata *meta)
172 {
173 int bit_depth;
174
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 if (get_bits1(gb)) {
175 /* float samples */
176 bit_depth = jxl_u32(gb, 32, 16, 24, 1, 0, 0, 0, 6); /* mantissa */
177 skip_bits_long(gb, 4); /* exponent */
178 } else {
179 /* integer samples */
180 10 bit_depth = jxl_u32(gb, 8, 10, 12, 1, 0, 0, 0, 6);
181 }
182
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
10 if (meta)
183 8 meta->bit_depth = bit_depth;
184 10 }
185
186 /**
187 * validate a Jpeg XL Extra Channel Info bundle
188 * @return >= 0 upon valid, < 0 upon invalid
189 */
190 7 static int jpegxl_read_extra_channel_info(GetBitContext *gb, FFJXLMetadata *meta, int validate)
191 {
192 7 int default_alpha = get_bits1(gb);
193 7 uint32_t type, name_len = 0;
194
195
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!default_alpha) {
196 type = jxl_enum(gb);
197 if (validate && type > 63)
198 return AVERROR_INVALIDDATA; /* enum types cannot be 64+ */
199 if (validate && validate < 10 && type == JPEGXL_CT_BLACK)
200 return AVERROR_INVALIDDATA;
201 jpegxl_get_bit_depth(gb, NULL);
202 jxl_u32(gb, 0, 3, 4, 1, 0, 0, 0, 3); /* dim-shift */
203 /* max of name_len is 1071 = 48 + 2^10 - 1 */
204 name_len = 8 * jxl_u32(gb, 0, 0, 16, 48, 0, 4, 5, 10);
205 } else {
206 7 type = JPEGXL_CT_ALPHA;
207 }
208
209
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (get_bits_left(gb) < name_len)
210 return AVERROR_BUFFER_TOO_SMALL;
211
212 /* skip over the name */
213 7 skip_bits_long(gb, name_len);
214
215
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
7 if (!default_alpha && type == JPEGXL_CT_ALPHA)
216 skip_bits1(gb);
217
218
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (type == JPEGXL_CT_SPOT_COLOR)
219 skip_bits_long(gb, 16 * 4);
220
221
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (type == JPEGXL_CT_CFA)
222 jxl_u32(gb, 1, 0, 3, 19, 0, 2, 4, 8);
223
224
3/4
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
7 if (meta && type == JPEGXL_CT_ALPHA)
225 6 meta->have_alpha = 1;
226
227 7 return 0;
228 }
229
230 10 static int jpegxl_skip_extensions(GetBitContext *gb)
231 {
232 10 uint64_t extensions = jxl_u64(gb), extensions_len = 0;
233
234
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 if (get_bits_left(gb) <= 0)
235 return AVERROR_BUFFER_TOO_SMALL;
236
237
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
10 if (!extensions)
238 10 return 0;
239
240 for (int i = 0; i < 64; i++) {
241 if (extensions & (UINT64_C(1) << i))
242 extensions_len += jxl_u64(gb);
243 if (get_bits_left(gb) <= 0)
244 return AVERROR_BUFFER_TOO_SMALL;
245 }
246
247 if (extensions_len > INT_MAX || get_bits_left(gb) <= extensions_len)
248 return AVERROR_BUFFER_TOO_SMALL;
249
250 skip_bits_long(gb, extensions_len);
251
252 return 0;
253 }
254
255 31 int ff_jpegxl_parse_codestream_header(const uint8_t *buf, int buflen, FFJXLMetadata *meta, int validate)
256 {
257 31 GetBitContext gbi, *gb = &gbi;
258
259 31 int all_default, extra_fields = 0;
260 31 int xyb_encoded = 1, have_icc_profile = 0;
261 31 int animation_offset = 0, have_timecodes = 0;
262
263 31 FFJXLPrimaries primaries = JPEGXL_PR_SRGB;
264 31 FFJXLTransferCharacteristic trc = JPEGXL_TR_SRGB + (1U << 24);
265 31 FFJXLWhitePoint white_point = JPEGXL_WP_D65;
266 31 FFJXLColorSpace color_space = JPEGXL_CS_RGB;
267
268 AVRational tb;
269 31 uint32_t num_extra_channels = 0;
270 int ret;
271
272 31 ret = init_get_bits8(gb, buf, buflen);
273
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (ret < 0)
274 return ret;
275
276
3/4
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 25 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
31 if (get_bits(gb, 16) != FF_JPEGXL_CODESTREAM_SIGNATURE_LE && validate)
277 return AVERROR_INVALIDDATA;
278
279 31 ret = jpegxl_read_size_header(gb, meta, validate);
280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 31 times.
31 if (ret < 0)
281 return ret;
282
283 31 all_default = get_bits1(gb);
284
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 15 times.
31 if (!all_default)
285 16 extra_fields = get_bits1(gb);
286
287
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 24 times.
31 if (extra_fields) {
288 7 int orientation = get_bits(gb, 3);
289
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
7 if (orientation > 3 && meta)
290 FFSWAP(uint32_t, meta->width, meta->height);
291
292 /*
293 * intrinstic size
294 * any size header here is valid, but as it
295 * is variable length we have to read it
296 */
297
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (get_bits1(gb))
298 jpegxl_read_size_header(gb, NULL, 0);
299
300 /* preview header */
301
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (get_bits1(gb)) {
302 ret = jpegxl_read_preview_header(gb, 0);
303 if (ret < 0)
304 return ret;
305 }
306
307 /* animation header */
308
1/2
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
7 if (get_bits1(gb)) {
309 7 animation_offset = get_bits_count(gb);
310 7 tb.den = jxl_u32(gb, 100, 1000, 1, 1, 0, 0, 10, 30);
311 7 tb.num = jxl_u32(gb, 1, 1001, 1, 1, 0, 0, 8, 10);
312 7 jxl_u32(gb, 0, 0, 0, 0, 0, 3, 16, 32);
313 7 have_timecodes = get_bits1(gb);
314 }
315 }
316
317
4/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 1 times.
31 if (animation_offset && meta) {
318 6 meta->animation_offset = animation_offset;
319 6 meta->timebase = tb;
320 6 meta->have_timecodes = have_timecodes;
321 }
322
323
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 25 times.
31 if (get_bits_left(gb) <= 0)
324 6 return AVERROR_BUFFER_TOO_SMALL;
325
326
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 15 times.
25 if (!all_default) {
327 10 jpegxl_get_bit_depth(gb, meta);
328
329 /* modular_16bit_buffers must equal 1 */
330
1/6
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
10 if (!get_bits1(gb) && validate && validate < 10)
331 return AVERROR_INVALIDDATA;
332
333 10 num_extra_channels = jxl_u32(gb, 0, 1, 2, 1, 0, 0, 4, 12);
334
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
10 if (num_extra_channels > 4 && validate && validate < 10)
335 return AVERROR_INVALIDDATA;
336
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 10 times.
17 for (uint32_t i = 0; i < num_extra_channels; i++) {
337 7 ret = jpegxl_read_extra_channel_info(gb, meta, validate);
338
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (ret < 0)
339 return ret;
340
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (get_bits_left(gb) <= 0)
341 return AVERROR_BUFFER_TOO_SMALL;
342 }
343
344 10 xyb_encoded = get_bits1(gb);
345
346 /* color encoding bundle */
347
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 if (!get_bits1(gb)) {
348 have_icc_profile = get_bits1(gb);
349 color_space = jxl_enum(gb);
350 if (color_space > 63 && validate)
351 return AVERROR_INVALIDDATA;
352 if (!have_icc_profile) {
353 if (color_space != JPEGXL_CS_XYB) {
354 white_point = jxl_enum(gb);
355 if (white_point > 63 && validate)
356 return AVERROR_INVALIDDATA;
357 if (white_point == JPEGXL_WP_CUSTOM) {
358 /* ux and uy values */
359 jxl_u32(gb, 0, 524288, 1048576, 2097152, 19, 19, 20, 21);
360 jxl_u32(gb, 0, 524288, 1048576, 2097152, 19, 19, 20, 21);
361 }
362 if (color_space != JPEGXL_CS_GRAY) {
363 /* primaries */
364 primaries = jxl_enum(gb);
365 if (primaries > 63 && validate)
366 return AVERROR_INVALIDDATA;
367 if (primaries == JPEGXL_PR_CUSTOM) {
368 /* ux/uy values for r,g,b */
369 for (int i = 0; i < 6; i++) {
370 jxl_u32(gb, 0, 524288, 1048576, 2097152, 19, 19, 20, 21);
371 if (get_bits_left(gb) <= 0)
372 return AVERROR_BUFFER_TOO_SMALL;
373 }
374 }
375 }
376 }
377
378 /* transfer characteristics */
379 if (get_bits1(gb)) {
380 /* gamma */
381 trc = get_bits(gb, 24);
382 } else {
383 /* transfer function */
384 trc = jxl_enum(gb);
385 if (trc > 63 && validate)
386 return AVERROR_INVALIDDATA;
387 trc += (1U << 24);
388 }
389
390 /* rendering intent */
391 if (jxl_enum(gb) > 63 && validate)
392 return AVERROR_INVALIDDATA;
393 }
394 }
395
396 /* tone mapping bundle */
397
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
10 if (extra_fields && !get_bits1(gb))
398 skip_bits_long(gb, 16 + 16 + 1 + 16);
399
400 10 ret = jpegxl_skip_extensions(gb);
401
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 if (ret < 0)
402 return ret;
403 }
404
405
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 3 times.
25 if (meta) {
406 22 meta->xyb_encoded = xyb_encoded;
407 22 meta->have_icc_profile = have_icc_profile;
408 22 meta->csp = color_space;
409 22 meta->primaries = primaries;
410 22 meta->wp = white_point;
411 22 meta->trc = trc;
412
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 8 times.
22 if (!meta->bit_depth)
413 14 meta->bit_depth = 8;
414 22 meta->num_extra_channels = num_extra_channels;
415 }
416
417 /* default transform */
418
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
25 if (!get_bits1(gb)) {
419 /* opsin inverse matrix */
420 if (xyb_encoded && !get_bits1(gb))
421 skip_bits_long(gb, 16 * 16);
422 /* cw_mask and default weights */
423 if (get_bits1(gb))
424 skip_bits_long(gb, 16 * 15);
425 if (get_bits1(gb))
426 skip_bits_long(gb, 16 * 55);
427 if (get_bits1(gb))
428 skip_bits_long(gb, 16 * 210);
429 }
430
431
1/2
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
25 if (!have_icc_profile) {
432 25 int bits_remaining = 7 - ((get_bits_count(gb) - 1) & 0x7);
433
2/4
✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 25 times.
25 if (bits_remaining && get_bits(gb, bits_remaining))
434 return AVERROR_INVALIDDATA;
435 }
436
437
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
25 if (get_bits_left(gb) < 0)
438 return AVERROR_BUFFER_TOO_SMALL;
439
440 25 return get_bits_count(gb);
441 }
442
443 /*
444 * copies as much of the codestream into the buffer as possible
445 * pass a shorter buflen to request less
446 * returns the number of bytes consumed from input, may be greater than input_len
447 * if the input doesn't end on an ISOBMFF-box boundary
448 */
449 10 int ff_jpegxl_collect_codestream_header(const uint8_t *input_buffer, int input_len,
450 uint8_t *buffer, int buflen, int *copied)
451 {
452 GetByteContext gb;
453 10 int pos = 0, last_box = 0;
454 10 bytestream2_init(&gb, input_buffer, input_len);
455
456 19 while (1) {
457 uint64_t size;
458 uint32_t tag;
459 29 int head_size = 8;
460
461
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
29 if (bytestream2_get_bytes_left(&gb) < 8)
462 return AVERROR_BUFFER_TOO_SMALL;
463
464 29 size = bytestream2_get_be32(&gb);
465 29 tag = bytestream2_get_le32(&gb);
466
467
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 24 times.
29 if (size == 1) {
468
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 if (bytestream2_get_bytes_left(&gb) < 8)
469 return AVERROR_BUFFER_TOO_SMALL;
470 5 size = bytestream2_get_be64(&gb);
471 5 head_size = 16;
472 }
473 /* invalid ISOBMFF size */
474
2/4
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 29 times.
29 if (size && size <= head_size)
475 return AVERROR_INVALIDDATA;
476
1/2
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
29 if (size)
477 29 size -= head_size;
478
479
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 26 times.
29 if (tag == MKTAG('j','x','l','p')) {
480 uint32_t idx;
481
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if (bytestream2_get_bytes_left(&gb) < 4)
482 return AVERROR_BUFFER_TOO_SMALL;
483 3 idx = bytestream2_get_be32(&gb);
484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (idx >= UINT32_C(0x80000000))
485 last_box = 1;
486
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (size) {
487
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (size <= 4)
488 return AVERROR_INVALIDDATA;
489 3 size -= 4;
490 }
491 }
492
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 22 times.
29 if (tag == MKTAG('j','x','l','c'))
493 7 last_box = 1;
494
495 /*
496 * size = 0 means "until EOF". this is legal but uncommon
497 * here we just set it to the remaining size of the probe buffer
498 */
499
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 29 times.
29 if (!size)
500 size = bytestream2_get_bytes_left(&gb);
501 else
502 29 pos += size + head_size;
503
504
4/4
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 19 times.
29 if (tag == MKTAG('j','x','l','c') || tag == MKTAG('j','x','l','p')) {
505
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 5 times.
10 if (size > buflen - *copied)
506 5 size = buflen - *copied;
507 /*
508 * arbitrary chunking of the payload makes this memcpy hard to avoid
509 * in practice this will only be performed one or two times at most
510 */
511 10 *copied += bytestream2_get_buffer(&gb, buffer + *copied, size);
512 } else {
513 19 bytestream2_skip(&gb, size);
514 }
515
6/6
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 7 times.
✓ Branch 3 taken 21 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 19 times.
✓ Branch 6 taken 2 times.
29 if (last_box || bytestream2_get_bytes_left(&gb) <= 0 || *copied >= buflen)
516 break;
517 }
518
519 10 return pos;
520 }
521