FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/exif.c
Date: 2026-10-30 17:37:53
Exec Total Coverage
Lines: 600 871 68.9%
Functions: 28 29 96.6%
Branches: 349 641 54.4%

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