Bug Summary

File:root/firefox-clang/media/ffvpx/libavcodec/bytestream.h
Warning:line 296, column 5
Null pointer passed to 2nd parameter expecting 'nonnull'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name exif.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/media/ffvpx/libavcodec -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/media/ffvpx/libavcodec -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -include libavutil_visibility.h -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D HAVE_AV_CONFIG_H -D ASSERT_LEVEL=2 -I /root/firefox-clang/media/ffvpx/libavcodec -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/media/ffvpx/libavcodec -I /root/firefox-clang/modules/fdlibm/inexact-math-override -I /root/firefox-clang/third_party/khronos/vulkan-headers/include -I /root/firefox-clang/media/mozva -I /root/firefox-clang/media/libopus/include -I /root/firefox-clang/media/libvorbis -I /root/firefox-clang/media/libvpx -I /root/firefox-clang/media/ffvpx -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=tautological-type-limit-compare -Wno-range-loop-analysis -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-unknown-warning-option -Wno-character-conversion -Wno-parentheses -Wno-pointer-sign -Wno-sign-compare -Wno-switch -Wno-type-limits -Wno-unused-function -Wno-deprecated-declarations -Wno-absolute-value -Wno-incompatible-pointer-types -Wno-string-conversion -Wno-visibility -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-10-17-231001-351276-1 -x c /root/firefox-clang/media/ffvpx/libavcodec/exif.c

/root/firefox-clang/media/ffvpx/libavcodec/exif.c

→
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_LONG0x49492a00 0x49492a00
44#define EXIF_MM_LONG0x4d4d002a 0x4d4d002a
45
46#define BASE_TAG_SIZE12 12
47#define IFD_EXTRA_SIZE6 6
48
49#define EXIF_TAG_NAME_LENGTH32 32
50#define MAKERNOTE_TAG0x927c 0x927c
51#define ORIENTATION_TAG0x112 0x112
52#define EXIFIFD_TAG0x8769 0x8769
53#define IMAGE_WIDTH_TAG0x100 0x100
54#define IMAGE_LENGTH_TAG0x101 0x101
55#define PIXEL_X_TAG0xa002 0xa002
56#define PIXEL_Y_TAG0xa003 0xa003
57
58struct exif_tag {
59 const char name[EXIF_TAG_NAME_LENGTH32];
60 uint16_t id;
61};
62
63static 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 */
217static 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
234const char *av_exif_get_tag_name(uint16_t id)
235{
236 for (size_t i = 0; i < FF_ARRAY_ELEMS(tag_list)(sizeof(tag_list) / sizeof((tag_list)[0])); i++) {
237 if (tag_list[i].id == id)
238 return tag_list[i].name;
239 }
240
241 return NULL((void*)0);
242}
243
244int32_t av_exif_get_tag_id(const char *name)
245{
246 if (!name)
247 return -1;
248
249 for (size_t i = 0; i < FF_ARRAY_ELEMS(tag_list)(sizeof(tag_list) / sizeof((tag_list)[0])); i++) {
250 if (!strcmp(tag_list[i].name, name))
251 return tag_list[i].id;
252 }
253
254 return -1;
255}
256
257static inline void tput16(PutByteContext *pb, const int le, const uint16_t value)
258{
259 le ? bytestream2_put_le16(pb, value) : bytestream2_put_be16(pb, value);
260}
261
262static inline void tput32(PutByteContext *pb, const int le, const uint32_t value)
263{
264 le ? bytestream2_put_le32(pb, value) : bytestream2_put_be32(pb, value);
265}
266
267static 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
272static int exif_read_values(void *logctx, GetByteContext *gb, int le, AVExifEntry *entry)
273{
274 if (exif_sizes[entry->type] * entry->count > bytestream2_get_bytes_left(gb))
275 return AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | ((
unsigned)('A') << 24)))
;
276
277 switch (entry->type) {
278 case AV_TIFF_SHORT:
279 case AV_TIFF_LONG:
280 entry->value.uint = av_calloc(entry->count, sizeof(*entry->value.uint));
281 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 case AV_TIFF_DOUBLE:
287 case AV_TIFF_FLOAT:
288 entry->value.dbl = av_calloc(entry->count, sizeof(*entry->value.dbl));
289 break;
290 case AV_TIFF_RATIONAL:
291 case AV_TIFF_SRATIONAL:
292 entry->value.rat = av_calloc(entry->count, sizeof(*entry->value.rat));
293 break;
294 case AV_TIFF_UNDEFINED:
295 case AV_TIFF_BYTE:
296 entry->value.ubytes = av_mallocz(entry->count);
297 break;
298 case AV_TIFF_SBYTE:
299 entry->value.sbytes = av_mallocz(entry->count);
300 break;
301 case AV_TIFF_STRING:
302 entry->value.str = av_mallocz(entry->count + 1);
303 break;
304 case AV_TIFF_IFD:
305 av_log(logctx, AV_LOG_WARNING24, "Bad IFD type for non-IFD tag\n");
306 return AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | ((
unsigned)('A') << 24)))
;
307 }
308 if (!entry->value.ptr)
309 return AVERROR(ENOMEM)(-(12));
310 switch (entry->type) {
311 case AV_TIFF_SHORT:
312 for (size_t i = 0; i < entry->count; i++)
313 entry->value.uint[i] = ff_tget_short(gb, le);
314 break;
315 case AV_TIFF_LONG:
316 for (size_t i = 0; i < entry->count; i++)
317 entry->value.uint[i] = ff_tget_long(gb, le);
318 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 case AV_TIFF_FLOAT:
332 for (size_t i = 0; i < entry->count; i++) {
333 av_alias32 alias = { .u32 = ff_tget_long(gb, le) };
334 entry->value.dbl[i] = alias.f32;
335 }
336 break;
337 case AV_TIFF_RATIONAL:
338 case AV_TIFF_SRATIONAL:
339 for (size_t i = 0; i < entry->count; i++) {
340 int32_t num = ff_tget_long(gb, le);
341 int32_t den = ff_tget_long(gb, le);
342 entry->value.rat[i] = av_make_q(num, den);
343 }
344 break;
345 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 av_assert0(entry->value.ubytes)do { if (!(entry->value.ubytes)) { av_log(((void*)0), 0, "Assertion %s failed at %s:%d\n"
, "entry->value.ubytes", "/root/firefox-clang/media/ffvpx/libavcodec/exif.c"
, 349); abort(); } } while (0)
;
350 bytestream2_get_buffer(gb, entry->value.ubytes, entry->count);
351 break;
352 case AV_TIFF_SBYTE:
353 av_assert0(entry->value.sbytes)do { if (!(entry->value.sbytes)) { av_log(((void*)0), 0, "Assertion %s failed at %s:%d\n"
, "entry->value.sbytes", "/root/firefox-clang/media/ffvpx/libavcodec/exif.c"
, 353); abort(); } } while (0)
;
354 bytestream2_get_buffer(gb, entry->value.sbytes, entry->count);
355 break;
356 case AV_TIFF_STRING:
357 av_assert0(entry->value.str)do { if (!(entry->value.str)) { av_log(((void*)0), 0, "Assertion %s failed at %s:%d\n"
, "entry->value.str", "/root/firefox-clang/media/ffvpx/libavcodec/exif.c"
, 357); abort(); } } while (0)
;
358 bytestream2_get_buffer(gb, entry->value.str, entry->count);
359 break;
360 }
361
362 return 0;
363}
364
365static void exif_write_values(PutByteContext *pb, int le, const AVExifEntry *entry)
366{
367 switch (entry->type) {
368 case AV_TIFF_SHORT:
369 for (size_t i = 0; i < entry->count; i++)
370 tput16(pb, le, entry->value.uint[i]);
371 break;
372 case AV_TIFF_LONG:
373 for (size_t i = 0; i < entry->count; i++)
374 tput32(pb, le, entry->value.uint[i]);
375 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 case AV_TIFF_FLOAT:
391 for (size_t i = 0; i < entry->count; i++) {
392 const av_alias32 a = { .f32 = entry->value.dbl[i] };
393 tput32(pb, le, a.u32);
394 }
395 break;
396 case AV_TIFF_RATIONAL:
397 case AV_TIFF_SRATIONAL:
398 for (size_t i = 0; i < entry->count; i++) {
399 tput32(pb, le, entry->value.rat[i].num);
400 tput32(pb, le, entry->value.rat[i].den);
401 }
402 break;
403 case AV_TIFF_UNDEFINED:
404 case AV_TIFF_BYTE:
405 bytestream2_put_buffer(pb, entry->value.ubytes, entry->count);
406 break;
407 case AV_TIFF_SBYTE:
408 bytestream2_put_buffer(pb, entry->value.sbytes, entry->count);
409 break;
410 case AV_TIFF_STRING:
411 bytestream2_put_buffer(pb, entry->value.str, entry->count);
412 break;
413 }
414}
415
416static const uint8_t aoc_header[] = { 'A', 'O', 'C', 0, };
417static const uint8_t casio_header[] = { 'Q', 'V', 'C', 0, 0, 0, };
418static const uint8_t foveon_header[] = { 'F', 'O', 'V', 'E', 'O', 'N', 0, 0, };
419static const uint8_t fuji_header[] = { 'F', 'U', 'J', 'I', };
420static const uint8_t nikon_header[] = { 'N', 'i', 'k', 'o', 'n', 0, };
421static const uint8_t olympus1_header[] = { 'O', 'L', 'Y', 'M', 'P', 0, };
422static const uint8_t olympus2_header[] = { 'O', 'L', 'Y', 'M', 'P', 'U', 'S', 0, 'I', 'I', };
423static const uint8_t panasonic_header[] = { 'P', 'a', 'n', 'a', 's', 'o', 'n', 'i', 'c', 0, 0, 0, };
424static const uint8_t sigma_header[] = { 'S', 'I', 'G', 'M', 'A', 0, 0, 0, };
425static const uint8_t sony_header[] = { 'S', 'O', 'N', 'Y', ' ', 'D', 'S', 'C', ' ', 0, 0, 0, };
426
427struct exif_makernote_data {
428 const uint8_t *header;
429 size_t header_size;
430 int result;
431};
432
433#define MAKERNOTE_STRUCT(h, r){ .header = (h), .header_size = sizeof((h)), .result = (r), } { \
434 .header = (h), \
435 .header_size = sizeof((h)), \
436 .result = (r), \
437}
438
439static const struct exif_makernote_data makernote_data[] = {
440 MAKERNOTE_STRUCT(aoc_header, 6){ .header = (aoc_header), .header_size = sizeof((aoc_header))
, .result = (6), }
,
441 MAKERNOTE_STRUCT(casio_header, -1){ .header = (casio_header), .header_size = sizeof((casio_header
)), .result = (-1), }
,
442 MAKERNOTE_STRUCT(foveon_header, 10){ .header = (foveon_header), .header_size = sizeof((foveon_header
)), .result = (10), }
,
443 MAKERNOTE_STRUCT(fuji_header, -1){ .header = (fuji_header), .header_size = sizeof((fuji_header
)), .result = (-1), }
,
444 MAKERNOTE_STRUCT(olympus1_header, 8){ .header = (olympus1_header), .header_size = sizeof((olympus1_header
)), .result = (8), }
,
445 MAKERNOTE_STRUCT(olympus2_header, -1){ .header = (olympus2_header), .header_size = sizeof((olympus2_header
)), .result = (-1), }
,
446 MAKERNOTE_STRUCT(panasonic_header, 12){ .header = (panasonic_header), .header_size = sizeof((panasonic_header
)), .result = (12), }
,
447 MAKERNOTE_STRUCT(sigma_header, 10){ .header = (sigma_header), .header_size = sizeof((sigma_header
)), .result = (10), }
,
448 MAKERNOTE_STRUCT(sony_header, 12){ .header = (sony_header), .header_size = sizeof((sony_header
)), .result = (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 */
456static int exif_get_makernote_offset(GetByteContext *gb)
457{
458 if (bytestream2_get_bytes_left(gb) < BASE_TAG_SIZE12)
459 return -1;
460
461 for (int i = 0; i < FF_ARRAY_ELEMS(makernote_data)(sizeof(makernote_data) / sizeof((makernote_data)[0])); i++) {
462 if (!memcmp(gb->buffer, makernote_data[i].header, makernote_data[i].header_size))
463 return makernote_data[i].result;
464 }
465
466 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)av_bswap32((((const union unaligned_32 *) (gb->buffer + 10
))->l))
== EXIF_MM_LONG0x4d4d002a || AV_RB32(gb->buffer + 10)av_bswap32((((const union unaligned_32 *) (gb->buffer + 10
))->l))
== EXIF_II_LONG0x49492a00)
470 return -1;
471 return 8;
472 }
473
474 return 0;
475}
476
477static int exif_parse_ifd_list(void *logctx, GetByteContext *gb, int le,
478 int depth, AVExifMetadata *ifd, int guess);
479
480static int exif_decode_tag(void *logctx, GetByteContext *gb, int le,
481 int depth, AVExifEntry *entry)
482{
483 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 if (depth > 3)
489 return AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | ((
unsigned)('A') << 24)))
;
490
491 tell = bytestream2_tell(gb);
492
493 entry->id = ff_tget_short(gb, le);
494 type = ff_tget_short(gb, le);
495 count = ff_tget_long(gb, le);
496 payload = ff_tget_long(gb, le);
497
498 av_log(logctx, AV_LOG_DEBUG48, "TIFF Tag: id: 0x%04x, type: %d, count: %u, offset: %d, "
499 "payload: %" PRIu32"u" "\n", entry->id, type, count, tell, payload);
500
501 if (!type) {
502 av_log(logctx, AV_LOG_DEBUG48, "Skipping invalid TIFF tag 0\n");
503 goto end;
504 }
505
506 /* AV_TIFF_IFD is the largest, numerically */
507 if (type > AV_TIFF_IFD || count >= INT_MAX2147483647/8U)
508 return AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | ((
unsigned)('A') << 24)))
;
509
510 is_ifd = type == AV_TIFF_IFD || ff_tis_ifd(entry->id) || entry->id == MAKERNOTE_TAG0x927c;
511
512 if (is_ifd) {
513 if (!payload)
514 goto end;
515 bytestream2_seek(gb, payload, SEEK_SET0);
516 }
517
518 if (entry->id == MAKERNOTE_TAG0x927c) {
519 makernote_offset = exif_get_makernote_offset(gb);
520 if (makernote_offset < 0)
521 is_ifd = 0;
522 }
523
524 if (is_ifd) {
525 entry->type = AV_TIFF_IFD;
526 entry->count = 1;
527 entry->ifd_offset = makernote_offset > 0 ? makernote_offset : 0;
528 if (entry->ifd_offset) {
529 entry->ifd_lead = av_malloc(entry->ifd_offset);
530 if (!entry->ifd_lead)
531 return AVERROR(ENOMEM)(-(12));
532 bytestream2_get_buffer(gb, entry->ifd_lead, entry->ifd_offset);
533 }
534 ret = exif_parse_ifd_list(logctx, gb, le, depth + 1, &entry->value.ifd, entry->id == MAKERNOTE_TAG0x927c);
535 if (ret < 0 && entry->id == MAKERNOTE_TAG0x927c) {
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_DEBUG48, "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 if (!is_ifd) {
548 entry->type = type == AV_TIFF_IFD ? AV_TIFF_UNDEFINED : type;
549 entry->count = count;
550 bytestream2_seek(gb, count * exif_sizes[type] > 4 ? payload : tell + 8, SEEK_SET0);
551 ret = exif_read_values(logctx, gb, le, entry);
552 }
553
554end:
555 bytestream2_seek(gb, tell + BASE_TAG_SIZE12, SEEK_SET0);
556
557 return ret;
558}
559
560static 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 int ret = 0;
567
568 av_log(logctx, AV_LOG_DEBUG48, "parsing IFD list at offset: %d\n", bytestream2_tell(gb));
569
570 if (bytestream2_get_bytes_left(gb) < 2) {
571 av_log(logctx, guess ? AV_LOG_DEBUG48 : AV_LOG_ERROR16,
572 "not enough bytes remaining in EXIF buffer: 2 required\n");
573 ret = AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | ((
unsigned)('A') << 24)))
;
574 goto end;
575 }
576
577 entries = ff_tget_short(gb, le);
578 if (bytestream2_get_bytes_left(gb) < entries * BASE_TAG_SIZE12) {
579 av_log(logctx, guess ? AV_LOG_DEBUG48 : AV_LOG_ERROR16,
580 "not enough bytes remaining in EXIF buffer. entries: %" PRIu32"u" "\n", entries);
581 ret = AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | ((
unsigned)('A') << 24)))
;
582 goto end;
583 }
584 if (entries > 4096) {
585 /* that is a lot of entries, probably an error */
586 av_log(logctx, guess ? AV_LOG_DEBUG48 : AV_LOG_ERROR16,
587 "too many entries: %" PRIu32"u" "\n", entries);
588 ret = AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | ((
unsigned)('A') << 24)))
;
589 goto end;
590 }
591
592 ifd->count = entries;
593 av_log(logctx, AV_LOG_DEBUG48, "entry count for IFD: %u\n", ifd->count);
594
595 /* empty IFD is technically legal but equivalent to no metadata present */
596 if (!ifd->count) {
597 ret = 0;
598 goto end;
599 }
600
601 if (av_size_mult(ifd->count, sizeof(*ifd->entries), &required_size) < 0) {
602 ret = AVERROR(ENOMEM)(-(12));
603 goto end;
604 }
605 temp = av_fast_realloc(ifd->entries, &ifd->size, required_size);
606 if (!temp) {
607 av_freep(&ifd->entries);
608 ret = AVERROR(ENOMEM)(-(12));
609 goto end;
610 }
611 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 memset(ifd->entries, 0, required_size);
616
617 for (uint32_t i = 0; i < entries; i++) {
618 ret = exif_decode_tag(logctx, gb, le, depth, &ifd->entries[i]);
619 if (ret < 0)
620 goto end;
621 }
622
623end:
624 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 ret = ff_tget_long(gb, le);
633
634 /* overflow */
635 if (ret < 0) {
636 ret = AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | ((
unsigned)('A') << 24)))
;
637 av_exif_free(ifd);
638 }
639
640 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 */
648static void exif_free_entry(AVExifEntry *entry)
649{
650 if (!entry)
651 return;
652 if (entry->type == AV_TIFF_IFD)
653 av_exif_free(&entry->value.ifd);
654 else
655 av_freep(&entry->value.ptr);
656 av_freep(&entry->ifd_lead);
657}
658
659void av_exif_free(AVExifMetadata *ifd)
660{
661 if (!ifd)
662 return;
663 if (!ifd->entries) {
664 ifd->count = 0;
665 ifd->size = 0;
666 return;
667 }
668 for (size_t i = 0; i < ifd->count; i++) {
669 AVExifEntry *entry = &ifd->entries[i];
670 exif_free_entry(entry);
671 }
672 av_freep(&ifd->entries);
673 ifd->count = 0;
674 ifd->size = 0;
675}
676
677static 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 size_t total_size = IFD_EXTRA_SIZE6;
682 for (size_t i = 0; i < ifd->count; i++) {
683 const AVExifEntry *entry = &ifd->entries[i];
684 if (entry->type == AV_TIFF_IFD) {
685 total_size += BASE_TAG_SIZE12 + exif_get_ifd_size(&entry->value.ifd) + entry->ifd_offset;
686 } else {
687 size_t payload_size = entry->count * exif_sizes[entry->type];
688 total_size += BASE_TAG_SIZE12 + (payload_size > 4 ? payload_size : 0);
689 }
690 }
691 return total_size;
692}
693
694static int exif_write_ifd(void *logctx, PutByteContext *pb, int le, int depth, const AVExifMetadata *ifd)
695{
696 int offset, ret, tell, tell2;
697 tell = bytestream2_tell_p(pb);
698 tput16(pb, le, ifd->count);
699 offset = tell + IFD_EXTRA_SIZE6 + BASE_TAG_SIZE12 * (uint32_t) ifd->count;
700 av_log(logctx, AV_LOG_DEBUG48, "writing IFD with %u entries and initial offset %d\n", ifd->count, offset);
701 for (size_t i = 0; i < ifd->count; i++) {
60
Loop condition is true. Entering loop body
702 const AVExifEntry *entry = &ifd->entries[i];
703 av_log(logctx, AV_LOG_DEBUG48, "writing TIFF entry: id: 0x%04" PRIx16"hx" ", type: %d, count: %"
704 PRIu32"u" ", offset: %d, offset value: %d\n",
705 entry->id, entry->type, entry->count,
706 bytestream2_tell_p(pb), offset);
707 tput16(pb, le, entry->id);
708 if (entry->id == MAKERNOTE_TAG0x927c && entry->type == AV_TIFF_IFD) {
61
Assuming field 'id' is not equal to MAKERNOTE_TAG
709 size_t ifd_size = exif_get_ifd_size(&entry->value.ifd);
710 tput16(pb, le, AV_TIFF_UNDEFINED);
711 tput32(pb, le, ifd_size);
712 } else {
713 tput16(pb, le, entry->type);
714 tput32(pb, le, entry->count);
715 }
716 if (entry->type == AV_TIFF_IFD) {
62
Assuming field 'type' is equal to AV_TIFF_IFD
63
Taking true branch
717 tput32(pb, le, offset);
718 tell2 = bytestream2_tell_p(pb);
719 bytestream2_seek_p(pb, offset, SEEK_SET0);
720 if (entry->ifd_offset)
64
Assuming field 'ifd_offset' is not equal to 0
65
Taking true branch
721 bytestream2_put_buffer(pb, entry->ifd_lead, entry->ifd_offset);
66
Passing null pointer value via 2nd parameter 'src'
67
Calling 'bytestream2_put_buffer'
722 ret = exif_write_ifd(logctx, pb, le, depth + 1, &entry->value.ifd);
723 if (ret < 0)
724 return ret;
725 offset += ret + entry->ifd_offset;
726 bytestream2_seek_p(pb, tell2, SEEK_SET0);
727 } else {
728 size_t payload_size = entry->count * exif_sizes[entry->type];
729 if (payload_size > 4) {
730 tput32(pb, le, offset);
731 tell2 = bytestream2_tell_p(pb);
732 bytestream2_seek_p(pb, offset, SEEK_SET0);
733 exif_write_values(pb, le, entry);
734 offset += payload_size;
735 bytestream2_seek_p(pb, tell2, SEEK_SET0);
736 } else {
737 /* zero uninitialized excess payload values */
738 AV_WN32(pb->buffer, 0)((((union unaligned_32 *) (pb->buffer))->l) = (0));
739 exif_write_values(pb, le, entry);
740 bytestream2_seek_p(pb, 4 - payload_size, SEEK_CUR1);
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 tput32(pb, le, depth ? offset : 0);
750 return offset - tell;
751}
752
753int av_exif_write(void *logctx, const AVExifMetadata *ifd, AVBufferRef **buffer, enum AVExifHeaderMode header_mode)
754{
755 AVBufferRef *buf = NULL((void*)0);
756 size_t size, headsize = 8;
757 PutByteContext pb;
758 int ret = 0, off = 0, next;
759 AVExifMetadata *ifd_new = NULL((void*)0);
760 AVExifMetadata extra_ifds[16] = { 0 };
761
762 int le = 1;
763
764 if (*buffer) {
11
Taking false branch
765 ret = AVERROR(EINVAL)(-(22));
766 goto end;
767 }
768
769 size = exif_get_ifd_size(ifd);
770 switch (header_mode) {
12
'Default' branch taken. Execution continues on line 787
771 case AV_EXIF_EXIF00:
772 off = 6;
773 break;
774 case AV_EXIF_T_OFF:
775 off = 4;
776 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 ret = av_buffer_realloc(&buf, size + off + headsize);
788 if (ret < 0)
13
Assuming 'ret' is >= 0
14
Taking false branch
789 goto end;
790
791 if (header_mode
14.1
'header_mode' is not equal to AV_EXIF_EXIF00
14.1
'header_mode' is not equal to AV_EXIF_EXIF00
== AV_EXIF_EXIF00) {
15
Taking false branch
792 AV_WL32(buf->data, MKTAG('E','x','i','f'))((((union unaligned_32 *) (buf->data))->l) = ((('E') | (
('x') << 8) | (('i') << 16) | ((unsigned)('f') <<
24))))
;
793 AV_WN16(buf->data + 4, 0)((((union unaligned_16 *) (buf->data + 4))->l) = (0));
794 } else if (header_mode
15.1
'header_mode' is not equal to AV_EXIF_T_OFF
15.1
'header_mode' is not equal to AV_EXIF_T_OFF
== AV_EXIF_T_OFF) {
16
Taking false branch
795 AV_WN32(buf->data, 0)((((union unaligned_32 *) (buf->data))->l) = (0));
796 }
797
798 bytestream2_init_writer(&pb, buf->data + off, buf->size - off);
17
Calling 'bytestream2_init_writer'
22
Returning from 'bytestream2_init_writer'
799
800 if (header_mode
22.1
'header_mode' is not equal to AV_EXIF_ASSUME_BE
22.1
'header_mode' is not equal to AV_EXIF_ASSUME_BE
!= AV_EXIF_ASSUME_BE && header_mode
22.2
'header_mode' is not equal to AV_EXIF_ASSUME_LE
22.2
'header_mode' is not equal to AV_EXIF_ASSUME_LE
!= AV_EXIF_ASSUME_LE) {
23
Taking true branch
801 /* these constants are be32 in both cases */
802 /* le == 1 always in this case */
803 bytestream2_put_be32(&pb, EXIF_II_LONG0x49492a00);
24
Calling 'bytestream2_put_be32'
27
Returning from 'bytestream2_put_be32'
804 tput32(&pb, le, 8);
805 }
806
807 int extras = 0;
808 for (int i = 0; i < FF_ARRAY_ELEMS(extra_ifds)(sizeof(extra_ifds) / sizeof((extra_ifds)[0])); i++) {
28
Loop condition is true. Entering loop body
809 AVExifEntry *extra_entry = NULL((void*)0);
810 uint16_t extra_tag = 0xFFFCu - i;
811 ret = av_exif_get_entry(logctx, (AVExifMetadata *) ifd, extra_tag, 0, &extra_entry);
812 if (ret
28.1
'ret' is >= 0
28.1
'ret' is >= 0
< 0)
29
Taking false branch
813 break;
814 if (!ret
29.1
'ret' is 1
29.1
'ret' is 1
)
30
Taking false branch
815 continue;
816 av_log(logctx, AV_LOG_DEBUG48, "found extra IFD tag: %04x\n", extra_tag);
817 if (!ifd_new
30.1
'ifd_new' is null
30.1
'ifd_new' is null
) {
31
Taking true branch
818 ifd_new = av_exif_clone_ifd(ifd);
32
Calling 'av_exif_clone_ifd'
54
Returning from 'av_exif_clone_ifd'
819 if (!ifd_new
54.1
'ifd_new' is non-null
54.1
'ifd_new' is non-null
)
55
Taking false branch
820 break;
821 ifd = ifd_new;
822 }
823 /* calling remove_entry will call av_exif_free on the original */
824 AVExifMetadata *cloned = av_exif_clone_ifd(&extra_entry->value.ifd);
825 if (!cloned
55.1
'cloned' is null
55.1
'cloned' is null
)
56
Taking true branch
826 break;
827 extra_ifds[extras++] = *cloned;
828 /* don't use av_exif_free here, we want to preserve internals */
829 av_free(cloned);
830 ret = av_exif_remove_entry(logctx, ifd_new, extra_tag, 0);
831 if (ret < 0)
832 break;
833 }
834
835 if (ret
57.1
'ret' is >= 0
57.1
'ret' is >= 0
< 0) {
57
Execution continues on line 835
58
Taking false branch
836 av_log(logctx, AV_LOG_ERROR16, "error popping additional IFD: %s\n", av_err2str(ret)av_make_error_string((char[64]){0}, 64, ret));
837 goto end;
838 }
839
840 next = bytestream2_tell_p(&pb);
841 ret = exif_write_ifd(logctx, &pb, le, 0, ifd);
59
Calling 'exif_write_ifd'
842 if (ret < 0) {
843 av_log(logctx, AV_LOG_ERROR16, "error writing EXIF data: %s\n", av_err2str(ret)av_make_error_string((char[64]){0}, 64, ret));
844 goto end;
845 }
846 next += ret;
847
848 for (int i = 0; i < extras; i++) {
849 av_log(logctx, AV_LOG_DEBUG48, "writing additional ifd at: %d\n", next);
850 /* exif_write_ifd always writes 0 i.e. last ifd so we overwrite that here */
851 bytestream2_seek_p(&pb, -4, SEEK_CUR1);
852 tput32(&pb, le, next);
853 bytestream2_seek_p(&pb, next, SEEK_SET0);
854 ret = exif_write_ifd(logctx, &pb, le, 0, &extra_ifds[i]);
855 if (ret < 0) {
856 av_log(logctx, AV_LOG_ERROR16, "error writing additional IFD: %s\n", av_err2str(ret)av_make_error_string((char[64]){0}, 64, ret));
857 goto end;
858 }
859 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 ret = av_buffer_realloc(&buf, buf->size - BASE_TAG_SIZE12 * extras);
865 if (ret < 0)
866 goto end;
867
868 *buffer = buf;
869 ret = 0;
870
871end:
872 av_exif_free(ifd_new);
873 av_freep(&ifd_new);
874 for (int i = 0; i < FF_ARRAY_ELEMS(extra_ifds)(sizeof(extra_ifds) / sizeof((extra_ifds)[0])); i++)
875 av_exif_free(&extra_ifds[i]);
876 if (ret < 0)
877 av_buffer_unref(&buf);
878
879 return ret;
880}
881
882int 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 if (size > INT_MAX2147483647)
888 return AVERROR(EINVAL)(-(22));
889 size_t off = 0;
890 switch (header_mode) {
891 case AV_EXIF_EXIF00:
892 if (size < 6)
893 return AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | ((
unsigned)('A') << 24)))
;
894 off = 6;
895 av_fallthrough__attribute__((fallthrough));
896 case AV_EXIF_T_OFF:
897 if (size < 4)
898 return AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | ((
unsigned)('A') << 24)))
;
899 if (!off)
900 off = AV_RB32(buf)av_bswap32((((const union unaligned_32 *) (buf))->l)) + 4;
901 av_fallthrough__attribute__((fallthrough));
902 case AV_EXIF_TIFF_HEADER: {
903 int ifd_offset;
904 if (size <= off)
905 return AVERROR_INVALIDDATA(-(int)(('I') | (('N') << 8) | (('D') << 16) | ((
unsigned)('A') << 24)))
;
906 bytestream2_init(&gbytes, buf + off, size - off);
907 // read TIFF header
908 ret = ff_tdecode_header(&gbytes, &le, &ifd_offset);
909 if (ret < 0) {
910 av_log(logctx, AV_LOG_ERROR16, "invalid TIFF header in EXIF data: %s\n", av_err2str(ret)av_make_error_string((char[64]){0}, 64, ret));
911 return ret;
912 }
913 bytestream2_seek(&gbytes, ifd_offset, SEEK_SET0);
914 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)(-(22));
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 ret = exif_parse_ifd_list(logctx, &gbytes, le, 0, ifd, 0);
933 if (ret < 0) {
934 av_log(logctx, AV_LOG_ERROR16, "error decoding EXIF data: %s\n", av_err2str(ret)av_make_error_string((char[64]){0}, 64, ret));
935 return ret;
936 }
937 if (!ret)
938 goto finish;
939 int next = ret;
940 bytestream2_seek(&gbytes, next, SEEK_SET0);
941
942 /* cap at 16 extra IFDs for sanity/parse security */
943 for (int extra_tag = 0xFFFCu; extra_tag > 0xFFECu; extra_tag--) {
944 AVExifMetadata extra_ifd = { 0 };
945 ret = exif_parse_ifd_list(logctx, &gbytes, le, 0, &extra_ifd, 1);
946 if (ret < 0) {
947 av_exif_free(&extra_ifd);
948 break;
949 }
950 next = ret;
951 av_log(logctx, AV_LOG_DEBUG48, "found extra IFD: %04x with next=%d\n", extra_tag, ret);
952 bytestream2_seek(&gbytes, next, SEEK_SET0);
953 ret = av_exif_set_entry(logctx, ifd, extra_tag, AV_TIFF_IFD, 1, NULL((void*)0), 0, &extra_ifd);
954 av_exif_free(&extra_ifd);
955 if (ret < 0 || !next || bytestream2_get_bytes_left(&gbytes) <= 0)
956 break;
957 }
958
959finish:
960 return bytestream2_tell(&gbytes) + off;
961}
962
963#define COLUMN_SEP(i, c)((i) ? ((i) % (c) ? ", " : "\n") : "") ((i) ? ((i) % (c) ? ", " : "\n") : "")
964
965static int exif_ifd_to_dict(void *logctx, const char *prefix, const AVExifMetadata *ifd, AVDictionary **metadata)
966{
967 AVBPrint bp;
968 int ret = 0;
969 char *key = NULL((void*)0);
970 char *value = NULL((void*)0);
971
972 if (!prefix)
973 prefix = "";
974
975 for (uint16_t i = 0; i < ifd->count; i++) {
976 const AVExifEntry *entry = &ifd->entries[i];
977 const char *name = av_exif_get_tag_name(entry->id);
978 av_bprint_init(&bp, entry->count * 10, AV_BPRINT_SIZE_UNLIMITED((unsigned)-1));
979 if (*prefix)
980 av_bprintf(&bp, "%s/", prefix);
981 if (name)
982 av_bprintf(&bp, "%s", name);
983 else
984 av_bprintf(&bp, "0x%04X", entry->id);
985 ret = av_bprint_finalize(&bp, &key);
986 if (ret < 0)
987 goto end;
988 av_bprint_init(&bp, entry->count * 10, AV_BPRINT_SIZE_UNLIMITED((unsigned)-1));
989 switch (entry->type) {
990 case AV_TIFF_IFD:
991 ret = exif_ifd_to_dict(logctx, key, &entry->value.ifd, metadata);
992 if (ret < 0)
993 goto end;
994 break;
995 case AV_TIFF_SHORT:
996 case AV_TIFF_LONG:
997 for (uint32_t j = 0; j < entry->count; j++)
998 av_bprintf(&bp, "%s%7" PRIu32"u", COLUMN_SEP(j, 8)((j) ? ((j) % (8) ? ", " : "\n") : ""), (uint32_t)entry->value.uint[j]);
999 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"d", COLUMN_SEP(j, 8)((j) ? ((j) % (8) ? ", " : "\n") : ""), (int32_t)entry->value.sint[j]);
1004 break;
1005 case AV_TIFF_RATIONAL:
1006 case AV_TIFF_SRATIONAL:
1007 for (uint32_t j = 0; j < entry->count; j++)
1008 av_bprintf(&bp, "%s%7i:%-7i", COLUMN_SEP(j, 4)((j) ? ((j) % (4) ? ", " : "\n") : ""), entry->value.rat[j].num, entry->value.rat[j].den);
1009 break;
1010 case AV_TIFF_DOUBLE:
1011 case AV_TIFF_FLOAT:
1012 for (uint32_t j = 0; j < entry->count; j++)
1013 av_bprintf(&bp, "%s%.15g", COLUMN_SEP(j, 4)((j) ? ((j) % (4) ? ", " : "\n") : ""), entry->value.dbl[j]);
1014 break;
1015 case AV_TIFF_STRING:
1016 av_bprintf(&bp, "%s", entry->value.str);
1017 break;
1018 case AV_TIFF_UNDEFINED:
1019 case AV_TIFF_BYTE:
1020 for (uint32_t j = 0; j < entry->count; j++)
1021 av_bprintf(&bp, "%s%3i", COLUMN_SEP(j, 16)((j) ? ((j) % (16) ? ", " : "\n") : ""), entry->value.ubytes[j]);
1022 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)((j) ? ((j) % (16) ? ", " : "\n") : ""), entry->value.sbytes[j]);
1026 break;
1027 }
1028 if (entry->type != AV_TIFF_IFD) {
1029 if (!av_bprint_is_complete(&bp)) {
1030 av_bprint_finalize(&bp, NULL((void*)0));
1031 ret = AVERROR(ENOMEM)(-(12));
1032 goto end;
1033 }
1034 ret = av_bprint_finalize(&bp, &value);
1035 if (ret < 0)
1036 goto end;
1037 ret = av_dict_set(metadata, key, value, AV_DICT_DONT_STRDUP_KEY4 | AV_DICT_DONT_STRDUP_VAL8);
1038 key = NULL((void*)0);
1039 value = NULL((void*)0);
1040 if (ret < 0)
1041 goto end;
1042 } else {
1043 av_freep(&key);
1044 }
1045 }
1046
1047end:
1048 av_freep(&key);
1049 av_freep(&value);
1050 return ret;
1051}
1052
1053int av_exif_ifd_to_dict(void *logctx, const AVExifMetadata *ifd, AVDictionary **metadata)
1054{
1055 return exif_ifd_to_dict(logctx, "", ifd, metadata);
1056}
1057
1058#define EXIF_COPY(fname, srcname)do { size_t sz; if (av_size_mult(src->count, sizeof(*(fname
)), &sz) < 0) { ret = (-(12)); goto end; } (fname) = av_memdup
((srcname), sz); if (!(fname)) { ret = (-(12)); goto end; } }
while (0)
do { \
1059 size_t sz; \
1060 if (av_size_mult(src->count, sizeof(*(fname)), &sz) < 0) { \
1061 ret = AVERROR(ENOMEM)(-(12)); \
1062 goto end; \
1063 } \
1064 (fname) = av_memdup((srcname), sz); \
1065 if (!(fname)) { \
1066 ret = AVERROR(ENOMEM)(-(12)); \
1067 goto end; \
1068 } \
1069} while (0)
1070
1071static int exif_clone_entry(AVExifEntry *dst, const AVExifEntry *src)
1072{
1073 int ret = 0;
1074
1075 memset(dst, 0, sizeof(*dst));
1076
1077 dst->count = src->count;
1078 dst->id = src->id;
1079 dst->type = src->type;
1080
1081 dst->ifd_offset = src->ifd_offset;
1082 if (src->ifd_lead) {
43
Assuming field 'ifd_lead' is null
44
Taking false branch
1083 dst->ifd_lead = av_memdup(src->ifd_lead, src->ifd_offset);
1084 if (!dst->ifd_lead) {
1085 ret = AVERROR(ENOMEM)(-(12));
1086 goto end;
1087 }
1088 } else {
1089 dst->ifd_lead = NULL((void*)0);
45
Null pointer value stored to field 'ifd_lead'
1090 }
1091
1092 switch(src->type) {
46
Control jumps to 'case AV_TIFF_STRING:' at line 1126
1093 case AV_TIFF_IFD: {
1094 AVExifMetadata *cloned = av_exif_clone_ifd(&src->value.ifd);
1095 if (!cloned) {
1096 ret = AVERROR(ENOMEM)(-(12));
1097 goto end;
1098 }
1099 dst->value.ifd = *cloned;
1100 av_freep(&cloned);
1101 break;
1102 }
1103 case AV_TIFF_SHORT:
1104 case AV_TIFF_LONG:
1105 EXIF_COPY(dst->value.uint, src->value.uint)do { size_t sz; if (av_size_mult(src->count, sizeof(*(dst->
value.uint)), &sz) < 0) { ret = (-(12)); goto end; } (
dst->value.uint) = av_memdup((src->value.uint), sz); if
(!(dst->value.uint)) { ret = (-(12)); goto end; } } while
(0)
;
1106 break;
1107 case AV_TIFF_SLONG:
1108 case AV_TIFF_SSHORT:
1109 EXIF_COPY(dst->value.sint, src->value.sint)do { size_t sz; if (av_size_mult(src->count, sizeof(*(dst->
value.sint)), &sz) < 0) { ret = (-(12)); goto end; } (
dst->value.sint) = av_memdup((src->value.sint), sz); if
(!(dst->value.sint)) { ret = (-(12)); goto end; } } while
(0)
;
1110 break;
1111 case AV_TIFF_RATIONAL:
1112 case AV_TIFF_SRATIONAL:
1113 EXIF_COPY(dst->value.rat, src->value.rat)do { size_t sz; if (av_size_mult(src->count, sizeof(*(dst->
value.rat)), &sz) < 0) { ret = (-(12)); goto end; } (dst
->value.rat) = av_memdup((src->value.rat), sz); if (!(dst
->value.rat)) { ret = (-(12)); goto end; } } while (0)
;
1114 break;
1115 case AV_TIFF_DOUBLE:
1116 case AV_TIFF_FLOAT:
1117 EXIF_COPY(dst->value.dbl, src->value.dbl)do { size_t sz; if (av_size_mult(src->count, sizeof(*(dst->
value.dbl)), &sz) < 0) { ret = (-(12)); goto end; } (dst
->value.dbl) = av_memdup((src->value.dbl), sz); if (!(dst
->value.dbl)) { ret = (-(12)); goto end; } } while (0)
;
1118 break;
1119 case AV_TIFF_BYTE:
1120 case AV_TIFF_UNDEFINED:
1121 EXIF_COPY(dst->value.ubytes, src->value.ubytes)do { size_t sz; if (av_size_mult(src->count, sizeof(*(dst->
value.ubytes)), &sz) < 0) { ret = (-(12)); goto end; }
(dst->value.ubytes) = av_memdup((src->value.ubytes), sz
); if (!(dst->value.ubytes)) { ret = (-(12)); goto end; } }
while (0)
;
1122 break;
1123 case AV_TIFF_SBYTE:
1124 EXIF_COPY(dst->value.sbytes, src->value.sbytes)do { size_t sz; if (av_size_mult(src->count, sizeof(*(dst->
value.sbytes)), &sz) < 0) { ret = (-(12)); goto end; }
(dst->value.sbytes) = av_memdup((src->value.sbytes), sz
); if (!(dst->value.sbytes)) { ret = (-(12)); goto end; } }
while (0)
;
1125 break;
1126 case AV_TIFF_STRING:
1127 dst->value.str = av_memdup(src->value.str, src->count+1);
1128 if (!dst->value.str) {
47
Assuming field 'str' is non-null
48
Taking false branch
1129 ret = AVERROR(ENOMEM)(-(12));
1130 goto end;
1131 }
1132 break;
49
Execution continues on line 1135
1133 }
1134
1135 return 0;
1136
1137end:
1138 av_freep(&dst->ifd_lead);
1139 if (src->type == AV_TIFF_IFD)
1140 av_exif_free(&dst->value.ifd);
1141 else
1142 av_freep(&dst->value.ptr);
1143 memset(dst, 0, sizeof(*dst));
1144
1145 return ret;
1146}
1147
1148static int exif_get_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, int depth, AVExifEntry **value)
1149{
1150 int offset = 1;
1151
1152 if (!ifd || ifd->count && !ifd->entries || !value)
1153 return AVERROR(EINVAL)(-(22));
1154
1155 for (size_t i = 0; i < ifd->count; i++) {
1156 if (ifd->entries[i].id == id) {
1157 *value = &ifd->entries[i];
1158 return i + offset;
1159 }
1160 if (ifd->entries[i].type == AV_TIFF_IFD) {
1161 if (depth < 3) {
1162 int ret = exif_get_entry(logctx, &ifd->entries[i].value.ifd, id, depth + 1, value);
1163 if (ret)
1164 return ret < 0 ? ret : ret + offset;
1165 }
1166 offset += ifd->entries[i].value.ifd.count;
1167 }
1168 }
1169
1170 return 0;
1171}
1172
1173int av_exif_get_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, int flags, AVExifEntry **value)
1174{
1175 return exif_get_entry(logctx, ifd, id, (flags & AV_EXIF_FLAG_RECURSIVE(1 << 0)) ? 0 : INT_MAX2147483647, value);
1176}
1177
1178int av_exif_set_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, enum AVTiffDataType type,
1179 uint32_t count, const uint8_t *ifd_lead, uint32_t ifd_offset, const void *value)
1180{
1181 void *temp;
1182 int ret, offset;
1183 AVExifEntry *entry = NULL((void*)0);
1184 AVExifEntry src = { 0 };
1185
1186 if (!ifd || ifd->count && !ifd->entries
1187 || ifd_lead && !ifd_offset || !ifd_lead && ifd_offset
1188 || !value || ifd->count == 0xFFFFu)
1189 return AVERROR(EINVAL)(-(22));
1190
1191 ret = av_exif_get_entry(logctx, ifd, id, 0, &entry);
1192 if (ret < 0)
1193 return ret;
1194 offset = ret;
1195
1196 if (entry) {
1197 exif_free_entry(entry);
1198 } else {
1199 size_t required_size;
1200 ret = av_size_mult(ifd->count + 1, sizeof(*ifd->entries), &required_size);
1201 if (ret < 0)
1202 return AVERROR(ENOMEM)(-(12));
1203 temp = av_fast_realloc(ifd->entries, &ifd->size, required_size);
1204 if (!temp)
1205 return AVERROR(ENOMEM)(-(12));
1206 ifd->entries = temp;
1207 entry = &ifd->entries[ifd->count++];
1208 }
1209
1210 src.count = count;
1211 src.id = id;
1212 src.type = type;
1213 src.ifd_lead = (uint8_t *) ifd_lead;
1214 src.ifd_offset = ifd_offset;
1215 if (type == AV_TIFF_IFD)
1216 src.value.ifd = * (const AVExifMetadata *) value;
1217 else
1218 src.value.ptr = (void *) value;
1219
1220 ret = exif_clone_entry(entry, &src);
1221
1222 if (ret < 0) {
1223 /* offset is the actual offset + 1 */
1224 if (offset) {
1225 size_t remaining = ifd->count - offset;
1226 /* pop the entry off the IFD by shifting everything to the left */
1227 memmove(&ifd->entries[offset - 1], &ifd->entries[offset], sizeof(*ifd->entries) * remaining);
1228 }
1229 ifd->count--;
1230 }
1231
1232 return ret;
1233}
1234
1235static int exif_remove_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, int depth)
1236{
1237 int32_t index = -1;
1238 int ret = 0;
1239
1240 if (!ifd || ifd->count && !ifd->entries)
1241 return AVERROR(EINVAL)(-(22));
1242
1243 for (size_t i = 0; i < ifd->count; i++) {
1244 if (ifd->entries[i].id == id) {
1245 index = i;
1246 break;
1247 }
1248 if (ifd->entries[i].type == AV_TIFF_IFD && depth < 3) {
1249 ret = exif_remove_entry(logctx, &ifd->entries[i].value.ifd, id, depth + 1);
1250 if (ret)
1251 return ret;
1252 }
1253 }
1254
1255 if (index < 0)
1256 return 0;
1257 exif_free_entry(&ifd->entries[index]);
1258
1259 if (index == --ifd->count) {
1260 if (!index) {
1261 av_freep(&ifd->entries);
1262 ifd->size = 0;
1263 }
1264 return 1;
1265 }
1266
1267 memmove(&ifd->entries[index], &ifd->entries[index + 1], (ifd->count - index) * sizeof(*ifd->entries));
1268
1269 return 1 + (ifd->count - index);
1270}
1271
1272int av_exif_remove_entry(void *logctx, AVExifMetadata *ifd, uint16_t id, int flags)
1273{
1274 return exif_remove_entry(logctx, ifd, id, (flags & AV_EXIF_FLAG_RECURSIVE(1 << 0)) ? 0 : INT_MAX2147483647);
1275}
1276
1277AVExifMetadata *av_exif_clone_ifd(const AVExifMetadata *ifd)
1278{
1279 AVExifMetadata *ret = av_mallocz(sizeof(*ret));
1280 if (!ret)
33
Assuming 'ret' is non-null
34
Taking false branch
1281 return NULL((void*)0);
1282
1283 ret->count = ifd->count;
1284 if (ret->count
34.1
Field 'count' is 1
34.1
Field 'count' is 1
) {
35
Taking true branch
1285 size_t required_size;
1286 if (av_size_mult(ret->count, sizeof(*ret->entries), &required_size) < 0)
36
Assuming the condition is false
37
Taking false branch
1287 goto fail;
1288 av_fast_mallocz(&ret->entries, &ret->size, required_size);
1289 if (!ret->entries)
38
Assuming field 'entries' is non-null
39
Taking false branch
1290 goto fail;
1291 }
1292
1293 for (size_t i = 0; i < ret->count; i++) {
40
Assuming 'i' is < field 'count'
41
Loop condition is true. Entering loop body
52
Assuming 'i' is >= field 'count'
53
Loop condition is false. Execution continues on line 1301
1294 const AVExifEntry *entry = &ifd->entries[i];
1295 AVExifEntry *ret_entry = &ret->entries[i];
1296 int status = exif_clone_entry(ret_entry, entry);
42
Calling 'exif_clone_entry'
50
Returning from 'exif_clone_entry'
1297 if (status
50.1
'status' is >= 0
50.1
'status' is >= 0
< 0)
51
Taking false branch
1298 goto fail;
1299 }
1300
1301 return ret;
1302
1303fail:
1304 av_exif_free(ret);
1305 av_free(ret);
1306 return NULL((void*)0);
1307}
1308
1309static const int rotation_lut[2][4] = {
1310 {1, 8, 3, 6}, {4, 7, 2, 5},
1311};
1312
1313int av_exif_matrix_to_orientation(const int32_t *matrix)
1314{
1315 double rotation = av_display_rotation_get(matrix);
1316 // determinant
1317 int vflip = ((int64_t)matrix[0] * (int64_t)matrix[4]
1318 - (int64_t)matrix[1] * (int64_t)matrix[3]) < 0;
1319 if (!isfinite(rotation)__builtin_isfinite (rotation))
1320 return 0;
1321 int rot = (int)(rotation + 0.5);
1322 rot = (((rot % 360) + 360) % 360) / 90;
1323 return rotation_lut[vflip][rot];
1324}
1325
1326int av_exif_orientation_to_matrix(int32_t *matrix, int orientation)
1327{
1328 switch (orientation) {
1329 case 1:
1330 av_display_rotation_set(matrix, 0.0);
1331 break;
1332 case 2:
1333 av_display_rotation_set(matrix, 0.0);
1334 av_display_matrix_flip(matrix, 1, 0);
1335 break;
1336 case 3:
1337 av_display_rotation_set(matrix, 180.0);
1338 break;
1339 case 4:
1340 av_display_rotation_set(matrix, 180.0);
1341 av_display_matrix_flip(matrix, 1, 0);
1342 break;
1343 case 5:
1344 av_display_rotation_set(matrix, 90.0);
1345 av_display_matrix_flip(matrix, 1, 0);
1346 break;
1347 case 6:
1348 av_display_rotation_set(matrix, 90.0);
1349 break;
1350 case 7:
1351 av_display_rotation_set(matrix, -90.0);
1352 av_display_matrix_flip(matrix, 1, 0);
1353 break;
1354 case 8:
1355 av_display_rotation_set(matrix, -90.0);
1356 break;
1357 default:
1358 return AVERROR(EINVAL)(-(22));
1359 }
1360
1361 return 0;
1362}
1363
1364int ff_exif_sanitize_ifd(void *logctx, const AVFrame *frame, AVExifMetadata *ifd)
1365{
1366 int ret = 0;
1367 AVFrameSideData *sd_orient = NULL((void*)0);
1368 AVExifEntry *or = NULL((void*)0);
1369 AVExifEntry *iw = NULL((void*)0);
1370 AVExifEntry *ih = NULL((void*)0);
1371 AVExifEntry *pw = NULL((void*)0);
1372 AVExifEntry *ph = NULL((void*)0);
1373 uint64_t orientation = 1;
1374 uint64_t w = frame->width;
1375 uint64_t h = frame->height;
1376 int rewrite = 0;
1377
1378 sd_orient = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX);
1379
1380 if (sd_orient)
1381 orientation = av_exif_matrix_to_orientation((int32_t *) sd_orient->data);
1382 if (!orientation) {
1383 av_log(logctx, AV_LOG_WARNING24, "display matrix is singular\n");
1384 orientation = 1;
1385 }
1386 if (orientation != 1)
1387 av_log(logctx, AV_LOG_DEBUG48, "matrix contains nontrivial EXIF orientation: %" PRIu64"l" "u" "\n", orientation);
1388
1389 for (size_t i = 0; i < ifd->count; i++) {
1390 AVExifEntry *entry = &ifd->entries[i];
1391 if (entry->id == ORIENTATION_TAG0x112 && entry->count > 0 && entry->type == AV_TIFF_SHORT) {
1392 or = entry;
1393 continue;
1394 }
1395 if (entry->id == IMAGE_WIDTH_TAG0x100 && entry->count > 0 && entry->type == AV_TIFF_LONG) {
1396 iw = entry;
1397 continue;
1398 }
1399 if (entry->id == IMAGE_LENGTH_TAG0x101 && entry->count > 0 && entry->type == AV_TIFF_LONG) {
1400 ih = entry;
1401 continue;
1402 }
1403 if (entry->id == EXIFIFD_TAG0x8769 && entry->type == AV_TIFF_IFD) {
1404 AVExifMetadata *exif = &entry->value.ifd;
1405 for (size_t j = 0; j < exif->count; j++) {
1406 AVExifEntry *exifentry = &exif->entries[j];
1407 if (exifentry->id == PIXEL_X_TAG0xa002 && exifentry->count > 0 && exifentry->type == AV_TIFF_SHORT) {
1408 pw = exifentry;
1409 continue;
1410 }
1411 if (exifentry->id == PIXEL_Y_TAG0xa003 && exifentry->count > 0 && exifentry->type == AV_TIFF_SHORT) {
1412 ph = exifentry;
1413 continue;
1414 }
1415 }
1416 }
1417 }
1418
1419 if (or && or->value.uint[0] != orientation) {
1420 rewrite = 1;
1421 or->value.uint[0] = orientation;
1422 }
1423 if (iw && iw->value.uint[0] != w) {
1424 rewrite = 1;
1425 iw->value.uint[0] = w;
1426 }
1427 if (ih && ih->value.uint[0] != h) {
1428 rewrite = 1;
1429 ih->value.uint[0] = h;
1430 }
1431 if (pw && pw->value.uint[0] != w) {
1432 rewrite = 1;
1433 pw->value.uint[0] = w;
1434 }
1435 if (ph && ph->value.uint[0] != h) {
1436 rewrite = 1;
1437 ph->value.uint[0] = h;
1438 }
1439 if (!or && orientation != 1) {
1440 rewrite = 1;
1441 ret = av_exif_set_entry(logctx, ifd, ORIENTATION_TAG0x112, AV_TIFF_SHORT, 1, NULL((void*)0), 0, &orientation);
1442 if (ret < 0)
1443 goto end;
1444 }
1445 if (!iw && w) {
1446 rewrite = 1;
1447 ret = av_exif_set_entry(logctx, ifd, IMAGE_WIDTH_TAG0x100, AV_TIFF_LONG, 1, NULL((void*)0), 0, &w);
1448 if (ret < 0)
1449 goto end;
1450 }
1451 if (!ih && h) {
1452 rewrite = 1;
1453 ret = av_exif_set_entry(logctx, ifd, IMAGE_LENGTH_TAG0x101, AV_TIFF_LONG, 1, NULL((void*)0), 0, &h);
1454 if (ret < 0)
1455 goto end;
1456 }
1457 if (!pw && w && w <= 0xFFFFu || !ph && h && h <= 0xFFFFu) {
1458 AVExifMetadata *exif;
1459 AVExifEntry *exif_entry;
1460 int exif_found = av_exif_get_entry(logctx, ifd, EXIFIFD_TAG0x8769, 0, &exif_entry);
1461 rewrite = 1;
1462 if (exif_found < 0)
1463 goto end;
1464 if (exif_found > 0) {
1465 exif = &exif_entry->value.ifd;
1466 } else {
1467 AVExifMetadata exif_new = { 0 };
1468 ret = av_exif_set_entry(logctx, ifd, EXIFIFD_TAG0x8769, AV_TIFF_IFD, 1, NULL((void*)0), 0, &exif_new);
1469 if (ret < 0) {
1470 av_exif_free(&exif_new);
1471 goto end;
1472 }
1473 exif = &ifd->entries[ifd->count - 1].value.ifd;
1474 }
1475 if (!pw && w && w <= 0xFFFFu) {
1476 ret = av_exif_set_entry(logctx, exif, PIXEL_X_TAG0xa002, AV_TIFF_SHORT, 1, NULL((void*)0), 0, &w);
1477 if (ret < 0)
1478 goto end;
1479 }
1480 if (!ph && h && h <= 0xFFFFu) {
1481 ret = av_exif_set_entry(logctx, exif, PIXEL_Y_TAG0xa003, AV_TIFF_SHORT, 1, NULL((void*)0), 0, &h);
1482 if (ret < 0)
1483 goto end;
1484 }
1485 }
1486
1487 return rewrite;
1488
1489end:
1490 return ret;
1491}
1492
1493int ff_exif_get_buffer(void *logctx, const AVFrame *frame, AVBufferRef **buffer_ptr, enum AVExifHeaderMode header_mode)
1494{
1495 AVFrameSideData *sd_exif = NULL((void*)0);
1496 AVBufferRef *buffer = NULL((void*)0);
1497 AVExifMetadata ifd = { 0 };
1498 int ret = 0;
1499 int rewrite = 0;
1500
1501 if (!buffer_ptr || *buffer_ptr)
1
Assuming 'buffer_ptr' is non-null
2
Assuming the condition is false
3
Taking false branch
1502 return AVERROR(EINVAL)(-(22));
1503
1504 sd_exif = av_frame_get_side_data(frame, AV_FRAME_DATA_EXIF);
1505 if (!sd_exif && !av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX))
4
Assuming 'sd_exif' is null
5
Assuming the condition is false
6
Taking false branch
1506 return 0;
1507
1508 if (sd_exif
6.1
'sd_exif' is null
6.1
'sd_exif' is null
) {
7
Taking false branch
1509 ret = av_exif_parse_buffer(logctx, sd_exif->data, sd_exif->size, &ifd, AV_EXIF_TIFF_HEADER);
1510 if (ret < 0)
1511 goto end;
1512 }
1513
1514 rewrite = ff_exif_sanitize_ifd(logctx, frame, &ifd);
1515 if (rewrite
7.1
'rewrite' is >= 0
7.1
'rewrite' is >= 0
< 0) {
1516 ret = rewrite;
1517 goto end;
1518 }
1519
1520 /*
1521 * we always have to rewrite if the requested header mode
1522 * does not match the internal header mode, which is always
1523 * AV_EXIF_TIFF_HEADER inside FFmpeg.
1524 *
1525 * If ifd.count == 0 then there's no data to write at all.
1526 * This is possible if the frame width and height are zero and the orientation is 1.
1527 */
1528 rewrite = (rewrite
7.2
'rewrite' is 1
7.2
'rewrite' is 1
|| header_mode != AV_EXIF_TIFF_HEADER) && ifd.count;
1529
1530 if (rewrite) {
8
Assuming 'rewrite' is not equal to 0
9
Taking true branch
1531 ret = av_exif_write(logctx, &ifd, &buffer, header_mode);
10
Calling 'av_exif_write'
1532 if (ret < 0)
1533 goto end;
1534
1535 *buffer_ptr = buffer;
1536 } else if (sd_exif) {
1537 *buffer_ptr = av_buffer_ref(sd_exif->buf);
1538 if (!*buffer_ptr) {
1539 ret = AVERROR(ENOMEM)(-(12));
1540 goto end;
1541 }
1542 }
1543
1544 av_exif_free(&ifd);
1545
1546 return !!(rewrite || sd_exif);
1547
1548end:
1549 av_exif_free(&ifd);
1550 return ret;
1551}

←

/root/firefox-clang/media/ffvpx/libavcodec/bytestream.h

1/*
2 * Bytestream functions
3 * copyright (c) 2006 Baptiste Coudurier <baptiste.coudurier@free.fr>
4 * Copyright (c) 2012 Aneesh Dogra (lionaneesh) <lionaneesh@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#ifndef AVCODEC_BYTESTREAM_H
24#define AVCODEC_BYTESTREAM_H
25
26#include <stdint.h>
27#include <string.h>
28
29#include "libavutil/avassert.h"
30#include "libavutil/common.h"
31#include "libavutil/intreadwrite.h"
32
33typedef struct GetByteContext {
34 const uint8_t *buffer, *buffer_end, *buffer_start;
35} GetByteContext;
36
37typedef struct PutByteContext {
38 uint8_t *buffer, *buffer_end, *buffer_start;
39 int eof;
40} PutByteContext;
41
42#define DEF(type, name, bytes, read, write)static __attribute__((always_inline)) inline type bytestream_get_name
(const uint8_t **b) { (*b) += bytes; return read(*b - bytes);
} static __attribute__((always_inline)) inline void bytestream_put_name
(uint8_t **b, const type value) { write(*b, value); (*b) += bytes
; } static __attribute__((always_inline)) inline void bytestream2_put_nameu
(PutByteContext *p, const type value) { bytestream_put_name(&
p->buffer, value); } static __attribute__((always_inline))
inline void bytestream2_put_name(PutByteContext *p, const type
value) { if (!p->eof && (p->buffer_end - p->
buffer >= bytes)) { write(p->buffer, value); p->buffer
+= bytes; } else p->eof = 1; } static __attribute__((always_inline
)) inline type bytestream2_get_nameu(GetByteContext *g) { return
bytestream_get_name(&g->buffer); } static __attribute__
((always_inline)) inline type bytestream2_get_name(GetByteContext
*g) { if (g->buffer_end - g->buffer < bytes) { g->
buffer = g->buffer_end; return 0; } return bytestream2_get_nameu
(g); } static __attribute__((always_inline)) inline type bytestream2_peek_nameu
(const GetByteContext *g) { return read(g->buffer); } static
__attribute__((always_inline)) inline type bytestream2_peek_name
(const GetByteContext *g){ if (g->buffer_end - g->buffer
< bytes) return 0; return bytestream2_peek_nameu(g); }
\
43static av_always_inline__attribute__((always_inline)) inline type bytestream_get_ ## name(const uint8_t **b) \
44{ \
45 (*b) += bytes; \
46 return read(*b - bytes); \
47} \
48static av_always_inline__attribute__((always_inline)) inline void bytestream_put_ ## name(uint8_t **b, \
49 const type value) \
50{ \
51 write(*b, value); \
52 (*b) += bytes; \
53} \
54static av_always_inline__attribute__((always_inline)) inline void bytestream2_put_ ## name ## u(PutByteContext *p, \
55 const type value) \
56{ \
57 bytestream_put_ ## name(&p->buffer, value); \
58} \
59static av_always_inline__attribute__((always_inline)) inline void bytestream2_put_ ## name(PutByteContext *p, \
60 const type value) \
61{ \
62 if (!p->eof && (p->buffer_end - p->buffer >= bytes)) { \
63 write(p->buffer, value); \
64 p->buffer += bytes; \
65 } else \
66 p->eof = 1; \
67} \
68static av_always_inline__attribute__((always_inline)) inline type bytestream2_get_ ## name ## u(GetByteContext *g) \
69{ \
70 return bytestream_get_ ## name(&g->buffer); \
71} \
72static av_always_inline__attribute__((always_inline)) inline type bytestream2_get_ ## name(GetByteContext *g) \
73{ \
74 if (g->buffer_end - g->buffer < bytes) { \
75 g->buffer = g->buffer_end; \
76 return 0; \
77 } \
78 return bytestream2_get_ ## name ## u(g); \
79} \
80static av_always_inline__attribute__((always_inline)) inline type bytestream2_peek_ ## name ## u(const GetByteContext *g) \
81{ \
82 return read(g->buffer); \
83} \
84static av_always_inline__attribute__((always_inline)) inline type bytestream2_peek_ ## name(const GetByteContext *g)\
85{ \
86 if (g->buffer_end - g->buffer < bytes) \
87 return 0; \
88 return bytestream2_peek_ ## name ## u(g); \
89}
90
91DEF(uint64_t, le64, 8, AV_RL64, AV_WL64)static __attribute__((always_inline)) inline uint64_t bytestream_get_le64
(const uint8_t **b) { (*b) += 8; return (((const union unaligned_64
*) (*b - 8))->l); } static __attribute__((always_inline))
inline void bytestream_put_le64(uint8_t **b, const uint64_t value
) { ((((union unaligned_64 *) (*b))->l) = (value)); (*b) +=
8; } static __attribute__((always_inline)) inline void bytestream2_put_le64u
(PutByteContext *p, const uint64_t value) { bytestream_put_le64
(&p->buffer, value); } static __attribute__((always_inline
)) inline void bytestream2_put_le64(PutByteContext *p, const uint64_t
value) { if (!p->eof && (p->buffer_end - p->
buffer >= 8)) { ((((union unaligned_64 *) (p->buffer))->
l) = (value)); p->buffer += 8; } else p->eof = 1; } static
__attribute__((always_inline)) inline uint64_t bytestream2_get_le64u
(GetByteContext *g) { return bytestream_get_le64(&g->buffer
); } static __attribute__((always_inline)) inline uint64_t bytestream2_get_le64
(GetByteContext *g) { if (g->buffer_end - g->buffer <
8) { g->buffer = g->buffer_end; return 0; } return bytestream2_get_le64u
(g); } static __attribute__((always_inline)) inline uint64_t bytestream2_peek_le64u
(const GetByteContext *g) { return (((const union unaligned_64
*) (g->buffer))->l); } static __attribute__((always_inline
)) inline uint64_t bytestream2_peek_le64(const GetByteContext
*g){ if (g->buffer_end - g->buffer < 8) return 0; return
bytestream2_peek_le64u(g); }
92DEF(unsigned int, le32, 4, AV_RL32, AV_WL32)static __attribute__((always_inline)) inline unsigned int bytestream_get_le32
(const uint8_t **b) { (*b) += 4; return (((const union unaligned_32
*) (*b - 4))->l); } static __attribute__((always_inline))
inline void bytestream_put_le32(uint8_t **b, const unsigned int
value) { ((((union unaligned_32 *) (*b))->l) = (value)); (
*b) += 4; } static __attribute__((always_inline)) inline void
bytestream2_put_le32u(PutByteContext *p, const unsigned int value
) { bytestream_put_le32(&p->buffer, value); } static __attribute__
((always_inline)) inline void bytestream2_put_le32(PutByteContext
*p, const unsigned int value) { if (!p->eof && (p
->buffer_end - p->buffer >= 4)) { ((((union unaligned_32
*) (p->buffer))->l) = (value)); p->buffer += 4; } else
p->eof = 1; } static __attribute__((always_inline)) inline
unsigned int bytestream2_get_le32u(GetByteContext *g) { return
bytestream_get_le32(&g->buffer); } static __attribute__
((always_inline)) inline unsigned int bytestream2_get_le32(GetByteContext
*g) { if (g->buffer_end - g->buffer < 4) { g->buffer
= g->buffer_end; return 0; } return bytestream2_get_le32u
(g); } static __attribute__((always_inline)) inline unsigned int
bytestream2_peek_le32u(const GetByteContext *g) { return (((
const union unaligned_32 *) (g->buffer))->l); } static __attribute__
((always_inline)) inline unsigned int bytestream2_peek_le32(const
GetByteContext *g){ if (g->buffer_end - g->buffer <
4) return 0; return bytestream2_peek_le32u(g); }
93DEF(unsigned int, le24, 3, AV_RL24, AV_WL24)static __attribute__((always_inline)) inline unsigned int bytestream_get_le24
(const uint8_t **b) { (*b) += 3; return ((((const uint8_t*)(*
b - 3))[2] << 16) | (((const uint8_t*)(*b - 3))[1] <<
8) | ((const uint8_t*)(*b - 3))[0]); } static __attribute__(
(always_inline)) inline void bytestream_put_le24(uint8_t **b,
const unsigned int value) { do { ((uint8_t*)(*b))[0] = (value
); ((uint8_t*)(*b))[1] = (value)>>8; ((uint8_t*)(*b))[2
] = (value)>>16; } while(0); (*b) += 3; } static __attribute__
((always_inline)) inline void bytestream2_put_le24u(PutByteContext
*p, const unsigned int value) { bytestream_put_le24(&p->
buffer, value); } static __attribute__((always_inline)) inline
void bytestream2_put_le24(PutByteContext *p, const unsigned int
value) { if (!p->eof && (p->buffer_end - p->
buffer >= 3)) { do { ((uint8_t*)(p->buffer))[0] = (value
); ((uint8_t*)(p->buffer))[1] = (value)>>8; ((uint8_t
*)(p->buffer))[2] = (value)>>16; } while(0); p->buffer
+= 3; } else p->eof = 1; } static __attribute__((always_inline
)) inline unsigned int bytestream2_get_le24u(GetByteContext *
g) { return bytestream_get_le24(&g->buffer); } static __attribute__
((always_inline)) inline unsigned int bytestream2_get_le24(GetByteContext
*g) { if (g->buffer_end - g->buffer < 3) { g->buffer
= g->buffer_end; return 0; } return bytestream2_get_le24u
(g); } static __attribute__((always_inline)) inline unsigned int
bytestream2_peek_le24u(const GetByteContext *g) { return (((
(const uint8_t*)(g->buffer))[2] << 16) | (((const uint8_t
*)(g->buffer))[1] << 8) | ((const uint8_t*)(g->buffer
))[0]); } static __attribute__((always_inline)) inline unsigned
int bytestream2_peek_le24(const GetByteContext *g){ if (g->
buffer_end - g->buffer < 3) return 0; return bytestream2_peek_le24u
(g); }
94DEF(unsigned int, le16, 2, AV_RL16, AV_WL16)static __attribute__((always_inline)) inline unsigned int bytestream_get_le16
(const uint8_t **b) { (*b) += 2; return (((const union unaligned_16
*) (*b - 2))->l); } static __attribute__((always_inline))
inline void bytestream_put_le16(uint8_t **b, const unsigned int
value) { ((((union unaligned_16 *) (*b))->l) = (value)); (
*b) += 2; } static __attribute__((always_inline)) inline void
bytestream2_put_le16u(PutByteContext *p, const unsigned int value
) { bytestream_put_le16(&p->buffer, value); } static __attribute__
((always_inline)) inline void bytestream2_put_le16(PutByteContext
*p, const unsigned int value) { if (!p->eof && (p
->buffer_end - p->buffer >= 2)) { ((((union unaligned_16
*) (p->buffer))->l) = (value)); p->buffer += 2; } else
p->eof = 1; } static __attribute__((always_inline)) inline
unsigned int bytestream2_get_le16u(GetByteContext *g) { return
bytestream_get_le16(&g->buffer); } static __attribute__
((always_inline)) inline unsigned int bytestream2_get_le16(GetByteContext
*g) { if (g->buffer_end - g->buffer < 2) { g->buffer
= g->buffer_end; return 0; } return bytestream2_get_le16u
(g); } static __attribute__((always_inline)) inline unsigned int
bytestream2_peek_le16u(const GetByteContext *g) { return (((
const union unaligned_16 *) (g->buffer))->l); } static __attribute__
((always_inline)) inline unsigned int bytestream2_peek_le16(const
GetByteContext *g){ if (g->buffer_end - g->buffer <
2) return 0; return bytestream2_peek_le16u(g); }
95DEF(uint64_t, be64, 8, AV_RB64, AV_WB64)static __attribute__((always_inline)) inline uint64_t bytestream_get_be64
(const uint8_t **b) { (*b) += 8; return av_bswap64((((const union
unaligned_64 *) (*b - 8))->l)); } static __attribute__((always_inline
)) inline void bytestream_put_be64(uint8_t **b, const uint64_t
value) { ((((union unaligned_64 *) (*b))->l) = (av_bswap64
(value))); (*b) += 8; } static __attribute__((always_inline))
inline void bytestream2_put_be64u(PutByteContext *p, const uint64_t
value) { bytestream_put_be64(&p->buffer, value); } static
__attribute__((always_inline)) inline void bytestream2_put_be64
(PutByteContext *p, const uint64_t value) { if (!p->eof &&
(p->buffer_end - p->buffer >= 8)) { ((((union unaligned_64
*) (p->buffer))->l) = (av_bswap64(value))); p->buffer
+= 8; } else p->eof = 1; } static __attribute__((always_inline
)) inline uint64_t bytestream2_get_be64u(GetByteContext *g) {
return bytestream_get_be64(&g->buffer); } static __attribute__
((always_inline)) inline uint64_t bytestream2_get_be64(GetByteContext
*g) { if (g->buffer_end - g->buffer < 8) { g->buffer
= g->buffer_end; return 0; } return bytestream2_get_be64u
(g); } static __attribute__((always_inline)) inline uint64_t bytestream2_peek_be64u
(const GetByteContext *g) { return av_bswap64((((const union unaligned_64
*) (g->buffer))->l)); } static __attribute__((always_inline
)) inline uint64_t bytestream2_peek_be64(const GetByteContext
*g){ if (g->buffer_end - g->buffer < 8) return 0; return
bytestream2_peek_be64u(g); }
96DEF(unsigned int, be32, 4, AV_RB32, AV_WB32)static __attribute__((always_inline)) inline unsigned int bytestream_get_be32
(const uint8_t **b) { (*b) += 4; return av_bswap32((((const union
unaligned_32 *) (*b - 4))->l)); } static __attribute__((always_inline
)) inline void bytestream_put_be32(uint8_t **b, const unsigned
int value) { ((((union unaligned_32 *) (*b))->l) = (av_bswap32
(value))); (*b) += 4; } static __attribute__((always_inline))
inline void bytestream2_put_be32u(PutByteContext *p, const unsigned
int value) { bytestream_put_be32(&p->buffer, value); }
static __attribute__((always_inline)) inline void bytestream2_put_be32
(PutByteContext *p, const unsigned int value) { if (!p->eof
&& (p->buffer_end - p->buffer >= 4)) { ((((
union unaligned_32 *) (p->buffer))->l) = (av_bswap32(value
))); p->buffer += 4; } else p->eof = 1; } static __attribute__
((always_inline)) inline unsigned int bytestream2_get_be32u(GetByteContext
*g) { return bytestream_get_be32(&g->buffer); } static
__attribute__((always_inline)) inline unsigned int bytestream2_get_be32
(GetByteContext *g) { if (g->buffer_end - g->buffer <
4) { g->buffer = g->buffer_end; return 0; } return bytestream2_get_be32u
(g); } static __attribute__((always_inline)) inline unsigned int
bytestream2_peek_be32u(const GetByteContext *g) { return av_bswap32
((((const union unaligned_32 *) (g->buffer))->l)); } static
__attribute__((always_inline)) inline unsigned int bytestream2_peek_be32
(const GetByteContext *g){ if (g->buffer_end - g->buffer
< 4) return 0; return bytestream2_peek_be32u(g); }
25
Assuming the condition is false
26
Taking false branch
97DEF(unsigned int, be24, 3, AV_RB24, AV_WB24)static __attribute__((always_inline)) inline unsigned int bytestream_get_be24
(const uint8_t **b) { (*b) += 3; return ((((const uint8_t*)(*
b - 3))[0] << 16) | (((const uint8_t*)(*b - 3))[1] <<
8) | ((const uint8_t*)(*b - 3))[2]); } static __attribute__(
(always_inline)) inline void bytestream_put_be24(uint8_t **b,
const unsigned int value) { do { ((uint8_t*)(*b))[2] = (value
); ((uint8_t*)(*b))[1] = (value)>>8; ((uint8_t*)(*b))[0
] = (value)>>16; } while(0); (*b) += 3; } static __attribute__
((always_inline)) inline void bytestream2_put_be24u(PutByteContext
*p, const unsigned int value) { bytestream_put_be24(&p->
buffer, value); } static __attribute__((always_inline)) inline
void bytestream2_put_be24(PutByteContext *p, const unsigned int
value) { if (!p->eof && (p->buffer_end - p->
buffer >= 3)) { do { ((uint8_t*)(p->buffer))[2] = (value
); ((uint8_t*)(p->buffer))[1] = (value)>>8; ((uint8_t
*)(p->buffer))[0] = (value)>>16; } while(0); p->buffer
+= 3; } else p->eof = 1; } static __attribute__((always_inline
)) inline unsigned int bytestream2_get_be24u(GetByteContext *
g) { return bytestream_get_be24(&g->buffer); } static __attribute__
((always_inline)) inline unsigned int bytestream2_get_be24(GetByteContext
*g) { if (g->buffer_end - g->buffer < 3) { g->buffer
= g->buffer_end; return 0; } return bytestream2_get_be24u
(g); } static __attribute__((always_inline)) inline unsigned int
bytestream2_peek_be24u(const GetByteContext *g) { return (((
(const uint8_t*)(g->buffer))[0] << 16) | (((const uint8_t
*)(g->buffer))[1] << 8) | ((const uint8_t*)(g->buffer
))[2]); } static __attribute__((always_inline)) inline unsigned
int bytestream2_peek_be24(const GetByteContext *g){ if (g->
buffer_end - g->buffer < 3) return 0; return bytestream2_peek_be24u
(g); }
98DEF(unsigned int, be16, 2, AV_RB16, AV_WB16)static __attribute__((always_inline)) inline unsigned int bytestream_get_be16
(const uint8_t **b) { (*b) += 2; return av_bswap16((((const union
unaligned_16 *) (*b - 2))->l)); } static __attribute__((always_inline
)) inline void bytestream_put_be16(uint8_t **b, const unsigned
int value) { ((((union unaligned_16 *) (*b))->l) = (av_bswap16
(value))); (*b) += 2; } static __attribute__((always_inline))
inline void bytestream2_put_be16u(PutByteContext *p, const unsigned
int value) { bytestream_put_be16(&p->buffer, value); }
static __attribute__((always_inline)) inline void bytestream2_put_be16
(PutByteContext *p, const unsigned int value) { if (!p->eof
&& (p->buffer_end - p->buffer >= 2)) { ((((
union unaligned_16 *) (p->buffer))->l) = (av_bswap16(value
))); p->buffer += 2; } else p->eof = 1; } static __attribute__
((always_inline)) inline unsigned int bytestream2_get_be16u(GetByteContext
*g) { return bytestream_get_be16(&g->buffer); } static
__attribute__((always_inline)) inline unsigned int bytestream2_get_be16
(GetByteContext *g) { if (g->buffer_end - g->buffer <
2) { g->buffer = g->buffer_end; return 0; } return bytestream2_get_be16u
(g); } static __attribute__((always_inline)) inline unsigned int
bytestream2_peek_be16u(const GetByteContext *g) { return av_bswap16
((((const union unaligned_16 *) (g->buffer))->l)); } static
__attribute__((always_inline)) inline unsigned int bytestream2_peek_be16
(const GetByteContext *g){ if (g->buffer_end - g->buffer
< 2) return 0; return bytestream2_peek_be16u(g); }
99DEF(unsigned int, byte, 1, AV_RB8 , AV_WB8)static __attribute__((always_inline)) inline unsigned int bytestream_get_byte
(const uint8_t **b) { (*b) += 1; return (((const uint8_t*)(*b
- 1))[0]); } static __attribute__((always_inline)) inline void
bytestream_put_byte(uint8_t **b, const unsigned int value) {
do { ((uint8_t*)(*b))[0] = (value); } while(0); (*b) += 1; }
static __attribute__((always_inline)) inline void bytestream2_put_byteu
(PutByteContext *p, const unsigned int value) { bytestream_put_byte
(&p->buffer, value); } static __attribute__((always_inline
)) inline void bytestream2_put_byte(PutByteContext *p, const unsigned
int value) { if (!p->eof && (p->buffer_end - p
->buffer >= 1)) { do { ((uint8_t*)(p->buffer))[0] = (
value); } while(0); p->buffer += 1; } else p->eof = 1; }
static __attribute__((always_inline)) inline unsigned int bytestream2_get_byteu
(GetByteContext *g) { return bytestream_get_byte(&g->buffer
); } static __attribute__((always_inline)) inline unsigned int
bytestream2_get_byte(GetByteContext *g) { if (g->buffer_end
- g->buffer < 1) { g->buffer = g->buffer_end; return
0; } return bytestream2_get_byteu(g); } static __attribute__
((always_inline)) inline unsigned int bytestream2_peek_byteu(
const GetByteContext *g) { return (((const uint8_t*)(g->buffer
))[0]); } static __attribute__((always_inline)) inline unsigned
int bytestream2_peek_byte(const GetByteContext *g){ if (g->
buffer_end - g->buffer < 1) return 0; return bytestream2_peek_byteu
(g); }
100
101#if AV_HAVE_BIGENDIAN0
102# define bytestream2_get_ne16bytestream2_get_le16 bytestream2_get_be16
103# define bytestream2_get_ne24bytestream2_get_le24 bytestream2_get_be24
104# define bytestream2_get_ne32bytestream2_get_le32 bytestream2_get_be32
105# define bytestream2_get_ne64bytestream2_get_le64 bytestream2_get_be64
106# define bytestream2_get_ne16ubytestream2_get_le16u bytestream2_get_be16u
107# define bytestream2_get_ne24ubytestream2_get_le24u bytestream2_get_be24u
108# define bytestream2_get_ne32ubytestream2_get_le32u bytestream2_get_be32u
109# define bytestream2_get_ne64ubytestream2_get_le64u bytestream2_get_be64u
110# define bytestream2_put_ne16bytestream2_put_le16 bytestream2_put_be16
111# define bytestream2_put_ne24bytestream2_put_le24 bytestream2_put_be24
112# define bytestream2_put_ne32bytestream2_put_le32 bytestream2_put_be32
113# define bytestream2_put_ne64bytestream2_put_le64 bytestream2_put_be64
114# define bytestream2_peek_ne16bytestream2_peek_le16 bytestream2_peek_be16
115# define bytestream2_peek_ne24bytestream2_peek_le24 bytestream2_peek_be24
116# define bytestream2_peek_ne32bytestream2_peek_le32 bytestream2_peek_be32
117# define bytestream2_peek_ne64bytestream2_peek_le64 bytestream2_peek_be64
118#else
119# define bytestream2_get_ne16bytestream2_get_le16 bytestream2_get_le16
120# define bytestream2_get_ne24bytestream2_get_le24 bytestream2_get_le24
121# define bytestream2_get_ne32bytestream2_get_le32 bytestream2_get_le32
122# define bytestream2_get_ne64bytestream2_get_le64 bytestream2_get_le64
123# define bytestream2_get_ne16ubytestream2_get_le16u bytestream2_get_le16u
124# define bytestream2_get_ne24ubytestream2_get_le24u bytestream2_get_le24u
125# define bytestream2_get_ne32ubytestream2_get_le32u bytestream2_get_le32u
126# define bytestream2_get_ne64ubytestream2_get_le64u bytestream2_get_le64u
127# define bytestream2_put_ne16bytestream2_put_le16 bytestream2_put_le16
128# define bytestream2_put_ne24bytestream2_put_le24 bytestream2_put_le24
129# define bytestream2_put_ne32bytestream2_put_le32 bytestream2_put_le32
130# define bytestream2_put_ne64bytestream2_put_le64 bytestream2_put_le64
131# define bytestream2_peek_ne16bytestream2_peek_le16 bytestream2_peek_le16
132# define bytestream2_peek_ne24bytestream2_peek_le24 bytestream2_peek_le24
133# define bytestream2_peek_ne32bytestream2_peek_le32 bytestream2_peek_le32
134# define bytestream2_peek_ne64bytestream2_peek_le64 bytestream2_peek_le64
135#endif
136
137static av_always_inline__attribute__((always_inline)) inline void bytestream2_init(GetByteContext *g,
138 const uint8_t *buf,
139 int buf_size)
140{
141 av_assert0(buf && buf_size >= 0)do { if (!(buf && buf_size >= 0)) { av_log(((void*
)0), 0, "Assertion %s failed at %s:%d\n", "buf && buf_size >= 0"
, "/root/firefox-clang/media/ffvpx/libavcodec/bytestream.h", 141
); abort(); } } while (0)
;
142 g->buffer = buf;
143 g->buffer_start = buf;
144 g->buffer_end = buf + buf_size;
145}
146
147static av_always_inline__attribute__((always_inline)) inline void bytestream2_init_writer(PutByteContext *p,
148 uint8_t *buf,
149 int buf_size)
150{
151 av_assert0(buf && buf_size >= 0)do { if (!(buf && buf_size >= 0)) { av_log(((void*
)0), 0, "Assertion %s failed at %s:%d\n", "buf && buf_size >= 0"
, "/root/firefox-clang/media/ffvpx/libavcodec/bytestream.h", 151
); abort(); } } while (0)
;
18
Assuming 'buf' is non-null
19
Assuming 'buf_size' is >= 0
20
Taking false branch
21
Loop condition is false. Exiting loop
152 p->buffer = buf;
153 p->buffer_start = buf;
154 p->buffer_end = buf + buf_size;
155 p->eof = 0;
156}
157
158static av_always_inline__attribute__((always_inline)) inline int bytestream2_get_bytes_left(const GetByteContext *g)
159{
160 return g->buffer_end - g->buffer;
161}
162
163static av_always_inline__attribute__((always_inline)) inline int bytestream2_get_bytes_left_p(const PutByteContext *p)
164{
165 return p->buffer_end - p->buffer;
166}
167
168static av_always_inline__attribute__((always_inline)) inline void bytestream2_skip(GetByteContext *g,
169 unsigned int size)
170{
171 g->buffer += FFMIN(g->buffer_end - g->buffer, size)((g->buffer_end - g->buffer) > (size) ? (size) : (g->
buffer_end - g->buffer))
;
172}
173
174static av_always_inline__attribute__((always_inline)) inline void bytestream2_skipu(GetByteContext *g,
175 unsigned int size)
176{
177 g->buffer += size;
178}
179
180static av_always_inline__attribute__((always_inline)) inline void bytestream2_skip_p(PutByteContext *p,
181 unsigned int size)
182{
183 unsigned int size2;
184 if (p->eof)
185 return;
186 size2 = FFMIN(p->buffer_end - p->buffer, size)((p->buffer_end - p->buffer) > (size) ? (size) : (p->
buffer_end - p->buffer))
;
187 if (size2 != size)
188 p->eof = 1;
189 p->buffer += size2;
190}
191
192static av_always_inline__attribute__((always_inline)) inline int bytestream2_tell(const GetByteContext *g)
193{
194 return (int)(g->buffer - g->buffer_start);
195}
196
197static av_always_inline__attribute__((always_inline)) inline int bytestream2_tell_p(const PutByteContext *p)
198{
199 return (int)(p->buffer - p->buffer_start);
200}
201
202static av_always_inline__attribute__((always_inline)) inline int bytestream2_size(const GetByteContext *g)
203{
204 return (int)(g->buffer_end - g->buffer_start);
205}
206
207static av_always_inline__attribute__((always_inline)) inline int bytestream2_size_p(const PutByteContext *p)
208{
209 return (int)(p->buffer_end - p->buffer_start);
210}
211
212static av_always_inline__attribute__((always_inline)) inline int bytestream2_seek(GetByteContext *g,
213 int offset,
214 int whence)
215{
216 switch (whence) {
217 case SEEK_CUR1:
218 offset = av_clipav_clip_c(offset, -(g->buffer - g->buffer_start),
219 g->buffer_end - g->buffer);
220 g->buffer += offset;
221 break;
222 case SEEK_END2:
223 offset = av_clipav_clip_c(offset, -(g->buffer_end - g->buffer_start), 0);
224 g->buffer = g->buffer_end + offset;
225 break;
226 case SEEK_SET0:
227 offset = av_clipav_clip_c(offset, 0, g->buffer_end - g->buffer_start);
228 g->buffer = g->buffer_start + offset;
229 break;
230 default:
231 return AVERROR(EINVAL)(-(22));
232 }
233 return bytestream2_tell(g);
234}
235
236static av_always_inline__attribute__((always_inline)) inline int bytestream2_seek_p(PutByteContext *p,
237 int offset,
238 int whence)
239{
240 p->eof = 0;
241 switch (whence) {
242 case SEEK_CUR1:
243 if (p->buffer_end - p->buffer < offset)
244 p->eof = 1;
245 offset = av_clipav_clip_c(offset, -(p->buffer - p->buffer_start),
246 p->buffer_end - p->buffer);
247 p->buffer += offset;
248 break;
249 case SEEK_END2:
250 if (offset > 0)
251 p->eof = 1;
252 offset = av_clipav_clip_c(offset, -(p->buffer_end - p->buffer_start), 0);
253 p->buffer = p->buffer_end + offset;
254 break;
255 case SEEK_SET0:
256 if (p->buffer_end - p->buffer_start < offset)
257 p->eof = 1;
258 offset = av_clipav_clip_c(offset, 0, p->buffer_end - p->buffer_start);
259 p->buffer = p->buffer_start + offset;
260 break;
261 default:
262 return AVERROR(EINVAL)(-(22));
263 }
264 return bytestream2_tell_p(p);
265}
266
267static av_always_inline__attribute__((always_inline)) inline unsigned int bytestream2_get_buffer(GetByteContext *g,
268 uint8_t *dst,
269 unsigned int size)
270{
271 unsigned int size2 = FFMIN(g->buffer_end - g->buffer, size)((g->buffer_end - g->buffer) > (size) ? (size) : (g->
buffer_end - g->buffer))
;
272 memcpy(dst, g->buffer, size2);
273 g->buffer += size2;
274 return size2;
275}
276
277static av_always_inline__attribute__((always_inline)) inline unsigned int bytestream2_get_bufferu(GetByteContext *g,
278 uint8_t *dst,
279 unsigned int size)
280{
281 memcpy(dst, g->buffer, size);
282 g->buffer += size;
283 return size;
284}
285
286static av_always_inline__attribute__((always_inline)) inline unsigned int bytestream2_put_buffer(PutByteContext *p,
287 const uint8_t *src,
288 unsigned int size)
289{
290 unsigned int size2;
291 if (p->eof)
68
Assuming field 'eof' is 0
292 return 0;
293 size2 = FFMIN(p->buffer_end - p->buffer, size)((p->buffer_end - p->buffer) > (size) ? (size) : (p->
buffer_end - p->buffer))
;
69
Taking false branch
70
Assuming the condition is true
71
'?' condition is true
294 if (size2
71.1
'size2' is equal to 'size'
71.1
'size2' is equal to 'size'
!= size)
72
Taking false branch
295 p->eof = 1;
296 memcpy(p->buffer, src, size2);
73
Null pointer passed to 2nd parameter expecting 'nonnull'
297 p->buffer += size2;
298 return size2;
299}
300
301static av_always_inline__attribute__((always_inline)) inline unsigned int bytestream2_put_bufferu(PutByteContext *p,
302 const uint8_t *src,
303 unsigned int size)
304{
305 memcpy(p->buffer, src, size);
306 p->buffer += size;
307 return size;
308}
309
310static av_always_inline__attribute__((always_inline)) inline void bytestream2_set_buffer(PutByteContext *p,
311 const uint8_t c,
312 unsigned int size)
313{
314 unsigned int size2;
315 if (p->eof)
316 return;
317 size2 = FFMIN(p->buffer_end - p->buffer, size)((p->buffer_end - p->buffer) > (size) ? (size) : (p->
buffer_end - p->buffer))
;
318 if (size2 != size)
319 p->eof = 1;
320 memset(p->buffer, c, size2);
321 p->buffer += size2;
322}
323
324static av_always_inline__attribute__((always_inline)) inline void bytestream2_set_bufferu(PutByteContext *p,
325 const uint8_t c,
326 unsigned int size)
327{
328 memset(p->buffer, c, size);
329 p->buffer += size;
330}
331
332static av_always_inline__attribute__((always_inline)) inline unsigned int bytestream2_get_eof(PutByteContext *p)
333{
334 return p->eof;
335}
336
337static av_always_inline__attribute__((always_inline)) inline unsigned int bytestream2_copy_bufferu(PutByteContext *p,
338 GetByteContext *g,
339 unsigned int size)
340{
341 memcpy(p->buffer, g->buffer, size);
342 p->buffer += size;
343 g->buffer += size;
344 return size;
345}
346
347static av_always_inline__attribute__((always_inline)) inline unsigned int bytestream2_copy_buffer(PutByteContext *p,
348 GetByteContext *g,
349 unsigned int size)
350{
351 unsigned int size2;
352
353 if (p->eof)
354 return 0;
355 size = FFMIN(g->buffer_end - g->buffer, size)((g->buffer_end - g->buffer) > (size) ? (size) : (g->
buffer_end - g->buffer))
;
356 size2 = FFMIN(p->buffer_end - p->buffer, size)((p->buffer_end - p->buffer) > (size) ? (size) : (p->
buffer_end - p->buffer))
;
357 if (size2 != size)
358 p->eof = 1;
359
360 return bytestream2_copy_bufferu(p, g, size2);
361}
362
363static av_always_inline__attribute__((always_inline)) inline unsigned int bytestream_get_buffer(const uint8_t **b,
364 uint8_t *dst,
365 unsigned int size)
366{
367 memcpy(dst, *b, size);
368 (*b) += size;
369 return size;
370}
371
372static av_always_inline__attribute__((always_inline)) inline void bytestream_put_buffer(uint8_t **b,
373 const uint8_t *src,
374 unsigned int size)
375{
376 memcpy(*b, src, size);
377 (*b) += size;
378}
379
380#endif /* AVCODEC_BYTESTREAM_H */