EXIF library (libexif) Internals  0.6.24
exif-mnote-data-fuji.c
Go to the documentation of this file.
1 /* exif-mnote-data-fuji.c
2  *
3  * Copyright (c) 2002 Lutz Mueller <lutz@users.sourceforge.net>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301 USA.
19  */
20 
21 #include <stdlib.h>
22 #include <string.h>
23 
24 
25 #include <config.h>
27 #include <libexif/exif-utils.h>
28 
29 #include "exif-mnote-data-fuji.h"
30 
31 #define CHECKOVERFLOW(offset,datasize,structsize) (( offset >= datasize) || (structsize > datasize) || (offset > datasize - structsize ))
32 
35 };
36 
37 static void
39 {
40  ExifMnoteData *d = (ExifMnoteData *) n;
41  unsigned int i;
42 
43  if (!n) return;
44 
45  if (n->entries) {
46  for (i = 0; i < n->count; i++)
47  if (n->entries[i].data) {
48  exif_mem_free (d->mem, n->entries[i].data);
49  n->entries[i].data = NULL;
50  }
51  exif_mem_free (d->mem, n->entries);
52  n->entries = NULL;
53  n->count = 0;
54  }
55 }
56 
57 static void
59 {
60  if (!n) return;
61 
63 }
64 
65 static char *
66 exif_mnote_data_fuji_get_value (ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen)
67 {
69 
70  if (!d || !val) return NULL;
71  if (i > n->count -1) return NULL;
72 /*
73  exif_log (d->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataFuji",
74  "Querying value for tag '%s'...",
75  mnote_fuji_tag_get_name (n->entries[i].tag));
76 */
77  return mnote_fuji_entry_get_value (&n->entries[i], val, maxlen);
78 }
79 
80 static void
81 exif_mnote_data_fuji_save (ExifMnoteData *ne, unsigned char **buf,
82  unsigned int *buf_size)
83 {
85  size_t i, o, s, doff;
86  unsigned char *t;
87  size_t ts;
88 
89  if (!n || !buf || !buf_size) return;
90 
91  /*
92  * Allocate enough memory for all entries and the number
93  * of entries.
94  */
95  *buf_size = 8 + 4 + 2 + n->count * 12 + 4;
96  *buf = exif_mem_alloc (ne->mem, *buf_size);
97  if (!*buf) {
98  *buf_size = 0;
99  return;
100  }
101 
102  /*
103  * Header: "FUJIFILM" and 4 bytes offset to the first entry.
104  * As the first entry will start right thereafter, the offset is 12.
105  */
106  memcpy (*buf, "FUJIFILM", 8);
107  exif_set_long (*buf + 8, n->order, 12);
108 
109  /* Save the number of entries */
110  exif_set_short (*buf + 8 + 4, n->order, (ExifShort) n->count);
111 
112  /* Save each entry */
113  for (i = 0; i < n->count; i++) {
114  o = 8 + 4 + 2 + i * 12;
115  exif_set_short (*buf + o + 0, n->order, (ExifShort) n->entries[i].tag);
116  exif_set_short (*buf + o + 2, n->order, (ExifShort) n->entries[i].format);
117  exif_set_long (*buf + o + 4, n->order, n->entries[i].components);
118  o += 8;
119  s = exif_format_get_size (n->entries[i].format) *
120  n->entries[i].components;
121  if (s > 65536) {
122  /* Corrupt data: EXIF data size is limited to the
123  * maximum size of a JPEG segment (64 kb).
124  */
125  continue;
126  }
127  if (s > 4) {
128  ts = *buf_size + s;
129 
130  /* Ensure even offsets. Set padding bytes to 0. */
131  if (s & 1) ts += 1;
132  t = exif_mem_realloc (ne->mem, *buf, ts);
133  if (!t) {
134  return;
135  }
136  *buf = t;
137  *buf_size = ts;
138  doff = *buf_size - s;
139  if (s & 1) { doff--; *(*buf + *buf_size - 1) = '\0'; }
140  exif_set_long (*buf + o, n->order, doff);
141  } else
142  doff = o;
143 
144  /*
145  * Write the data. Fill unneeded bytes with 0. Do not
146  * crash if data is NULL.
147  */
148  if (!n->entries[i].data) memset (*buf + doff, 0, s);
149  else memcpy (*buf + doff, n->entries[i].data, s);
150  }
151 }
152 
153 static void
155  const unsigned char *buf, unsigned int buf_size)
156 {
158  ExifLong c;
159  size_t i, tcount, o, datao;
160 
161  if (!n || !buf || !buf_size) {
163  "ExifMnoteDataFuji", "Short MakerNote");
164  return;
165  }
166  datao = 6 + n->offset;
167  if (CHECKOVERFLOW(datao, buf_size, 12)) {
169  "ExifMnoteDataFuji", "Short MakerNote");
170  return;
171  }
172 
174 
175  datao += exif_get_long (buf + datao + 8, EXIF_BYTE_ORDER_INTEL);
176  if (CHECKOVERFLOW(datao, buf_size, 2)) {
178  "ExifMnoteDataFuji", "Short MakerNote");
179  return;
180  }
181 
182  /* Read the number of tags */
183  c = exif_get_short (buf + datao, EXIF_BYTE_ORDER_INTEL);
184  datao += 2;
185 
186  /* Just use an arbitrary max tag limit here to avoid needing to much memory or time. There are 50 named tags currently.
187  * Fuji XT2 had 56 entries or so, GFX500 has 68. 150 seems a safe upper bound currently.
188  * The format allows specifying the same range of memory as often as it can, so this multiplies quickly. */
189  if (c > 150) {
190  exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifMnoteDataFuji", "Too much tags (%d) in Fuji MakerNote", c);
191  return;
192  }
193 
194  /* Remove any old entries */
196 
197  /* Reserve enough space for all the possible MakerNote tags */
198  n->entries = exif_mem_alloc (en->mem, sizeof (MnoteFujiEntry) * c);
199  if (!n->entries) {
200  EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteDataFuji", sizeof (MnoteFujiEntry) * c);
201  return;
202  }
203 
204  /* Parse all c entries, storing ones that are successfully parsed */
205  tcount = 0;
206  for (i = c, o = datao; i; --i, o += 12) {
207  size_t s;
208 
209  memset(&n->entries[tcount], 0, sizeof(MnoteFujiEntry));
210  if (CHECKOVERFLOW(o, buf_size, 12)) {
212  "ExifMnoteDataFuji", "Short MakerNote");
213  break;
214  }
215 
216  n->entries[tcount].tag = exif_get_short (buf + o, n->order);
217  n->entries[tcount].format = exif_get_short (buf + o + 2, n->order);
218  n->entries[tcount].components = exif_get_long (buf + o + 4, n->order);
219  n->entries[tcount].order = n->order;
220 
221  exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataFuji",
222  "Loading entry 0x%x ('%s')...", n->entries[tcount].tag,
223  mnote_fuji_tag_get_name (n->entries[tcount].tag));
224 
225  /* Check if we overflow the multiplication. Use buf_size as the max size for integer overflow detection,
226  * we will check the buffer sizes closer later. */
227  if ( exif_format_get_size (n->entries[tcount].format) &&
228  buf_size / exif_format_get_size (n->entries[tcount].format) < n->entries[tcount].components
229  ) {
231  "ExifMnoteDataFuji", "Tag size overflow detected (%u * %lu)", exif_format_get_size (n->entries[tcount].format), n->entries[tcount].components);
232  continue;
233  }
234  /*
235  * Size? If bigger than 4 bytes, the actual data is not
236  * in the entry but somewhere else (offset).
237  */
238  s = exif_format_get_size (n->entries[tcount].format) * n->entries[tcount].components;
239  n->entries[tcount].size = s;
240  if (s) {
241  size_t dataofs = o + 8;
242  if (s > 4)
243  /* The data in this case is merely a pointer */
244  dataofs = exif_get_long (buf + dataofs, n->order) + 6 + n->offset;
245 
246  if (CHECKOVERFLOW(dataofs, buf_size, s)) {
248  "ExifMnoteDataFuji", "Tag data past end of "
249  "buffer (%u >= %u)", (unsigned)(dataofs + s), buf_size);
250  continue;
251  }
252 
253  n->entries[tcount].data = exif_mem_alloc (en->mem, s);
254  if (!n->entries[tcount].data) {
255  EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteDataFuji", s);
256  continue;
257  }
258  memcpy (n->entries[tcount].data, buf + dataofs, s);
259  }
260 
261  /* Tag was successfully parsed */
262  ++tcount;
263  }
264  /* Store the count of successfully parsed tags */
265  n->count = tcount;
266 }
267 
268 static unsigned int
270 {
271  return n ? ((ExifMnoteDataFuji *) n)->count : 0;
272 }
273 
274 static unsigned int
276 {
277  ExifMnoteDataFuji *note = (ExifMnoteDataFuji *) d;
278 
279  if (!note) return 0;
280  if (note->count <= n) return 0;
281  return note->entries[n].tag;
282 }
283 
284 static const char *
286 {
288 
289  if (!n) return NULL;
290  if (i >= n->count) return NULL;
291  return mnote_fuji_tag_get_name (n->entries[i].tag);
292 }
293 
294 static const char *
296 {
298 
299  if (!n) return NULL;
300  if (i >= n->count) return NULL;
301  return mnote_fuji_tag_get_title (n->entries[i].tag);
302 }
303 
304 static const char *
306 {
308 
309  if (!n) return NULL;
310  if (i >= n->count) return NULL;
312 }
313 
314 static void
316 {
317  ExifByteOrder o_orig;
319  unsigned int i;
320 
321  if (!n) return;
322 
323  o_orig = n->order;
324  n->order = o;
325  for (i = 0; i < n->count; i++) {
326  if (n->entries[i].components && (n->entries[i].size/n->entries[i].components < exif_format_get_size (n->entries[i].format)))
327  continue;
328  n->entries[i].order = o;
330  n->entries[i].components, o_orig, o);
331  }
332 }
333 
334 static void
336 {
337  if (n) ((ExifMnoteDataFuji *) n)->offset = o;
338 }
339 
340 int
342 {
343  (void) ed; /* unused */
344  return ((e->size >= 12) && !memcmp (e->data, "FUJIFILM", 8));
345 }
346 
349 {
350  ExifMnoteData *d;
351 
352  if (!mem) return NULL;
353 
354  d = exif_mem_alloc (mem, sizeof (ExifMnoteDataFuji));
355  if (!d) return NULL;
356 
357  exif_mnote_data_construct (d, mem);
358 
359  /* Set up function pointers */
371 
372  return d;
373 }
Defines the ExifByteOrder enum and the associated functions.
ExifByteOrder
Which byte order to use.
@ EXIF_BYTE_ORDER_INTEL
Little-endian byte order.
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
ExifMnoteData * exif_mnote_data_fuji_new(ExifMem *mem)
static char * exif_mnote_data_fuji_get_value(ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen)
static const char * exif_mnote_data_fuji_get_name(ExifMnoteData *d, unsigned int i)
static void exif_mnote_data_fuji_load(ExifMnoteData *en, const unsigned char *buf, unsigned int buf_size)
static void exif_mnote_data_fuji_set_offset(ExifMnoteData *n, unsigned int o)
static const char * exif_mnote_data_fuji_get_description(ExifMnoteData *d, unsigned int i)
static void exif_mnote_data_fuji_save(ExifMnoteData *ne, unsigned char **buf, unsigned int *buf_size)
static unsigned int exif_mnote_data_fuji_count(ExifMnoteData *n)
int exif_mnote_data_fuji_identify(const ExifData *ed, const ExifEntry *e)
Detect if MakerNote is recognized as one handled by the Fuji module.
static const char * exif_mnote_data_fuji_get_title(ExifMnoteData *d, unsigned int i)
static unsigned int exif_mnote_data_fuji_get_id(ExifMnoteData *d, unsigned int n)
static void exif_mnote_data_fuji_free(ExifMnoteData *n)
#define CHECKOVERFLOW(offset, datasize, structsize)
static void exif_mnote_data_fuji_clear(ExifMnoteDataFuji *n)
static void exif_mnote_data_fuji_set_byte_order(ExifMnoteData *d, ExifByteOrder o)
void exif_mnote_data_construct(ExifMnoteData *, ExifMem *mem)
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.
uint32_t ExifLong
EXIF Unsigned Long data type.
Definition: exif-utils.h:54
uint16_t ExifShort
EXIF Unsigned Short data type.
Definition: exif-utils.h:48
char * mnote_fuji_entry_get_value(MnoteFujiEntry *entry, char *val, unsigned int maxlen)
const char * mnote_fuji_tag_get_name(MnoteFujiTag t)
const char * mnote_fuji_tag_get_title(MnoteFujiTag t)
const char * mnote_fuji_tag_get_description(MnoteFujiTag 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
unsigned char * data
Pointer to the raw EXIF data for this entry.
Definition: exif-entry.h:57
unsigned int size
Number of bytes in the buffer at data.
Definition: exif-entry.h:61
MnoteFujiEntry * 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
MnoteFujiTag tag
unsigned char * data
ExifByteOrder order
unsigned int size
unsigned long components

libexif Generated by doxygen