EXIF library (libexif) Internals  0.6.24
exif-mnote-data-canon.c
Go to the documentation of this file.
1 /* exif-mnote-data-canon.c
2  *
3  * Copyright (c) 2002, 2003 Lutz Mueller <lutz@users.sourceforge.net>
4  * Copyright (c) 2003 Matthieu Castet <mat-c@users.sourceforge.net>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301 USA.
20  */
21 
22 #include <config.h>
23 #include "exif-mnote-data-canon.h"
24 
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 
30 #include <libexif/exif-utils.h>
31 #include <libexif/exif-data.h>
32 
33 #define CHECKOVERFLOW(offset,datasize,structsize) (( offset >= datasize) || (structsize > datasize) || (offset > datasize - structsize ))
34 
35 /* Total size limit to prevent abuse by DoS */
36 #define FAILSAFE_SIZE_MAX 1000000L
37 
38 static void
40 {
41  ExifMnoteData *d = (ExifMnoteData *) n;
42  unsigned int i;
43 
44  if (!n) return;
45 
46  if (n->entries) {
47  for (i = 0; i < n->count; i++)
48  if (n->entries[i].data) {
49  exif_mem_free (d->mem, n->entries[i].data);
50  n->entries[i].data = NULL;
51  }
52  exif_mem_free (d->mem, n->entries);
53  n->entries = NULL;
54  n->count = 0;
55  }
56 }
57 
58 static void
60 {
61  if (!n) return;
62 
64 }
65 
66 static void
68  unsigned int *m, unsigned int *s)
69 {
70  unsigned int from = 0, to;
71 
72  if (!dc || !m) return;
73  for (*m = 0; *m < dc->count; (*m)++) {
74  to = from + mnote_canon_entry_count_values (&dc->entries[*m]);
75  if (to > n) {
76  if (s) *s = n - from;
77  break;
78  }
79  from = to;
80  }
81 }
82 
83 static char *
84 exif_mnote_data_canon_get_value (ExifMnoteData *note, unsigned int n, char *val, unsigned int maxlen)
85 {
87  unsigned int m, s;
88 
89  if (!dc) return NULL;
90  exif_mnote_data_canon_get_tags (dc, n, &m, &s);
91  if (m >= dc->count) return NULL;
92  return mnote_canon_entry_get_value (&dc->entries[m], s, val, maxlen);
93 }
94 
95 static void
97 {
98  ExifByteOrder o_orig;
100  unsigned int i;
101 
102  if (!n) return;
103 
104  o_orig = n->order;
105  n->order = o;
106  for (i = 0; i < n->count; i++) {
107  if (n->entries[i].components && (n->entries[i].size/n->entries[i].components < exif_format_get_size (n->entries[i].format)))
108  continue;
109  n->entries[i].order = o;
111  n->entries[i].components, o_orig, o);
112  }
113 }
114 
115 static void
117 {
118  if (n) ((ExifMnoteDataCanon *) n)->offset = o;
119 }
120 
121 static void
123  unsigned char **buf, unsigned int *buf_size)
124 {
126  size_t i, o, s, doff;
127  unsigned char *t;
128  size_t ts;
129 
130  if (!n || !buf || !buf_size) return;
131 
132  /*
133  * Allocate enough memory for all entries and the number
134  * of entries.
135  */
136  *buf_size = 2 + n->count * 12 + 4;
137  *buf = exif_mem_alloc (ne->mem, sizeof (char) * *buf_size);
138  if (!*buf) {
139  EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", *buf_size);
140  return;
141  }
142 
143  /* Save the number of entries */
144  exif_set_short (*buf, n->order, (ExifShort) n->count);
145 
146  /* Save each entry */
147  for (i = 0; i < n->count; i++) {
148  o = 2 + i * 12;
149  exif_set_short (*buf + o + 0, n->order, (ExifShort) n->entries[i].tag);
150  exif_set_short (*buf + o + 2, n->order, (ExifShort) n->entries[i].format);
151  exif_set_long (*buf + o + 4, n->order,
152  n->entries[i].components);
153  o += 8;
154  s = exif_format_get_size (n->entries[i].format) *
155  n->entries[i].components;
156  if (s > 65536) {
157  /* Corrupt data: EXIF data size is limited to the
158  * maximum size of a JPEG segment (64 kb).
159  */
160  continue;
161  }
162  if (s > 4) {
163  ts = *buf_size + s;
164 
165  /* Ensure even offsets. Set padding bytes to 0. */
166  if (s & 1) ts += 1;
167  t = exif_mem_realloc (ne->mem, *buf,
168  sizeof (char) * ts);
169  if (!t) {
170  EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", ts);
171  return;
172  }
173  *buf = t;
174  *buf_size = ts;
175  doff = *buf_size - s;
176  if (s & 1) { doff--; *(*buf + *buf_size - 1) = '\0'; }
177  exif_set_long (*buf + o, n->order, n->offset + doff);
178  } else
179  doff = o;
180 
181  /*
182  * Write the data. Fill unneeded bytes with 0. Do not
183  * crash if data is NULL.
184  */
185  if (!n->entries[i].data) memset (*buf + doff, 0, s);
186  else memcpy (*buf + doff, n->entries[i].data, s);
187  if (s < 4) memset (*buf + doff + s, 0, (4 - s));
188  }
189 }
190 
191 /* XXX
192  * FIXME: exif_mnote_data_canon_load() may fail and there is no
193  * semantics to express that.
194  * See bug #1054323 for details, especially the comment by liblit
195  * after it has supposedly been fixed:
196  *
197  * https://sourceforge.net/tracker/?func=detail&aid=1054323&group_id=12272&atid=112272
198  * Unfortunately, the "return" statements aren't commented at
199  * all, so it isn't trivial to find out what is a normal
200  * return, and what is a reaction to an error condition.
201  */
202 
203 static void
205  const unsigned char *buf, unsigned int buf_size)
206 {
208  ExifShort c;
209  size_t i, tcount, o, datao;
210  long failsafe_size = 0;
211 
212  if (!n || !buf || !buf_size) {
214  "ExifMnoteCanon", "Short MakerNote");
215  return;
216  }
217  datao = 6 + n->offset;
218  if (CHECKOVERFLOW(datao, buf_size, 2)) {
220  "ExifMnoteCanon", "Short MakerNote");
221  return;
222  }
223 
224  /* Read the number of tags */
225  c = exif_get_short (buf + datao, n->order);
226  datao += 2;
227  /* Just use an arbitrary max tag limit here to avoid needing to much memory or time. There are 24 named tags currently.
228  * current 2020 camera EOS M6 Mark 2 had 156 entries.
229  * The format allows specifying the same range of memory as often as it can, so this multiplies quickly. */
230  if (c > 250) {
231  exif_log (ne->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifMnoteCanon", "Too much tags (%d) in Canon MakerNote", c);
232  return;
233  }
234 
235  /* Remove any old entries */
237 
238  /* Reserve enough space for all the possible MakerNote tags */
239  n->entries = exif_mem_alloc (ne->mem, sizeof (MnoteCanonEntry) * c);
240  if (!n->entries) {
241  EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", sizeof (MnoteCanonEntry) * c);
242  return;
243  }
244 
245  /* Parse the entries */
246  tcount = 0;
247  for (i = c, o = datao; i; --i, o += 12) {
248  size_t s;
249 
250  memset(&n->entries[tcount], 0, sizeof(MnoteCanonEntry));
251  if (CHECKOVERFLOW(o,buf_size,12)) {
253  "ExifMnoteCanon", "Short MakerNote");
254  break;
255  }
256 
257  n->entries[tcount].tag = exif_get_short (buf + o, n->order);
258  n->entries[tcount].format = exif_get_short (buf + o + 2, n->order);
259  n->entries[tcount].components = exif_get_long (buf + o + 4, n->order);
260  n->entries[tcount].order = n->order;
261 
262  exif_log (ne->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteCanon",
263  "Loading entry 0x%x ('%s')...", n->entries[tcount].tag,
264  mnote_canon_tag_get_name (n->entries[tcount].tag));
265 
266  /* Check if we overflow the multiplication. Use buf_size as the max size for integer overflow detection,
267  * we will check the buffer sizes closer later. */
268  if ( exif_format_get_size (n->entries[tcount].format) &&
269  buf_size / exif_format_get_size (n->entries[tcount].format) < n->entries[tcount].components
270  ) {
272  "ExifMnoteCanon", "Tag size overflow detected (%u * %lu)", exif_format_get_size (n->entries[tcount].format), n->entries[tcount].components);
273  continue;
274  }
275 
276  /*
277  * Size? If bigger than 4 bytes, the actual data is not
278  * in the entry but somewhere else (offset).
279  */
280  s = exif_format_get_size (n->entries[tcount].format) *
281  n->entries[tcount].components;
282  n->entries[tcount].size = s;
283  if (!s) {
285  "ExifMnoteCanon",
286  "Invalid zero-length tag size");
287  continue;
288 
289  } else {
290  size_t dataofs = o + 8;
291  if (s > 4) dataofs = exif_get_long (buf + dataofs, n->order) + 6;
292 
293  if (CHECKOVERFLOW(dataofs, buf_size, s)) {
295  "ExifMnoteCanon",
296  "Tag data past end of buffer (%u > %u)",
297  (unsigned)(dataofs + s), buf_size);
298  continue;
299  }
300 
301  n->entries[tcount].data = exif_mem_alloc (ne->mem, s);
302  if (!n->entries[tcount].data) {
303  EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteCanon", s);
304  continue;
305  }
306  memcpy (n->entries[tcount].data, buf + dataofs, s);
307  }
308 
309  /* Track the size of decoded tag data. A malicious file could
310  * be crafted to cause extremely large values here without
311  * tripping any buffer range checks. This is especially bad
312  * with the libexif representation of Canon MakerNotes because
313  * some arrays are turned into individual tags that the
314  * application must loop around. */
315  failsafe_size += mnote_canon_entry_count_values(&n->entries[tcount]);
316 
317  if (failsafe_size > FAILSAFE_SIZE_MAX) {
318  /* Abort if the total size of the data in the tags extraordinarily large, */
319  exif_mem_free (ne->mem, n->entries[tcount].data);
321  "ExifMnoteCanon", "Failsafe tag size overflow (%lu > %ld)",
322  failsafe_size, FAILSAFE_SIZE_MAX);
323  break;
324  }
325 
326  /* Tag was successfully parsed */
327  ++tcount;
328  }
329  /* Store the count of successfully parsed tags */
330  n->count = tcount;
331 }
332 
333 static unsigned int
335 {
337  unsigned int i, c;
338 
339  for (i = c = 0; dc && (i < dc->count); i++)
341  return c;
342 }
343 
344 static unsigned int
346 {
348  unsigned int m;
349 
350  if (!dc) return 0;
351  exif_mnote_data_canon_get_tags (dc, i, &m, NULL);
352  if (m >= dc->count) return 0;
353  return dc->entries[m].tag;
354 }
355 
356 static const char *
358 {
359  ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) note;
360  unsigned int m, s;
361 
362  if (!dc) return NULL;
363  exif_mnote_data_canon_get_tags (dc, i, &m, &s);
364  if (m >= dc->count) return NULL;
365  return mnote_canon_tag_get_name_sub (dc->entries[m].tag, s, dc->options);
366 }
367 
368 static const char *
370 {
371  ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) note;
372  unsigned int m, s;
373 
374  if (!dc) return NULL;
375  exif_mnote_data_canon_get_tags (dc, i, &m, &s);
376  if (m >= dc->count) return NULL;
377  return mnote_canon_tag_get_title_sub (dc->entries[m].tag, s, dc->options);
378 }
379 
380 static const char *
382 {
383  ExifMnoteDataCanon *dc = (ExifMnoteDataCanon *) note;
384  unsigned int m;
385 
386  if (!dc) return NULL;
387  exif_mnote_data_canon_get_tags (dc, i, &m, NULL);
388  if (m >= dc->count) return NULL;
390 }
391 
392 int
394 {
395  char value[8];
396 
398  if (!em)
399  return 0;
400 
401  (void) e; /* unused */
402  return !strcmp (exif_entry_get_value (em, value, sizeof (value)), "Canon");
403 }
404 
407 {
408  ExifMnoteData *d;
409  ExifMnoteDataCanon *dc;
410 
411  if (!mem) return NULL;
412 
413  d = exif_mem_alloc (mem, sizeof (ExifMnoteDataCanon));
414  if (!d)
415  return NULL;
416 
417  exif_mnote_data_construct (d, mem);
418 
419  /* Set up function pointers */
431 
432  dc = (ExifMnoteDataCanon*)d;
433  dc->options = o;
434  return d;
435 }
Defines the ExifByteOrder enum and the associated functions.
ExifByteOrder
Which byte order to use.
Defines the ExifData type and the associated functions.
ExifDataOption
Options to configure the behaviour of ExifData.
Definition: exif-data.h:174
#define exif_data_get_entry(d, t)
Return an ExifEntry for the given tag if found in any IFD.
Definition: exif-data.h:251
const char * exif_entry_get_value(ExifEntry *e, char *val, unsigned int maxlen)
Return a localized textual representation of the value of the EXIF entry.
Definition: exif-entry.c:846
unsigned char exif_format_get_size(ExifFormat format)
Return the raw size of the given EXIF data type.
Definition: exif-format.c:66
void exif_log(ExifLog *log, ExifLogCode code, const char *domain, const char *format,...)
Definition: exif-log.c:135
@ EXIF_LOG_CODE_CORRUPT_DATA
Definition: exif-log.h:58
@ EXIF_LOG_CODE_DEBUG
Definition: exif-log.h:56
#define EXIF_LOG_NO_MEMORY(l, d, s)
Definition: exif-log.h:110
void * exif_mem_realloc(ExifMem *mem, void *d, ExifLong ds)
Definition: exif-mem.c:89
void exif_mem_free(ExifMem *mem, void *d)
Definition: exif-mem.c:69
void * exif_mem_alloc(ExifMem *mem, ExifLong ds)
Definition: exif-mem.c:79
#define FAILSAFE_SIZE_MAX
ExifMnoteData * exif_mnote_data_canon_new(ExifMem *mem, ExifDataOption o)
static void exif_mnote_data_canon_set_offset(ExifMnoteData *n, unsigned int o)
static const char * exif_mnote_data_canon_get_title(ExifMnoteData *note, unsigned int i)
static char * exif_mnote_data_canon_get_value(ExifMnoteData *note, unsigned int n, char *val, unsigned int maxlen)
static const char * exif_mnote_data_canon_get_name(ExifMnoteData *note, unsigned int i)
static unsigned int exif_mnote_data_canon_get_id(ExifMnoteData *d, unsigned int i)
static void exif_mnote_data_canon_save(ExifMnoteData *ne, unsigned char **buf, unsigned int *buf_size)
int exif_mnote_data_canon_identify(const ExifData *ed, const ExifEntry *e)
Detect if MakerNote is recognized as one handled by the Canon module.
static const char * exif_mnote_data_canon_get_description(ExifMnoteData *note, unsigned int i)
static void exif_mnote_data_canon_clear(ExifMnoteDataCanon *n)
static void exif_mnote_data_canon_free(ExifMnoteData *n)
static unsigned int exif_mnote_data_canon_count(ExifMnoteData *n)
#define CHECKOVERFLOW(offset, datasize, structsize)
static void exif_mnote_data_canon_load(ExifMnoteData *ne, const unsigned char *buf, unsigned int buf_size)
static void exif_mnote_data_canon_get_tags(ExifMnoteDataCanon *dc, unsigned int n, unsigned int *m, unsigned int *s)
static void exif_mnote_data_canon_set_byte_order(ExifMnoteData *d, ExifByteOrder o)
void exif_mnote_data_construct(ExifMnoteData *, ExifMem *mem)
@ EXIF_TAG_MAKE
Definition: exif-tag.h:46
ExifLong exif_get_long(const unsigned char *buf, ExifByteOrder order)
Retrieve an ExifLong value from memory.
Definition: exif-utils.c:165
ExifShort exif_get_short(const unsigned char *buf, ExifByteOrder order)
Retrieve an ExifShort value from memory.
Definition: exif-utils.c:102
void exif_array_set_byte_order(ExifFormat f, unsigned char *b, unsigned int n, ExifByteOrder o_orig, ExifByteOrder o_new)
Definition: exif-utils.c:26
void exif_set_long(unsigned char *b, ExifByteOrder order, ExifLong value)
Store an ExifLong value into memory in EXIF format.
Definition: exif-utils.c:171
void exif_set_short(unsigned char *b, ExifByteOrder order, ExifShort value)
Store an ExifShort value into memory in EXIF format.
Definition: exif-utils.c:124
EXIF data manipulation functions and types.
uint16_t ExifShort
EXIF Unsigned Short data type.
Definition: exif-utils.h:48
char * mnote_canon_entry_get_value(const MnoteCanonEntry *entry, unsigned int t, char *val, unsigned int maxlen)
unsigned int mnote_canon_entry_count_values(const MnoteCanonEntry *entry)
const char * mnote_canon_tag_get_title_sub(MnoteCanonTag t, unsigned int s, ExifDataOption o)
const char * mnote_canon_tag_get_name(MnoteCanonTag t)
const char * mnote_canon_tag_get_name_sub(MnoteCanonTag t, unsigned int s, ExifDataOption o)
const char * mnote_canon_tag_get_description(MnoteCanonTag t)
Represents the entire EXIF data found in an image.
Definition: exif-data.h:47
Data found in one EXIF tag.
Definition: exif-entry.h:43
MnoteCanonEntry * entries
const char *(* get_description)(ExifMnoteData *, unsigned int)
void(* load)(ExifMnoteData *, const unsigned char *, unsigned int)
const char *(* get_name)(ExifMnoteData *, unsigned int)
const char *(* get_title)(ExifMnoteData *, unsigned int)
char *(* get_value)(ExifMnoteData *, unsigned int, char *val, unsigned int maxlen)
unsigned int(* get_id)(ExifMnoteData *, unsigned int)
void(* save)(ExifMnoteData *, unsigned char **, unsigned int *)
unsigned int(* count)(ExifMnoteData *)
void(* set_offset)(ExifMnoteData *, unsigned int)
void(* set_byte_order)(ExifMnoteData *, ExifByteOrder)
void(* free)(ExifMnoteData *)
ExifMnoteDataMethods methods
ExifByteOrder order
MnoteCanonTag tag
unsigned long components
unsigned char * data

libexif Generated by doxygen