FFmpeg coverage


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