FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/exif.c
Date: 2026-04-24 19:58:39
Exec Total Coverage
Lines: 585 856 68.3%
Functions: 28 30 93.3%
Branches: 334 611 54.7%

Line Branch Exec Source
1 /*
2 * EXIF metadata parser
3 * Copyright (c) 2013 Thilo Borgmann <thilo.borgmann _at_ mail.de>
4 * Copyright (c) 2024-2025 Leo Izen <leo.izen@gmail.com>
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 /**
24 * @file
25 * EXIF metadata parser
26 * @author Thilo Borgmann <thilo.borgmann _at_ mail.de>
27 * @author Leo Izen <leo.izen@gmail.com>
28 */
29
30 #include <inttypes.h>
31
32 #include "libavutil/avconfig.h"
33 #include "libavutil/bprint.h"
34 #include "libavutil/display.h"
35 #include "libavutil/intreadwrite.h"
36 #include "libavutil/mem.h"
37
38 #include "bytestream.h"
39 #include "exif_internal.h"
40 #include "tiff_common.h"
41
42 #define EXIF_II_LONG 0x49492a00
43 #define EXIF_MM_LONG 0x4d4d002a
44
45 #define BASE_TAG_SIZE 12
46 #define IFD_EXTRA_SIZE 6
47
48 #define EXIF_TAG_NAME_LENGTH 32
49 #define MAKERNOTE_TAG 0x927c
50 #define ORIENTATION_TAG 0x112
51 #define EXIFIFD_TAG 0x8769
52 #define IMAGE_WIDTH_TAG 0x100
53 #define IMAGE_LENGTH_TAG 0x101
54 #define PIXEL_X_TAG 0xa002
55 #define PIXEL_Y_TAG 0xa003
56
57 struct exif_tag {
58 const char name[EXIF_TAG_NAME_LENGTH];
59 uint16_t id;
60 };
61
62 static const struct exif_tag tag_list[] = { // JEITA CP-3451 EXIF specification:
63 {"GPSVersionID", 0x00}, // <- Table 12 GPS Attribute Information
64 {"GPSLatitudeRef", 0x01},
65 {"GPSLatitude", 0x02},
66 {"GPSLongitudeRef", 0x03},
67 {"GPSLongitude", 0x04},
68 {"GPSAltitudeRef", 0x05},
69 {"GPSAltitude", 0x06},
70 {"GPSTimeStamp", 0x07},
71 {"GPSSatellites", 0x08},
72 {"GPSStatus", 0x09},
73 {"GPSMeasureMode", 0x0A},
74 {"GPSDOP", 0x0B},
75 {"GPSSpeedRef", 0x0C},
76 {"GPSSpeed", 0x0D},
77 {"GPSTrackRef", 0x0E},
78 {"GPSTrack", 0x0F},
79 {"GPSImgDirectionRef", 0x10},
80 {"GPSImgDirection", 0x11},
81 {"GPSMapDatum", 0x12},
82 {"GPSDestLatitudeRef", 0x13},
83 {"GPSDestLatitude", 0x14},
84 {"GPSDestLongitudeRef", 0x15},
85 {"GPSDestLongitude", 0x16},
86 {"GPSDestBearingRef", 0x17},
87 {"GPSDestBearing", 0x18},
88 {"GPSDestDistanceRef", 0x19},
89 {"GPSDestDistance", 0x1A},
90 {"GPSProcessingMethod", 0x1B},
91 {"GPSAreaInformation", 0x1C},
92 {"GPSDateStamp", 0x1D},
93 {"GPSDifferential", 0x1E},
94 {"ImageWidth", 0x100}, // <- Table 3 TIFF Rev. 6.0 Attribute Information Used in Exif
95 {"ImageLength", 0x101},
96 {"BitsPerSample", 0x102},
97 {"Compression", 0x103},
98 {"PhotometricInterpretation", 0x106},
99 {"Orientation", 0x112},
100 {"SamplesPerPixel", 0x115},
101 {"PlanarConfiguration", 0x11C},
102 {"YCbCrSubSampling", 0x212},
103 {"YCbCrPositioning", 0x213},
104 {"XResolution", 0x11A},
105 {"YResolution", 0x11B},
106 {"ResolutionUnit", 0x128},
107 {"StripOffsets", 0x111},
108 {"RowsPerStrip", 0x116},
109 {"StripByteCounts", 0x117},
110 {"JPEGInterchangeFormat", 0x201},
111 {"JPEGInterchangeFormatLength",0x202},
112 {"TransferFunction", 0x12D},
113 {"WhitePoint", 0x13E},
114 {"PrimaryChromaticities", 0x13F},
115 {"YCbCrCoefficients", 0x211},
116 {"ReferenceBlackWhite", 0x214},
117 {"DateTime", 0x132},
118 {"ImageDescription", 0x10E},
119 {"Make", 0x10F},
120 {"Model", 0x110},
121 {"Software", 0x131},
122 {"Artist", 0x13B},
123 {"Copyright", 0x8298},
124 {"ExifVersion", 0x9000}, // <- Table 4 Exif IFD Attribute Information (1)
125 {"FlashpixVersion", 0xA000},
126 {"ColorSpace", 0xA001},
127 {"ComponentsConfiguration", 0x9101},
128 {"CompressedBitsPerPixel", 0x9102},
129 {"PixelXDimension", 0xA002},
130 {"PixelYDimension", 0xA003},
131 {"MakerNote", 0x927C},
132 {"UserComment", 0x9286},
133 {"RelatedSoundFile", 0xA004},
134 {"DateTimeOriginal", 0x9003},
135 {"DateTimeDigitized", 0x9004},
136 {"SubSecTime", 0x9290},
137 {"SubSecTimeOriginal", 0x9291},
138 {"SubSecTimeDigitized", 0x9292},
139 {"ImageUniqueID", 0xA420},
140 {"ExposureTime", 0x829A}, // <- Table 5 Exif IFD Attribute Information (2)
141 {"FNumber", 0x829D},
142 {"ExposureProgram", 0x8822},
143 {"SpectralSensitivity", 0x8824},
144 {"ISOSpeedRatings", 0x8827},
145 {"OECF", 0x8828},
146 {"ShutterSpeedValue", 0x9201},
147 {"ApertureValue", 0x9202},
148 {"BrightnessValue", 0x9203},
149 {"ExposureBiasValue", 0x9204},
150 {"MaxApertureValue", 0x9205},
151 {"SubjectDistance", 0x9206},
152 {"MeteringMode", 0x9207},
153 {"LightSource", 0x9208},
154 {"Flash", 0x9209},
155 {"FocalLength", 0x920A},
156 {"SubjectArea", 0x9214},
157 {"FlashEnergy", 0xA20B},
158 {"SpatialFrequencyResponse", 0xA20C},
159 {"FocalPlaneXResolution", 0xA20E},
160 {"FocalPlaneYResolution", 0xA20F},
161 {"FocalPlaneResolutionUnit", 0xA210},
162 {"SubjectLocation", 0xA214},
163 {"ExposureIndex", 0xA215},
164 {"SensingMethod", 0xA217},
165 {"FileSource", 0xA300},
166 {"SceneType", 0xA301},
167 {"CFAPattern", 0xA302},
168 {"CustomRendered", 0xA401},
169 {"ExposureMode", 0xA402},
170 {"WhiteBalance", 0xA403},
171 {"DigitalZoomRatio", 0xA404},
172 {"FocalLengthIn35mmFilm", 0xA405},
173 {"SceneCaptureType", 0xA406},
174 {"GainControl", 0xA407},
175 {"Contrast", 0xA408},
176 {"Saturation", 0xA409},
177 {"Sharpness", 0xA40A},
178 {"DeviceSettingDescription", 0xA40B},
179 {"SubjectDistanceRange", 0xA40C},
180
181 /* InteropIFD tags */
182 {"RelatedImageFileFormat", 0x1000},
183 {"RelatedImageWidth", 0x1001},
184 {"RelatedImageLength", 0x1002},
185
186 /* private EXIF tags */
187 {"PrintImageMatching", 0xC4A5}, // <- undocumented meaning
188
189 /* IFD tags */
190 {"ExifIFD", 0x8769}, // <- An IFD pointing to standard Exif metadata
191 {"GPSInfo", 0x8825}, // <- An IFD pointing to GPS Exif Metadata
192 {"InteropIFD", 0xA005}, // <- Table 13 Interoperability IFD Attribute Information
193 {"GlobalParametersIFD", 0x0190},
194 {"ProfileIFD", 0xc6f5},
195
196 /* Extra FFmpeg tags */
197 { "IFD1", 0xFFFC},
198 { "IFD2", 0xFFFB},
199 { "IFD3", 0xFFFA},
200 { "IFD4", 0xFFF9},
201 { "IFD5", 0xFFF8},
202 { "IFD6", 0xFFF7},
203 { "IFD7", 0xFFF6},
204 { "IFD8", 0xFFF5},
205 { "IFD9", 0xFFF4},
206 { "IFD10", 0xFFF3},
207 { "IFD11", 0xFFF2},
208 { "IFD12", 0xFFF1},
209 { "IFD13", 0xFFF0},
210 { "IFD14", 0xFFEF},
211 { "IFD15", 0xFFEE},
212 { "IFD16", 0xFFED},
213 };
214
215 /* same as type_sizes but with string == 1 */
216 static const size_t exif_sizes[] = {
217 [0] = 0,
218 [AV_TIFF_BYTE] = 1,
219 [AV_TIFF_STRING] = 1,
220 [AV_TIFF_SHORT] = 2,
221 [AV_TIFF_LONG] = 4,
222 [AV_TIFF_RATIONAL] = 8,
223 [AV_TIFF_SBYTE] = 1,
224 [AV_TIFF_UNDEFINED] = 1,
225 [AV_TIFF_SSHORT] = 2,
226 [AV_TIFF_SLONG] = 4,
227 [AV_TIFF_SRATIONAL] = 8,
228 [AV_TIFF_FLOAT] = 4,
229 [AV_TIFF_DOUBLE] = 8,
230 [AV_TIFF_IFD] = 4,
231 };
232
233 930 const char *av_exif_get_tag_name(uint16_t id)
234 {
235
2/2
✓ Branch 0 taken 73275 times.
✓ Branch 1 taken 288 times.
73563 for (size_t i = 0; i < FF_ARRAY_ELEMS(tag_list); i++) {
236
2/2
✓ Branch 0 taken 642 times.
✓ Branch 1 taken 72633 times.
73275 if (tag_list[i].id == id)
237 642 return tag_list[i].name;
238 }
239
240 288 return NULL;
241 }
242
243 325 int32_t av_exif_get_tag_id(const char *name)
244 {
245
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 325 times.
325 if (!name)
246 return -1;
247
248
1/2
✓ Branch 0 taken 12025 times.
✗ Branch 1 not taken.
12025 for (size_t i = 0; i < FF_ARRAY_ELEMS(tag_list); i++) {
249
2/2
✓ Branch 0 taken 325 times.
✓ Branch 1 taken 11700 times.
12025 if (!strcmp(tag_list[i].name, name))
250 325 return tag_list[i].id;
251 }
252
253 return -1;
254 }
255
256 4523 static inline void tput16(PutByteContext *pb, const int le, const uint16_t value)
257 {
258
1/2
✓ Branch 0 taken 4523 times.
✗ Branch 1 not taken.
4523 le ? bytestream2_put_le16(pb, value) : bytestream2_put_be16(pb, value);
259 4523 }
260
261 4169 static inline void tput32(PutByteContext *pb, const int le, const uint32_t value)
262 {
263
1/2
✓ Branch 0 taken 4169 times.
✗ Branch 1 not taken.
4169 le ? bytestream2_put_le32(pb, value) : bytestream2_put_be32(pb, value);
264 4169 }
265
266 static inline void tput64(PutByteContext *pb, const int le, const uint64_t value)
267 {
268 le ? bytestream2_put_le64(pb, value) : bytestream2_put_be64(pb, value);
269 }
270
271 1888 static int exif_read_values(void *logctx, GetByteContext *gb, int le, AVExifEntry *entry)
272 {
273
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1888 times.
1888 if (exif_sizes[entry->type] * entry->count > bytestream2_get_bytes_left(gb))
274 return AVERROR_INVALIDDATA;
275
276
5/9
✓ Branch 0 taken 1278 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✓ Branch 3 taken 247 times.
✓ Branch 4 taken 194 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 149 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
1888 switch (entry->type) {
277 1278 case AV_TIFF_SHORT:
278 case AV_TIFF_LONG:
279 1278 entry->value.uint = av_calloc(entry->count, sizeof(*entry->value.uint));
280 1278 break;
281 case AV_TIFF_SSHORT:
282 case AV_TIFF_SLONG:
283 entry->value.sint = av_calloc(entry->count, sizeof(*entry->value.sint));
284 break;
285 20 case AV_TIFF_DOUBLE:
286 case AV_TIFF_FLOAT:
287 20 entry->value.dbl = av_calloc(entry->count, sizeof(*entry->value.dbl));
288 20 break;
289 247 case AV_TIFF_RATIONAL:
290 case AV_TIFF_SRATIONAL:
291 247 entry->value.rat = av_calloc(entry->count, sizeof(*entry->value.rat));
292 247 break;
293 194 case AV_TIFF_UNDEFINED:
294 case AV_TIFF_BYTE:
295 194 entry->value.ubytes = av_mallocz(entry->count);
296 194 break;
297 case AV_TIFF_SBYTE:
298 entry->value.sbytes = av_mallocz(entry->count);
299 break;
300 149 case AV_TIFF_STRING:
301 149 entry->value.str = av_mallocz(entry->count + 1);
302 149 break;
303 case AV_TIFF_IFD:
304 av_log(logctx, AV_LOG_WARNING, "Bad IFD type for non-IFD tag\n");
305 return AVERROR_INVALIDDATA;
306 }
307
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1888 times.
1888 if (!entry->value.ptr)
308 return AVERROR(ENOMEM);
309
6/11
✓ Branch 0 taken 953 times.
✓ Branch 1 taken 325 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 20 times.
✓ Branch 6 taken 247 times.
✓ Branch 7 taken 194 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 149 times.
✗ Branch 10 not taken.
1888 switch (entry->type) {
310 953 case AV_TIFF_SHORT:
311
2/2
✓ Branch 0 taken 2853 times.
✓ Branch 1 taken 953 times.
3806 for (size_t i = 0; i < entry->count; i++)
312 2853 entry->value.uint[i] = ff_tget_short(gb, le);
313 953 break;
314 325 case AV_TIFF_LONG:
315
2/2
✓ Branch 0 taken 2490 times.
✓ Branch 1 taken 325 times.
2815 for (size_t i = 0; i < entry->count; i++)
316 2490 entry->value.uint[i] = ff_tget_long(gb, le);
317 325 break;
318 case AV_TIFF_SSHORT:
319 for (size_t i = 0; i < entry->count; i++)
320 entry->value.sint[i] = (int16_t) ff_tget_short(gb, le);
321 break;
322 case AV_TIFF_SLONG:
323 for (size_t i = 0; i < entry->count; i++)
324 entry->value.sint[i] = (int32_t) ff_tget_long(gb, le);
325 break;
326 case AV_TIFF_DOUBLE:
327 for (size_t i = 0; i < entry->count; i++)
328 entry->value.dbl[i] = ff_tget_double(gb, le);
329 break;
330 20 case AV_TIFF_FLOAT:
331
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 20 times.
88 for (size_t i = 0; i < entry->count; i++) {
332 68 av_alias32 alias = { .u32 = ff_tget_long(gb, le) };
333 68 entry->value.dbl[i] = alias.f32;
334 }
335 20 break;
336 247 case AV_TIFF_RATIONAL:
337 case AV_TIFF_SRATIONAL:
338
2/2
✓ Branch 0 taken 356 times.
✓ Branch 1 taken 247 times.
603 for (size_t i = 0; i < entry->count; i++) {
339 356 int32_t num = ff_tget_long(gb, le);
340 356 int32_t den = ff_tget_long(gb, le);
341 356 entry->value.rat[i] = av_make_q(num, den);
342 }
343 247 break;
344 194 case AV_TIFF_UNDEFINED:
345 case AV_TIFF_BYTE:
346 /* these three fields are aliased to entry->value.ptr via a union */
347 /* and entry->value.ptr will always be nonzero here */
348
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 194 times.
194 av_assert0(entry->value.ubytes);
349 194 bytestream2_get_buffer(gb, entry->value.ubytes, entry->count);
350 194 break;
351 case AV_TIFF_SBYTE:
352 av_assert0(entry->value.sbytes);
353 bytestream2_get_buffer(gb, entry->value.sbytes, entry->count);
354 break;
355 149 case AV_TIFF_STRING:
356
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 149 times.
149 av_assert0(entry->value.str);
357 149 bytestream2_get_buffer(gb, entry->value.str, entry->count);
358 149 break;
359 }
360
361 1888 return 0;
362 }
363
364 1205 static void exif_write_values(PutByteContext *pb, int le, const AVExifEntry *entry)
365 {
366
6/11
✓ Branch 0 taken 597 times.
✓ Branch 1 taken 217 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
✓ Branch 6 taken 161 times.
✓ Branch 7 taken 128 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 92 times.
✗ Branch 10 not taken.
1205 switch (entry->type) {
367 597 case AV_TIFF_SHORT:
368
2/2
✓ Branch 0 taken 1998 times.
✓ Branch 1 taken 597 times.
2595 for (size_t i = 0; i < entry->count; i++)
369 1998 tput16(pb, le, entry->value.uint[i]);
370 597 break;
371 217 case AV_TIFF_LONG:
372
2/2
✓ Branch 0 taken 1918 times.
✓ Branch 1 taken 217 times.
2135 for (size_t i = 0; i < entry->count; i++)
373 1918 tput32(pb, le, entry->value.uint[i]);
374 217 break;
375 case AV_TIFF_SSHORT:
376 for (size_t i = 0; i < entry->count; i++)
377 tput16(pb, le, entry->value.sint[i]);
378 break;
379 case AV_TIFF_SLONG:
380 for (size_t i = 0; i < entry->count; i++)
381 tput32(pb, le, entry->value.sint[i]);
382 break;
383 case AV_TIFF_DOUBLE:
384 for (size_t i = 0; i < entry->count; i++) {
385 const av_alias64 a = { .f64 = entry->value.dbl[i] };
386 tput64(pb, le, a.u64);
387 }
388 break;
389 10 case AV_TIFF_FLOAT:
390
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 10 times.
44 for (size_t i = 0; i < entry->count; i++) {
391 34 const av_alias32 a = { .f32 = entry->value.dbl[i] };
392 34 tput32(pb, le, a.u32);
393 }
394 10 break;
395 161 case AV_TIFF_RATIONAL:
396 case AV_TIFF_SRATIONAL:
397
2/2
✓ Branch 0 taken 217 times.
✓ Branch 1 taken 161 times.
378 for (size_t i = 0; i < entry->count; i++) {
398 217 tput32(pb, le, entry->value.rat[i].num);
399 217 tput32(pb, le, entry->value.rat[i].den);
400 }
401 161 break;
402 128 case AV_TIFF_UNDEFINED:
403 case AV_TIFF_BYTE:
404 128 bytestream2_put_buffer(pb, entry->value.ubytes, entry->count);
405 128 break;
406 case AV_TIFF_SBYTE:
407 bytestream2_put_buffer(pb, entry->value.sbytes, entry->count);
408 break;
409 92 case AV_TIFF_STRING:
410 92 bytestream2_put_buffer(pb, entry->value.str, entry->count);
411 92 break;
412 }
413 1205 }
414
415 static const uint8_t aoc_header[] = { 'A', 'O', 'C', 0, };
416 static const uint8_t casio_header[] = { 'Q', 'V', 'C', 0, 0, 0, };
417 static const uint8_t foveon_header[] = { 'F', 'O', 'V', 'E', 'O', 'N', 0, 0, };
418 static const uint8_t fuji_header[] = { 'F', 'U', 'J', 'I', };
419 static const uint8_t nikon_header[] = { 'N', 'i', 'k', 'o', 'n', 0, };
420 static const uint8_t olympus1_header[] = { 'O', 'L', 'Y', 'M', 'P', 0, };
421 static const uint8_t olympus2_header[] = { 'O', 'L', 'Y', 'M', 'P', 'U', 'S', 0, 'I', 'I', };
422 static const uint8_t panasonic_header[] = { 'P', 'a', 'n', 'a', 's', 'o', 'n', 'i', 'c', 0, 0, 0, };
423 static const uint8_t sigma_header[] = { 'S', 'I', 'G', 'M', 'A', 0, 0, 0, };
424 static const uint8_t sony_header[] = { 'S', 'O', 'N', 'Y', ' ', 'D', 'S', 'C', ' ', 0, 0, 0, };
425
426 struct exif_makernote_data {
427 const uint8_t *header;
428 size_t header_size;
429 int result;
430 };
431
432 #define MAKERNOTE_STRUCT(h, r) { \
433 .header = (h), \
434 .header_size = sizeof((h)), \
435 .result = (r), \
436 }
437
438 static const struct exif_makernote_data makernote_data[] = {
439 MAKERNOTE_STRUCT(aoc_header, 6),
440 MAKERNOTE_STRUCT(casio_header, -1),
441 MAKERNOTE_STRUCT(foveon_header, 10),
442 MAKERNOTE_STRUCT(fuji_header, -1),
443 MAKERNOTE_STRUCT(olympus1_header, 8),
444 MAKERNOTE_STRUCT(olympus2_header, -1),
445 MAKERNOTE_STRUCT(panasonic_header, 12),
446 MAKERNOTE_STRUCT(sigma_header, 10),
447 MAKERNOTE_STRUCT(sony_header, 12),
448 };
449
450 /*
451 * derived from Exiv2 MakerNote's article
452 * https://exiv2.org/makernote.html or archived at
453 * https://web.archive.org/web/20250311155857/https://exiv2.org/makernote.html
454 */
455 7 static int exif_get_makernote_offset(GetByteContext *gb)
456 {
457
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if (bytestream2_get_bytes_left(gb) < BASE_TAG_SIZE)
458 return -1;
459
460
2/2
✓ Branch 0 taken 57 times.
✓ Branch 1 taken 4 times.
61 for (int i = 0; i < FF_ARRAY_ELEMS(makernote_data); i++) {
461
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 54 times.
57 if (!memcmp(gb->buffer, makernote_data[i].header, makernote_data[i].header_size))
462 3 return makernote_data[i].result;
463 }
464
465
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 if (!memcmp(gb->buffer, nikon_header, sizeof(nikon_header))) {
466 if (bytestream2_get_bytes_left(gb) < 14)
467 return -1;
468 else if (AV_RB32(gb->buffer + 10) == EXIF_MM_LONG || AV_RB32(gb->buffer + 10) == EXIF_II_LONG)
469 return -1;
470 return 8;
471 }
472
473 4 return 0;
474 }
475
476 static int exif_parse_ifd_list(void *logctx, GetByteContext *gb, int le,
477 int depth, AVExifMetadata *ifd, int guess);
478
479 1920 static int exif_decode_tag(void *logctx, GetByteContext *gb, int le,
480 int depth, AVExifEntry *entry)
481 {
482 1920 int ret = 0, makernote_offset = -1, tell, is_ifd, count;
483 enum AVTiffDataType type;
484 uint32_t payload;
485
486 /* safety check to prevent infinite recursion on malicious IFDs */
487
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1920 times.
1920 if (depth > 3)
488 return AVERROR_INVALIDDATA;
489
490 1920 tell = bytestream2_tell(gb);
491
492 1920 entry->id = ff_tget_short(gb, le);
493 1920 type = ff_tget_short(gb, le);
494 1920 count = ff_tget_long(gb, le);
495 1920 payload = ff_tget_long(gb, le);
496
497 1920 av_log(logctx, AV_LOG_DEBUG, "TIFF Tag: id: 0x%04x, type: %d, count: %u, offset: %d, "
498 1920 "payload: %" PRIu32 "\n", entry->id, type, count, tell, payload);
499
500
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1920 times.
1920 if (!type) {
501 av_log(logctx, AV_LOG_DEBUG, "Skipping invalid TIFF tag 0\n");
502 goto end;
503 }
504
505 /* AV_TIFF_IFD is the largest, numerically */
506
2/4
✓ Branch 0 taken 1920 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1920 times.
1920 if (type > AV_TIFF_IFD || count >= INT_MAX/8U)
507 return AVERROR_INVALIDDATA;
508
509
6/6
✓ Branch 0 taken 1915 times.
✓ Branch 1 taken 5 times.
✓ Branch 3 taken 1895 times.
✓ Branch 4 taken 20 times.
✓ Branch 5 taken 7 times.
✓ Branch 6 taken 1888 times.
1920 is_ifd = type == AV_TIFF_IFD || ff_tis_ifd(entry->id) || entry->id == MAKERNOTE_TAG;
510
511
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 1888 times.
1920 if (is_ifd) {
512
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
32 if (!payload)
513 goto end;
514 32 bytestream2_seek(gb, payload, SEEK_SET);
515 }
516
517
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1913 times.
1920 if (entry->id == MAKERNOTE_TAG) {
518 7 makernote_offset = exif_get_makernote_offset(gb);
519
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (makernote_offset < 0)
520 is_ifd = 0;
521 }
522
523
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 1888 times.
1920 if (is_ifd) {
524 32 entry->type = AV_TIFF_IFD;
525 32 entry->count = 1;
526 32 entry->ifd_offset = makernote_offset > 0 ? makernote_offset : 0;
527
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 29 times.
32 if (entry->ifd_offset) {
528 3 entry->ifd_lead = av_malloc(entry->ifd_offset);
529
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (!entry->ifd_lead)
530 return AVERROR(ENOMEM);
531 3 bytestream2_get_buffer(gb, entry->ifd_lead, entry->ifd_offset);
532 }
533 32 ret = exif_parse_ifd_list(logctx, gb, le, depth + 1, &entry->value.ifd, entry->id == MAKERNOTE_TAG);
534
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
32 if (ret < 0 && entry->id == MAKERNOTE_TAG) {
535 /*
536 * we guessed that MakerNote was an IFD
537 * but we were probably incorrect at this
538 * point so we try again as a binary blob
539 */
540 av_log(logctx, AV_LOG_DEBUG, "unrecognized MakerNote IFD, retrying as blob\n");
541 is_ifd = 0;
542 }
543 }
544
545 /* inverted condition instead of else so we can fall through from above */
546
2/2
✓ Branch 0 taken 32 times.
✓ Branch 1 taken 1888 times.
1920 if (!is_ifd) {
547
1/2
✓ Branch 0 taken 1888 times.
✗ Branch 1 not taken.
1888 entry->type = type == AV_TIFF_IFD ? AV_TIFF_UNDEFINED : type;
548 1888 entry->count = count;
549
2/2
✓ Branch 0 taken 1252 times.
✓ Branch 1 taken 636 times.
1888 bytestream2_seek(gb, count * exif_sizes[type] > 4 ? payload : tell + 8, SEEK_SET);
550 1888 ret = exif_read_values(logctx, gb, le, entry);
551 }
552
553 32 end:
554 1920 bytestream2_seek(gb, tell + BASE_TAG_SIZE, SEEK_SET);
555
556 1920 return ret;
557 }
558
559 119 static int exif_parse_ifd_list(void *logctx, GetByteContext *gb, int le,
560 int depth, AVExifMetadata *ifd, int guess)
561 {
562 uint32_t entries;
563 size_t required_size;
564 void *temp;
565 119 int ret = 0;
566
567 119 av_log(logctx, AV_LOG_DEBUG, "parsing IFD list at offset: %d\n", bytestream2_tell(gb));
568
569
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 119 times.
119 if (bytestream2_get_bytes_left(gb) < 2) {
570 av_log(logctx, guess ? AV_LOG_DEBUG : AV_LOG_ERROR,
571 "not enough bytes remaining in EXIF buffer: 2 required\n");
572 ret = AVERROR_INVALIDDATA;
573 goto end;
574 }
575
576 119 entries = ff_tget_short(gb, le);
577
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 119 times.
119 if (bytestream2_get_bytes_left(gb) < entries * BASE_TAG_SIZE) {
578 av_log(logctx, guess ? AV_LOG_DEBUG : AV_LOG_ERROR,
579 "not enough bytes remaining in EXIF buffer. entries: %" PRIu32 "\n", entries);
580 ret = AVERROR_INVALIDDATA;
581 goto end;
582 }
583
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 119 times.
119 if (entries > 4096) {
584 /* that is a lot of entries, probably an error */
585 av_log(logctx, guess ? AV_LOG_DEBUG : AV_LOG_ERROR,
586 "too many entries: %" PRIu32 "\n", entries);
587 ret = AVERROR_INVALIDDATA;
588 goto end;
589 }
590
591 119 ifd->count = entries;
592 119 av_log(logctx, AV_LOG_DEBUG, "entry count for IFD: %u\n", ifd->count);
593
594 /* empty IFD is technically legal but equivalent to no metadata present */
595
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 119 times.
119 if (!ifd->count) {
596 ret = 0;
597 goto end;
598 }
599
600
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 119 times.
119 if (av_size_mult(ifd->count, sizeof(*ifd->entries), &required_size) < 0) {
601 ret = AVERROR(ENOMEM);
602 goto end;
603 }
604 119 temp = av_fast_realloc(ifd->entries, &ifd->size, required_size);
605
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 119 times.
119 if (!temp) {
606 av_freep(&ifd->entries);
607 ret = AVERROR(ENOMEM);
608 goto end;
609 }
610 119 ifd->entries = temp;
611
612 /* entries have pointers in them which can cause issues if */
613 /* they are freed or realloc'd when garbage */
614 119 memset(ifd->entries, 0, required_size);
615
616
2/2
✓ Branch 0 taken 1920 times.
✓ Branch 1 taken 119 times.
2039 for (uint32_t i = 0; i < entries; i++) {
617 1920 ret = exif_decode_tag(logctx, gb, le, depth, &ifd->entries[i]);
618
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1920 times.
1920 if (ret < 0)
619 goto end;
620 }
621
622 119 end:
623
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 119 times.
119 if (ret < 0) {
624 av_exif_free(ifd);
625 return ret;
626 }
627 /*
628 * at the end of an IFD is an pointer to the next IFD
629 * or zero if there are no more IFDs, which is usually the case
630 */
631 119 ret = ff_tget_long(gb, le);
632
633 /* overflow */
634
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 119 times.
119 if (ret < 0) {
635 ret = AVERROR_INVALIDDATA;
636 av_exif_free(ifd);
637 }
638
639 119 return ret;
640 }
641
642 /*
643 * note that this function does not free the entry pointer itself
644 * because it's probably part of a larger array that should be freed
645 * all at once
646 */
647 3343 static void exif_free_entry(AVExifEntry *entry)
648 {
649
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3343 times.
3343 if (!entry)
650 return;
651
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 3261 times.
3343 if (entry->type == AV_TIFF_IFD)
652 82 av_exif_free(&entry->value.ifd);
653 else
654 3261 av_freep(&entry->value.ptr);
655 3343 av_freep(&entry->ifd_lead);
656 }
657
658 3767 void av_exif_free(AVExifMetadata *ifd)
659 {
660
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 3712 times.
3767 if (!ifd)
661 55 return;
662
2/2
✓ Branch 0 taken 3512 times.
✓ Branch 1 taken 200 times.
3712 if (!ifd->entries) {
663 3512 ifd->count = 0;
664 3512 ifd->size = 0;
665 3512 return;
666 }
667
2/2
✓ Branch 0 taken 3315 times.
✓ Branch 1 taken 200 times.
3515 for (size_t i = 0; i < ifd->count; i++) {
668 3315 AVExifEntry *entry = &ifd->entries[i];
669 3315 exif_free_entry(entry);
670 }
671 200 av_freep(&ifd->entries);
672 200 ifd->count = 0;
673 200 ifd->size = 0;
674 }
675
676 76 static size_t exif_get_ifd_size(const AVExifMetadata *ifd)
677 {
678 /* 6 == 4 + 2; 2-byte entry-count at the beginning */
679 /* plus 4-byte next-IFD pointer at the end */
680 76 size_t total_size = IFD_EXTRA_SIZE;
681
2/2
✓ Branch 0 taken 1711 times.
✓ Branch 1 taken 76 times.
1787 for (size_t i = 0; i < ifd->count; i++) {
682 1711 const AVExifEntry *entry = &ifd->entries[i];
683
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 1682 times.
1711 if (entry->type == AV_TIFF_IFD) {
684 29 total_size += BASE_TAG_SIZE + exif_get_ifd_size(&entry->value.ifd) + entry->ifd_offset;
685 } else {
686 1682 size_t payload_size = entry->count * exif_sizes[entry->type];
687
2/2
✓ Branch 0 taken 564 times.
✓ Branch 1 taken 1118 times.
1682 total_size += BASE_TAG_SIZE + (payload_size > 4 ? payload_size : 0);
688 }
689 }
690 76 return total_size;
691 }
692
693 71 static int exif_write_ifd(void *logctx, PutByteContext *pb, int le, int depth, const AVExifMetadata *ifd)
694 {
695 int offset, ret, tell, tell2;
696 71 tell = bytestream2_tell_p(pb);
697 71 tput16(pb, le, ifd->count);
698 71 offset = tell + IFD_EXTRA_SIZE + BASE_TAG_SIZE * (uint32_t) ifd->count;
699 71 av_log(logctx, AV_LOG_DEBUG, "writing IFD with %u entries and initial offset %d\n", ifd->count, offset);
700
2/2
✓ Branch 0 taken 1227 times.
✓ Branch 1 taken 71 times.
1298 for (size_t i = 0; i < ifd->count; i++) {
701 1227 const AVExifEntry *entry = &ifd->entries[i];
702 1227 av_log(logctx, AV_LOG_DEBUG, "writing TIFF entry: id: 0x%04" PRIx16 ", type: %d, count: %"
703 PRIu32 ", offset: %d, offset value: %d\n",
704 1227 entry->id, entry->type, entry->count,
705 bytestream2_tell_p(pb), offset);
706 1227 tput16(pb, le, entry->id);
707
3/4
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1222 times.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
1232 if (entry->id == MAKERNOTE_TAG && entry->type == AV_TIFF_IFD) {
708 5 size_t ifd_size = exif_get_ifd_size(&entry->value.ifd);
709 5 tput16(pb, le, AV_TIFF_UNDEFINED);
710 5 tput32(pb, le, ifd_size);
711 } else {
712 1222 tput16(pb, le, entry->type);
713 1222 tput32(pb, le, entry->count);
714 }
715
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 1205 times.
1227 if (entry->type == AV_TIFF_IFD) {
716 22 tput32(pb, le, offset);
717 22 tell2 = bytestream2_tell_p(pb);
718 22 bytestream2_seek_p(pb, offset, SEEK_SET);
719
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 20 times.
22 if (entry->ifd_offset)
720 2 bytestream2_put_buffer(pb, entry->ifd_lead, entry->ifd_offset);
721 22 ret = exif_write_ifd(logctx, pb, le, depth + 1, &entry->value.ifd);
722
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
22 if (ret < 0)
723 return ret;
724 22 offset += ret + entry->ifd_offset;
725 22 bytestream2_seek_p(pb, tell2, SEEK_SET);
726 } else {
727 1205 size_t payload_size = entry->count * exif_sizes[entry->type];
728
2/2
✓ Branch 0 taken 414 times.
✓ Branch 1 taken 791 times.
1205 if (payload_size > 4) {
729 414 tput32(pb, le, offset);
730 414 tell2 = bytestream2_tell_p(pb);
731 414 bytestream2_seek_p(pb, offset, SEEK_SET);
732 414 exif_write_values(pb, le, entry);
733 414 offset += payload_size;
734 414 bytestream2_seek_p(pb, tell2, SEEK_SET);
735 } else {
736 /* zero uninitialized excess payload values */
737 791 AV_WN32(pb->buffer, 0);
738 791 exif_write_values(pb, le, entry);
739 791 bytestream2_seek_p(pb, 4 - payload_size, SEEK_CUR);
740 }
741 }
742 }
743
744 /*
745 * we write 0 if this is the top-level exif IFD
746 * indicating that there are no more IFD pointers
747 */
748
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 49 times.
71 tput32(pb, le, depth ? offset : 0);
749 71 return offset - tell;
750 }
751
752 42 int av_exif_write(void *logctx, const AVExifMetadata *ifd, AVBufferRef **buffer, enum AVExifHeaderMode header_mode)
753 {
754 42 AVBufferRef *buf = NULL;
755 42 size_t size, headsize = 8;
756 PutByteContext pb;
757 42 int ret = 0, off = 0, next;
758 42 AVExifMetadata *ifd_new = NULL;
759 42 AVExifMetadata extra_ifds[16] = { 0 };
760
761 42 int le = 1;
762
763
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (*buffer) {
764 ret = AVERROR(EINVAL);
765 goto end;
766 }
767
768 42 size = exif_get_ifd_size(ifd);
769
2/5
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 40 times.
42 switch (header_mode) {
770 case AV_EXIF_EXIF00:
771 off = 6;
772 break;
773 2 case AV_EXIF_T_OFF:
774 2 off = 4;
775 2 break;
776 case AV_EXIF_ASSUME_BE:
777 le = 0;
778 headsize = 0;
779 break;
780 case AV_EXIF_ASSUME_LE:
781 le = 1;
782 headsize = 0;
783 break;
784 }
785
786 42 ret = av_buffer_realloc(&buf, size + off + headsize);
787
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (ret < 0)
788 goto end;
789
790
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (header_mode == AV_EXIF_EXIF00) {
791 AV_WL32(buf->data, MKTAG('E','x','i','f'));
792 AV_WN16(buf->data + 4, 0);
793
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 40 times.
42 } else if (header_mode == AV_EXIF_T_OFF) {
794 2 AV_WN32(buf->data, 0);
795 }
796
797 42 bytestream2_init_writer(&pb, buf->data + off, buf->size - off);
798
799
2/4
✓ Branch 0 taken 42 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 42 times.
✗ Branch 3 not taken.
42 if (header_mode != AV_EXIF_ASSUME_BE && header_mode != AV_EXIF_ASSUME_LE) {
800 /* these constants are be32 in both cases */
801 /* le == 1 always in this case */
802 42 bytestream2_put_be32(&pb, EXIF_II_LONG);
803 42 tput32(&pb, le, 8);
804 }
805
806 42 int extras = 0;
807
2/2
✓ Branch 0 taken 672 times.
✓ Branch 1 taken 42 times.
714 for (int i = 0; i < FF_ARRAY_ELEMS(extra_ifds); i++) {
808 672 AVExifEntry *extra_entry = NULL;
809 672 uint16_t extra_tag = 0xFFFCu - i;
810 672 ret = av_exif_get_entry(logctx, (AVExifMetadata *) ifd, extra_tag, 0, &extra_entry);
811
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 672 times.
672 if (ret < 0)
812 break;
813
2/2
✓ Branch 0 taken 665 times.
✓ Branch 1 taken 7 times.
672 if (!ret)
814 665 continue;
815 7 av_log(logctx, AV_LOG_DEBUG, "found extra IFD tag: %04x\n", extra_tag);
816
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
7 if (!ifd_new) {
817 5 ifd_new = av_exif_clone_ifd(ifd);
818
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!ifd_new)
819 break;
820 5 ifd = ifd_new;
821 }
822 /* calling remove_entry will call av_exif_free on the original */
823 7 AVExifMetadata *cloned = av_exif_clone_ifd(&extra_entry->value.ifd);
824
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (!cloned)
825 break;
826 7 extra_ifds[extras++] = *cloned;
827 /* don't use av_exif_free here, we want to preserve internals */
828 7 av_free(cloned);
829 7 ret = av_exif_remove_entry(logctx, ifd_new, extra_tag, 0);
830
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (ret < 0)
831 break;
832 }
833
834
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (ret < 0) {
835 av_log(logctx, AV_LOG_ERROR, "error popping additional IFD: %s\n", av_err2str(ret));
836 goto end;
837 }
838
839 42 next = bytestream2_tell_p(&pb);
840 42 ret = exif_write_ifd(logctx, &pb, le, 0, ifd);
841
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (ret < 0) {
842 av_log(logctx, AV_LOG_ERROR, "error writing EXIF data: %s\n", av_err2str(ret));
843 goto end;
844 }
845 42 next += ret;
846
847
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 42 times.
49 for (int i = 0; i < extras; i++) {
848 7 av_log(logctx, AV_LOG_DEBUG, "writing additional ifd at: %d\n", next);
849 /* exif_write_ifd always writes 0 i.e. last ifd so we overwrite that here */
850 7 bytestream2_seek_p(&pb, -4, SEEK_CUR);
851 7 tput32(&pb, le, next);
852 7 bytestream2_seek_p(&pb, next, SEEK_SET);
853 7 ret = exif_write_ifd(logctx, &pb, le, 0, &extra_ifds[i]);
854
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (ret < 0) {
855 av_log(logctx, AV_LOG_ERROR, "error writing additional IFD: %s\n", av_err2str(ret));
856 goto end;
857 }
858 7 next += ret;
859 }
860
861 /* shrink the buffer to the amount of data we actually used */
862 /* extras don't contribute the initial BASE_TAG_SIZE each */
863 42 ret = av_buffer_realloc(&buf, buf->size - BASE_TAG_SIZE * extras);
864
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (ret < 0)
865 goto end;
866
867 42 *buffer = buf;
868 42 ret = 0;
869
870 42 end:
871 42 av_exif_free(ifd_new);
872 42 av_freep(&ifd_new);
873
2/2
✓ Branch 0 taken 672 times.
✓ Branch 1 taken 42 times.
714 for (int i = 0; i < FF_ARRAY_ELEMS(extra_ifds); i++)
874 672 av_exif_free(&extra_ifds[i]);
875
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 42 times.
42 if (ret < 0)
876 av_buffer_unref(&buf);
877
878 42 return ret;
879 }
880
881 75 int av_exif_parse_buffer(void *logctx, const uint8_t *buf, size_t size,
882 AVExifMetadata *ifd, enum AVExifHeaderMode header_mode)
883 {
884 int ret, le;
885 GetByteContext gbytes;
886
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 if (size > INT_MAX)
887 return AVERROR(EINVAL);
888 75 size_t off = 0;
889
2/6
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 73 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
75 switch (header_mode) {
890 case AV_EXIF_EXIF00:
891 if (size < 6)
892 return AVERROR_INVALIDDATA;
893 off = 6;
894 /* fallthrough */
895 2 case AV_EXIF_T_OFF:
896
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (size < 4)
897 return AVERROR_INVALIDDATA;
898
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (!off)
899 2 off = AV_RB32(buf) + 4;
900 /* fallthrough */
901 case AV_EXIF_TIFF_HEADER: {
902 int ifd_offset;
903
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 if (size <= off)
904 return AVERROR_INVALIDDATA;
905 75 bytestream2_init(&gbytes, buf + off, size - off);
906 // read TIFF header
907 75 ret = ff_tdecode_header(&gbytes, &le, &ifd_offset);
908
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 if (ret < 0) {
909 av_log(logctx, AV_LOG_ERROR, "invalid TIFF header in EXIF data: %s\n", av_err2str(ret));
910 return ret;
911 }
912 75 bytestream2_seek(&gbytes, ifd_offset, SEEK_SET);
913 75 break;
914 }
915 case AV_EXIF_ASSUME_LE:
916 le = 1;
917 bytestream2_init(&gbytes, buf, size);
918 break;
919 case AV_EXIF_ASSUME_BE:
920 le = 0;
921 bytestream2_init(&gbytes, buf, size);
922 break;
923 default:
924 return AVERROR(EINVAL);
925 }
926
927 /*
928 * parse IFD0 here. If the return value is positive that tells us
929 * there is subimage metadata, but we don't parse that IFD here
930 */
931 75 ret = exif_parse_ifd_list(logctx, &gbytes, le, 0, ifd, 0);
932
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
75 if (ret < 0) {
933 av_log(logctx, AV_LOG_ERROR, "error decoding EXIF data: %s\n", av_err2str(ret));
934 return ret;
935 }
936
2/2
✓ Branch 0 taken 66 times.
✓ Branch 1 taken 9 times.
75 if (!ret)
937 66 goto finish;
938 9 int next = ret;
939 9 bytestream2_seek(&gbytes, next, SEEK_SET);
940
941 /* cap at 16 extra IFDs for sanity/parse security */
942
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 for (int extra_tag = 0xFFFCu; extra_tag > 0xFFECu; extra_tag--) {
943 12 AVExifMetadata extra_ifd = { 0 };
944 12 ret = exif_parse_ifd_list(logctx, &gbytes, le, 0, &extra_ifd, 1);
945
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (ret < 0) {
946 av_exif_free(&extra_ifd);
947 9 break;
948 }
949 12 next = ret;
950 12 av_log(logctx, AV_LOG_DEBUG, "found extra IFD: %04x with next=%d\n", extra_tag, ret);
951 12 bytestream2_seek(&gbytes, next, SEEK_SET);
952 12 ret = av_exif_set_entry(logctx, ifd, extra_tag, AV_TIFF_IFD, 1, NULL, 0, &extra_ifd);
953 12 av_exif_free(&extra_ifd);
954
4/6
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 9 times.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
12 if (ret < 0 || !next || bytestream2_get_bytes_left(&gbytes) <= 0)
955 break;
956 }
957
958 finish:
959 75 return bytestream2_tell(&gbytes) + off;
960 }
961
962 #define COLUMN_SEP(i, c) ((i) ? ((i) % (c) ? ", " : "\n") : "")
963
964 59 static int exif_ifd_to_dict(void *logctx, const char *prefix, const AVExifMetadata *ifd, AVDictionary **metadata)
965 {
966 AVBPrint bp;
967 59 int ret = 0;
968 59 char *key = NULL;
969 59 char *value = NULL;
970
971
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
59 if (!prefix)
972 prefix = "";
973
974
2/2
✓ Branch 0 taken 930 times.
✓ Branch 1 taken 59 times.
989 for (uint16_t i = 0; i < ifd->count; i++) {
975 930 const AVExifEntry *entry = &ifd->entries[i];
976 930 const char *name = av_exif_get_tag_name(entry->id);
977 930 av_bprint_init(&bp, entry->count * 10, AV_BPRINT_SIZE_UNLIMITED);
978
2/2
✓ Branch 0 taken 472 times.
✓ Branch 1 taken 458 times.
930 if (*prefix)
979 472 av_bprintf(&bp, "%s/", prefix);
980
2/2
✓ Branch 0 taken 642 times.
✓ Branch 1 taken 288 times.
930 if (name)
981 642 av_bprintf(&bp, "%s", name);
982 else
983 288 av_bprintf(&bp, "0x%04X", entry->id);
984 930 ret = av_bprint_finalize(&bp, &key);
985
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 930 times.
930 if (ret < 0)
986 goto end;
987 930 av_bprint_init(&bp, entry->count * 10, AV_BPRINT_SIZE_UNLIMITED);
988
6/9
✓ Branch 0 taken 21 times.
✓ Branch 1 taken 624 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 134 times.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 65 times.
✓ Branch 6 taken 76 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
930 switch (entry->type) {
989 21 case AV_TIFF_IFD:
990 21 ret = exif_ifd_to_dict(logctx, key, &entry->value.ifd, metadata);
991
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 21 times.
21 if (ret < 0)
992 goto end;
993 21 break;
994 624 case AV_TIFF_SHORT:
995 case AV_TIFF_LONG:
996
2/2
✓ Branch 0 taken 3715 times.
✓ Branch 1 taken 624 times.
4339 for (uint32_t j = 0; j < entry->count; j++)
997
4/4
✓ Branch 0 taken 3091 times.
✓ Branch 1 taken 624 times.
✓ Branch 2 taken 2743 times.
✓ Branch 3 taken 348 times.
3715 av_bprintf(&bp, "%s%7" PRIu32, COLUMN_SEP(j, 8), (uint32_t)entry->value.uint[j]);
998 624 break;
999 case AV_TIFF_SSHORT:
1000 case AV_TIFF_SLONG:
1001 for (uint32_t j = 0; j < entry->count; j++)
1002 av_bprintf(&bp, "%s%7" PRId32, COLUMN_SEP(j, 8), (int32_t)entry->value.sint[j]);
1003 break;
1004 134 case AV_TIFF_RATIONAL:
1005 case AV_TIFF_SRATIONAL:
1006
2/2
✓ Branch 0 taken 187 times.
✓ Branch 1 taken 134 times.
321 for (uint32_t j = 0; j < entry->count; j++)
1007
4/4
✓ Branch 0 taken 53 times.
✓ Branch 1 taken 134 times.
✓ Branch 2 taken 44 times.
✓ Branch 3 taken 9 times.
187 av_bprintf(&bp, "%s%7i:%-7i", COLUMN_SEP(j, 4), entry->value.rat[j].num, entry->value.rat[j].den);
1008 134 break;
1009 10 case AV_TIFF_DOUBLE:
1010 case AV_TIFF_FLOAT:
1011
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 10 times.
44 for (uint32_t j = 0; j < entry->count; j++)
1012
3/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
34 av_bprintf(&bp, "%s%.15g", COLUMN_SEP(j, 4), entry->value.dbl[j]);
1013 10 break;
1014 65 case AV_TIFF_STRING:
1015 65 av_bprintf(&bp, "%s", entry->value.str);
1016 65 break;
1017 76 case AV_TIFF_UNDEFINED:
1018 case AV_TIFF_BYTE:
1019
2/2
✓ Branch 0 taken 27795 times.
✓ Branch 1 taken 76 times.
27871 for (uint32_t j = 0; j < entry->count; j++)
1020
4/4
✓ Branch 0 taken 27719 times.
✓ Branch 1 taken 76 times.
✓ Branch 2 taken 26012 times.
✓ Branch 3 taken 1707 times.
27795 av_bprintf(&bp, "%s%3i", COLUMN_SEP(j, 16), entry->value.ubytes[j]);
1021 76 break;
1022 case AV_TIFF_SBYTE:
1023 for (uint32_t j = 0; j < entry->count; j++)
1024 av_bprintf(&bp, "%s%3i", COLUMN_SEP(j, 16), entry->value.sbytes[j]);
1025 break;
1026 }
1027
2/2
✓ Branch 0 taken 909 times.
✓ Branch 1 taken 21 times.
930 if (entry->type != AV_TIFF_IFD) {
1028
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 909 times.
909 if (!av_bprint_is_complete(&bp)) {
1029 av_bprint_finalize(&bp, NULL);
1030 ret = AVERROR(ENOMEM);
1031 goto end;
1032 }
1033 909 ret = av_bprint_finalize(&bp, &value);
1034
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 909 times.
909 if (ret < 0)
1035 goto end;
1036 909 ret = av_dict_set(metadata, key, value, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL);
1037 909 key = NULL;
1038 909 value = NULL;
1039
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 909 times.
909 if (ret < 0)
1040 goto end;
1041 } else {
1042 21 av_freep(&key);
1043 }
1044 }
1045
1046 59 end:
1047 59 av_freep(&key);
1048 59 av_freep(&value);
1049 59 return ret;
1050 }
1051
1052 38 int av_exif_ifd_to_dict(void *logctx, const AVExifMetadata *ifd, AVDictionary **metadata)
1053 {
1054 38 return exif_ifd_to_dict(logctx, "", ifd, metadata);
1055 }
1056
1057 #if LIBAVCODEC_VERSION_MAJOR < 63
1058 int avpriv_exif_decode_ifd(void *logctx, const uint8_t *buf, int size,
1059 int le, int depth, AVDictionary **metadata)
1060 {
1061 AVExifMetadata ifd = { 0 };
1062 GetByteContext gb;
1063 int ret;
1064 bytestream2_init(&gb, buf, size);
1065 ret = exif_parse_ifd_list(logctx, &gb, le, depth, &ifd, 0);
1066 if (ret < 0)
1067 return ret;
1068 ret = av_exif_ifd_to_dict(logctx, &ifd, metadata);
1069 av_exif_free(&ifd);
1070 return ret;
1071 }
1072 #endif
1073
1074 #define EXIF_COPY(fname, srcname) do { \
1075 size_t sz; \
1076 if (av_size_mult(src->count, sizeof(*(fname)), &sz) < 0) { \
1077 ret = AVERROR(ENOMEM); \
1078 goto end; \
1079 } \
1080 (fname) = av_memdup((srcname), sz); \
1081 if (!(fname)) { \
1082 ret = AVERROR(ENOMEM); \
1083 goto end; \
1084 } \
1085 } while (0)
1086
1087 1423 static int exif_clone_entry(AVExifEntry *dst, const AVExifEntry *src)
1088 {
1089 1423 int ret = 0;
1090
1091 1423 memset(dst, 0, sizeof(*dst));
1092
1093 1423 dst->count = src->count;
1094 1423 dst->id = src->id;
1095 1423 dst->type = src->type;
1096
1097 1423 dst->ifd_offset = src->ifd_offset;
1098
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1421 times.
1423 if (src->ifd_lead) {
1099 2 dst->ifd_lead = av_memdup(src->ifd_lead, src->ifd_offset);
1100
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!dst->ifd_lead) {
1101 ret = AVERROR(ENOMEM);
1102 goto end;
1103 }
1104 } else {
1105 1421 dst->ifd_lead = NULL;
1106 }
1107
1108
6/9
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 886 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 210 times.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 150 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 117 times.
✗ Branch 8 not taken.
1423 switch(src->type) {
1109 50 case AV_TIFF_IFD: {
1110 50 AVExifMetadata *cloned = av_exif_clone_ifd(&src->value.ifd);
1111
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
50 if (!cloned) {
1112 ret = AVERROR(ENOMEM);
1113 goto end;
1114 }
1115 50 dst->value.ifd = *cloned;
1116 50 av_freep(&cloned);
1117 50 break;
1118 }
1119 886 case AV_TIFF_SHORT:
1120 case AV_TIFF_LONG:
1121
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 886 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 886 times.
886 EXIF_COPY(dst->value.uint, src->value.uint);
1122 886 break;
1123 case AV_TIFF_SLONG:
1124 case AV_TIFF_SSHORT:
1125 EXIF_COPY(dst->value.sint, src->value.sint);
1126 break;
1127 210 case AV_TIFF_RATIONAL:
1128 case AV_TIFF_SRATIONAL:
1129
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 210 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 210 times.
210 EXIF_COPY(dst->value.rat, src->value.rat);
1130 210 break;
1131 10 case AV_TIFF_DOUBLE:
1132 case AV_TIFF_FLOAT:
1133
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
10 EXIF_COPY(dst->value.dbl, src->value.dbl);
1134 10 break;
1135 150 case AV_TIFF_BYTE:
1136 case AV_TIFF_UNDEFINED:
1137
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 150 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 150 times.
150 EXIF_COPY(dst->value.ubytes, src->value.ubytes);
1138 150 break;
1139 case AV_TIFF_SBYTE:
1140 EXIF_COPY(dst->value.sbytes, src->value.sbytes);
1141 break;
1142 117 case AV_TIFF_STRING:
1143 117 dst->value.str = av_memdup(src->value.str, src->count+1);
1144
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 117 times.
117 if (!dst->value.str) {
1145 ret = AVERROR(ENOMEM);
1146 goto end;
1147 }
1148 117 break;
1149 }
1150
1151 1423 return 0;
1152
1153 end:
1154 av_freep(&dst->ifd_lead);
1155 if (src->type == AV_TIFF_IFD)
1156 av_exif_free(&dst->value.ifd);
1157 else
1158 av_freep(&dst->value.ptr);
1159 memset(dst, 0, sizeof(*dst));
1160
1161 return ret;
1162 }
1163
1164 703 static int exif_get_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, int depth, AVExifEntry **value)
1165 {
1166 703 int offset = 1;
1167
1168
5/8
✓ Branch 0 taken 703 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 701 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 701 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 703 times.
703 if (!ifd || ifd->count && !ifd->entries || !value)
1169 return AVERROR(EINVAL);
1170
1171
2/2
✓ Branch 0 taken 7941 times.
✓ Branch 1 taken 695 times.
8636 for (size_t i = 0; i < ifd->count; i++) {
1172
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 7933 times.
7941 if (ifd->entries[i].id == id) {
1173 8 *value = &ifd->entries[i];
1174 8 return i + offset;
1175 }
1176
2/2
✓ Branch 0 taken 212 times.
✓ Branch 1 taken 7721 times.
7933 if (ifd->entries[i].type == AV_TIFF_IFD) {
1177
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 212 times.
212 if (depth < 3) {
1178 int ret = exif_get_entry(logctx, &ifd->entries[i].value.ifd, id, depth + 1, value);
1179 if (ret)
1180 return ret < 0 ? ret : ret + offset;
1181 }
1182 212 offset += ifd->entries[i].value.ifd.count;
1183 }
1184 }
1185
1186 695 return 0;
1187 }
1188
1189 703 int av_exif_get_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, int flags, AVExifEntry **value)
1190 {
1191
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 703 times.
703 return exif_get_entry(logctx, ifd, id, (flags & AV_EXIF_FLAG_RECURSIVE) ? 0 : INT_MAX, value);
1192 }
1193
1194 27 int av_exif_set_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, enum AVTiffDataType type,
1195 uint32_t count, const uint8_t *ifd_lead, uint32_t ifd_offset, const void *value)
1196 {
1197 void *temp;
1198 27 int ret = 0;
1199 27 AVExifEntry *entry = NULL;
1200 27 AVExifEntry src = { 0 };
1201
1202
4/6
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 25 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 25 times.
✗ Branch 5 not taken.
27 if (!ifd || ifd->count && !ifd->entries
1203
3/8
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 27 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 27 times.
✗ Branch 7 not taken.
27 || ifd_lead && !ifd_offset || !ifd_lead && ifd_offset
1204
2/4
✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 27 times.
27 || !value || ifd->count == 0xFFFFu)
1205 return AVERROR(EINVAL);
1206
1207 27 ret = av_exif_get_entry(logctx, ifd, id, 0, &entry);
1208
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (ret < 0)
1209 return ret;
1210
1211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (entry) {
1212 exif_free_entry(entry);
1213 } else {
1214 size_t required_size;
1215 27 ret = av_size_mult(ifd->count + 1, sizeof(*ifd->entries), &required_size);
1216
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (ret < 0)
1217 return AVERROR(ENOMEM);
1218 27 temp = av_fast_realloc(ifd->entries, &ifd->size, required_size);
1219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (!temp)
1220 return AVERROR(ENOMEM);
1221 27 ifd->entries = temp;
1222 27 entry = &ifd->entries[ifd->count++];
1223 }
1224
1225 27 src.count = count;
1226 27 src.id = id;
1227 27 src.type = type;
1228 27 src.ifd_lead = (uint8_t *) ifd_lead;
1229 27 src.ifd_offset = ifd_offset;
1230
2/2
✓ Branch 0 taken 14 times.
✓ Branch 1 taken 13 times.
27 if (type == AV_TIFF_IFD)
1231 14 src.value.ifd = * (const AVExifMetadata *) value;
1232 else
1233 13 src.value.ptr = (void *) value;
1234
1235 27 ret = exif_clone_entry(entry, &src);
1236
1237
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
27 if (ret < 0)
1238 ifd->count--;
1239
1240 27 return ret;
1241 }
1242
1243 28 static int exif_remove_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, int depth)
1244 {
1245 28 int32_t index = -1;
1246 28 int ret = 0;
1247
1248
3/6
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 28 times.
28 if (!ifd || ifd->count && !ifd->entries)
1249 return AVERROR(EINVAL);
1250
1251
1/2
✓ Branch 0 taken 209 times.
✗ Branch 1 not taken.
209 for (size_t i = 0; i < ifd->count; i++) {
1252
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 181 times.
209 if (ifd->entries[i].id == id) {
1253 28 index = i;
1254 28 break;
1255 }
1256
3/4
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 174 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
181 if (ifd->entries[i].type == AV_TIFF_IFD && depth < 3) {
1257 ret = exif_remove_entry(logctx, &ifd->entries[i].value.ifd, id, depth + 1);
1258 if (ret)
1259 return ret;
1260 }
1261 }
1262
1263
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 if (index < 0)
1264 return 0;
1265 28 exif_free_entry(&ifd->entries[index]);
1266
1267
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 23 times.
28 if (index == --ifd->count) {
1268
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if (!index)
1269 av_freep(&ifd->entries);
1270 5 return 1;
1271 }
1272
1273 23 memmove(&ifd->entries[index], &ifd->entries[index + 1], (ifd->count - index) * sizeof(*ifd->entries));
1274
1275 23 return 1 + (ifd->count - index);
1276 }
1277
1278 28 int av_exif_remove_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, int flags)
1279 {
1280
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 28 times.
28 return exif_remove_entry(logctx, ifd, id, (flags & AV_EXIF_FLAG_RECURSIVE) ? 0 : INT_MAX);
1281 }
1282
1283 81 AVExifMetadata *av_exif_clone_ifd(const AVExifMetadata *ifd)
1284 {
1285 81 AVExifMetadata *ret = av_mallocz(sizeof(*ret));
1286
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
81 if (!ret)
1287 return NULL;
1288
1289 81 ret->count = ifd->count;
1290
2/2
✓ Branch 0 taken 79 times.
✓ Branch 1 taken 2 times.
81 if (ret->count) {
1291 size_t required_size;
1292
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 79 times.
79 if (av_size_mult(ret->count, sizeof(*ret->entries), &required_size) < 0)
1293 goto fail;
1294 79 av_fast_mallocz(&ret->entries, &ret->size, required_size);
1295
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
79 if (!ret->entries)
1296 goto fail;
1297 }
1298
1299
2/2
✓ Branch 0 taken 1396 times.
✓ Branch 1 taken 81 times.
1477 for (size_t i = 0; i < ret->count; i++) {
1300 1396 const AVExifEntry *entry = &ifd->entries[i];
1301 1396 AVExifEntry *ret_entry = &ret->entries[i];
1302 1396 int status = exif_clone_entry(ret_entry, entry);
1303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1396 times.
1396 if (status < 0)
1304 goto fail;
1305 }
1306
1307 81 return ret;
1308
1309 fail:
1310 av_exif_free(ret);
1311 av_free(ret);
1312 return NULL;
1313 }
1314
1315 static const int rotation_lut[2][4] = {
1316 {1, 8, 3, 6}, {4, 7, 2, 5},
1317 };
1318
1319 2 int av_exif_matrix_to_orientation(const int32_t *matrix)
1320 {
1321 2 double rotation = av_display_rotation_get(matrix);
1322 // determinant
1323 2 int vflip = ((int64_t)matrix[0] * (int64_t)matrix[4]
1324 2 - (int64_t)matrix[1] * (int64_t)matrix[3]) < 0;
1325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!isfinite(rotation))
1326 return 0;
1327 2 int rot = (int)(rotation + 0.5);
1328 2 rot = (((rot % 360) + 360) % 360) / 90;
1329 2 return rotation_lut[vflip][rot];
1330 }
1331
1332 18 int av_exif_orientation_to_matrix(int32_t *matrix, int orientation)
1333 {
1334
2/9
✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
18 switch (orientation) {
1335 14 case 1:
1336 14 av_display_rotation_set(matrix, 0.0);
1337 14 break;
1338 case 2:
1339 av_display_rotation_set(matrix, 0.0);
1340 av_display_matrix_flip(matrix, 1, 0);
1341 break;
1342 case 3:
1343 av_display_rotation_set(matrix, 180.0);
1344 break;
1345 case 4:
1346 av_display_rotation_set(matrix, 180.0);
1347 av_display_matrix_flip(matrix, 1, 0);
1348 break;
1349 4 case 5:
1350 4 av_display_rotation_set(matrix, 90.0);
1351 4 av_display_matrix_flip(matrix, 1, 0);
1352 4 break;
1353 case 6:
1354 av_display_rotation_set(matrix, 90.0);
1355 break;
1356 case 7:
1357 av_display_rotation_set(matrix, -90.0);
1358 av_display_matrix_flip(matrix, 1, 0);
1359 break;
1360 case 8:
1361 av_display_rotation_set(matrix, -90.0);
1362 break;
1363 default:
1364 return AVERROR(EINVAL);
1365 }
1366
1367 18 return 0;
1368 }
1369
1370 3 int ff_exif_sanitize_ifd(void *logctx, const AVFrame *frame, AVExifMetadata *ifd)
1371 {
1372 3 int ret = 0;
1373 3 AVFrameSideData *sd_orient = NULL;
1374 3 AVExifEntry *or = NULL;
1375 3 AVExifEntry *iw = NULL;
1376 3 AVExifEntry *ih = NULL;
1377 3 AVExifEntry *pw = NULL;
1378 3 AVExifEntry *ph = NULL;
1379 3 uint64_t orientation = 1;
1380 3 uint64_t w = frame->width;
1381 3 uint64_t h = frame->height;
1382 3 int rewrite = 0;
1383
1384 3 sd_orient = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX);
1385
1386
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (sd_orient)
1387 1 orientation = av_exif_matrix_to_orientation((int32_t *) sd_orient->data);
1388
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (orientation != 1)
1389 1 av_log(logctx, AV_LOG_DEBUG, "matrix contains nontrivial EXIF orientation: %" PRIu64 "\n", orientation);
1390
1391
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
12 for (size_t i = 0; i < ifd->count; i++) {
1392 9 AVExifEntry *entry = &ifd->entries[i];
1393
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
9 if (entry->id == ORIENTATION_TAG && entry->count > 0 && entry->type == AV_TIFF_SHORT) {
1394 or = entry;
1395 continue;
1396 }
1397
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
9 if (entry->id == IMAGE_WIDTH_TAG && entry->count > 0 && entry->type == AV_TIFF_LONG) {
1398 iw = entry;
1399 continue;
1400 }
1401
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
9 if (entry->id == IMAGE_LENGTH_TAG && entry->count > 0 && entry->type == AV_TIFF_LONG) {
1402 ih = entry;
1403 continue;
1404 }
1405
3/4
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
9 if (entry->id == EXIFIFD_TAG && entry->type == AV_TIFF_IFD) {
1406 1 AVExifMetadata *exif = &entry->value.ifd;
1407
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 for (size_t j = 0; j < exif->count; j++) {
1408 1 AVExifEntry *exifentry = &exif->entries[j];
1409
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 if (exifentry->id == PIXEL_X_TAG && exifentry->count > 0 && exifentry->type == AV_TIFF_SHORT) {
1410 pw = exifentry;
1411 continue;
1412 }
1413
1/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 if (exifentry->id == PIXEL_Y_TAG && exifentry->count > 0 && exifentry->type == AV_TIFF_SHORT) {
1414 ph = exifentry;
1415 continue;
1416 }
1417 }
1418 }
1419 }
1420
1421
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 if (or && or->value.uint[0] != orientation) {
1422 rewrite = 1;
1423 or->value.uint[0] = orientation;
1424 }
1425
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 if (iw && iw->value.uint[0] != w) {
1426 rewrite = 1;
1427 iw->value.uint[0] = w;
1428 }
1429
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 if (ih && ih->value.uint[0] != h) {
1430 rewrite = 1;
1431 ih->value.uint[0] = h;
1432 }
1433
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 if (pw && pw->value.uint[0] != w) {
1434 rewrite = 1;
1435 pw->value.uint[0] = w;
1436 }
1437
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
3 if (ph && ph->value.uint[0] != h) {
1438 rewrite = 1;
1439 ph->value.uint[0] = h;
1440 }
1441
3/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 2 times.
3 if (!or && orientation != 1) {
1442 1 rewrite = 1;
1443 1 ret = av_exif_set_entry(logctx, ifd, ORIENTATION_TAG, AV_TIFF_SHORT, 1, NULL, 0, &orientation);
1444
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ret < 0)
1445 goto end;
1446 }
1447
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 if (!iw && w) {
1448 3 rewrite = 1;
1449 3 ret = av_exif_set_entry(logctx, ifd, IMAGE_WIDTH_TAG, AV_TIFF_LONG, 1, NULL, 0, &w);
1450
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
1451 goto end;
1452 }
1453
2/4
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
3 if (!ih && h) {
1454 3 rewrite = 1;
1455 3 ret = av_exif_set_entry(logctx, ifd, IMAGE_LENGTH_TAG, AV_TIFF_LONG, 1, NULL, 0, &h);
1456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
1457 goto end;
1458 }
1459
3/12
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
3 if (!pw && w && w < 0xFFFFu || !ph && h && h < 0xFFFFu) {
1460 AVExifMetadata *exif;
1461 AVExifEntry *exif_entry;
1462 3 int exif_found = av_exif_get_entry(logctx, ifd, EXIFIFD_TAG, 0, &exif_entry);
1463 3 rewrite = 1;
1464
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (exif_found < 0)
1465 goto end;
1466
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
3 if (exif_found > 0) {
1467 1 exif = &exif_entry->value.ifd;
1468 } else {
1469 2 AVExifMetadata exif_new = { 0 };
1470 2 ret = av_exif_set_entry(logctx, ifd, EXIFIFD_TAG, AV_TIFF_IFD, 1, NULL, 0, &exif_new);
1471
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (ret < 0) {
1472 av_exif_free(&exif_new);
1473 goto end;
1474 }
1475 2 exif = &ifd->entries[ifd->count - 1].value.ifd;
1476 }
1477
3/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
3 if (!pw && w && w < 0xFFFFu) {
1478 3 ret = av_exif_set_entry(logctx, exif, PIXEL_X_TAG, AV_TIFF_SHORT, 1, NULL, 0, &w);
1479
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
1480 goto end;
1481 }
1482
3/6
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
3 if (!ph && h && h < 0xFFFFu) {
1483 3 ret = av_exif_set_entry(logctx, exif, PIXEL_Y_TAG, AV_TIFF_SHORT, 1, NULL, 0, &h);
1484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
1485 goto end;
1486 }
1487 }
1488
1489 3 return rewrite;
1490
1491 end:
1492 return ret;
1493 }
1494
1495 249 int ff_exif_get_buffer(void *logctx, const AVFrame *frame, AVBufferRef **buffer_ptr, enum AVExifHeaderMode header_mode)
1496 {
1497 249 AVFrameSideData *sd_exif = NULL;
1498 249 AVBufferRef *buffer = NULL;
1499 249 AVExifMetadata ifd = { 0 };
1500 249 int ret = 0;
1501 249 int rewrite = 0;
1502
1503
2/4
✓ Branch 0 taken 249 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 249 times.
249 if (!buffer_ptr || *buffer_ptr)
1504 return AVERROR(EINVAL);
1505
1506 249 sd_exif = av_frame_get_side_data(frame, AV_FRAME_DATA_EXIF);
1507
2/2
✓ Branch 0 taken 246 times.
✓ Branch 1 taken 3 times.
249 if (!sd_exif)
1508 246 return 0;
1509
1510 3 ret = av_exif_parse_buffer(logctx, sd_exif->data, sd_exif->size, &ifd, AV_EXIF_TIFF_HEADER);
1511
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
1512 goto end;
1513
1514 3 rewrite = ff_exif_sanitize_ifd(logctx, frame, &ifd);
1515
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (rewrite < 0) {
1516 ret = rewrite;
1517 goto end;
1518 }
1519
1520
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if (rewrite) {
1521 3 ret = av_exif_write(logctx, &ifd, &buffer, header_mode);
1522
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 if (ret < 0)
1523 goto end;
1524
1525 3 *buffer_ptr = buffer;
1526 } else {
1527 *buffer_ptr = av_buffer_ref(sd_exif->buf);
1528 if (!*buffer_ptr) {
1529 ret = AVERROR(ENOMEM);
1530 goto end;
1531 }
1532 }
1533
1534 3 av_exif_free(&ifd);
1535 3 return rewrite;
1536
1537 end:
1538 av_exif_free(&ifd);
1539 return ret;
1540 }
1541