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>
26 #include <libexif/exif-byte-order.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
33 struct _MNoteFujiDataPrivate {
34 ExifByteOrder order;
35 };
36
37 static void
exif_mnote_data_fuji_clear(ExifMnoteDataFuji * n)38 exif_mnote_data_fuji_clear (ExifMnoteDataFuji *n)
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
exif_mnote_data_fuji_free(ExifMnoteData * n)58 exif_mnote_data_fuji_free (ExifMnoteData *n)
59 {
60 if (!n) return;
61
62 exif_mnote_data_fuji_clear ((ExifMnoteDataFuji *) n);
63 }
64
65 static char *
exif_mnote_data_fuji_get_value(ExifMnoteData * d,unsigned int i,char * val,unsigned int maxlen)66 exif_mnote_data_fuji_get_value (ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen)
67 {
68 ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
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
exif_mnote_data_fuji_save(ExifMnoteData * ne,unsigned char ** buf,unsigned int * buf_size)81 exif_mnote_data_fuji_save (ExifMnoteData *ne, unsigned char **buf,
82 unsigned int *buf_size)
83 {
84 ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) ne;
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
exif_mnote_data_fuji_load(ExifMnoteData * en,const unsigned char * buf,unsigned int buf_size)154 exif_mnote_data_fuji_load (ExifMnoteData *en,
155 const unsigned char *buf, unsigned int buf_size)
156 {
157 ExifMnoteDataFuji *n = (ExifMnoteDataFuji*) en;
158 ExifLong c;
159 size_t i, tcount, o, datao;
160
161 if (!n || !buf || !buf_size) {
162 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
163 "ExifMnoteDataFuji", "Short MakerNote");
164 return;
165 }
166 datao = 6 + n->offset;
167 if (CHECKOVERFLOW(datao, buf_size, 12)) {
168 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
169 "ExifMnoteDataFuji", "Short MakerNote");
170 return;
171 }
172
173 n->order = EXIF_BYTE_ORDER_INTEL;
174
175 datao += exif_get_long (buf + datao + 8, EXIF_BYTE_ORDER_INTEL);
176 if (CHECKOVERFLOW(datao, buf_size, 2)) {
177 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
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 */
195 exif_mnote_data_fuji_clear (n);
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)) {
211 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
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 ) {
230 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
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)) {
247 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
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
exif_mnote_data_fuji_count(ExifMnoteData * n)269 exif_mnote_data_fuji_count (ExifMnoteData *n)
270 {
271 return n ? ((ExifMnoteDataFuji *) n)->count : 0;
272 }
273
274 static unsigned int
exif_mnote_data_fuji_get_id(ExifMnoteData * d,unsigned int n)275 exif_mnote_data_fuji_get_id (ExifMnoteData *d, unsigned int n)
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 *
exif_mnote_data_fuji_get_name(ExifMnoteData * d,unsigned int i)285 exif_mnote_data_fuji_get_name (ExifMnoteData *d, unsigned int i)
286 {
287 ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
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 *
exif_mnote_data_fuji_get_title(ExifMnoteData * d,unsigned int i)295 exif_mnote_data_fuji_get_title (ExifMnoteData *d, unsigned int i)
296 {
297 ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
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 *
exif_mnote_data_fuji_get_description(ExifMnoteData * d,unsigned int i)305 exif_mnote_data_fuji_get_description (ExifMnoteData *d, unsigned int i)
306 {
307 ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
308
309 if (!n) return NULL;
310 if (i >= n->count) return NULL;
311 return mnote_fuji_tag_get_description (n->entries[i].tag);
312 }
313
314 static void
exif_mnote_data_fuji_set_byte_order(ExifMnoteData * d,ExifByteOrder o)315 exif_mnote_data_fuji_set_byte_order (ExifMnoteData *d, ExifByteOrder o)
316 {
317 ExifByteOrder o_orig;
318 ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
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;
329 exif_array_set_byte_order (n->entries[i].format, n->entries[i].data,
330 n->entries[i].components, o_orig, o);
331 }
332 }
333
334 static void
exif_mnote_data_fuji_set_offset(ExifMnoteData * n,unsigned int o)335 exif_mnote_data_fuji_set_offset (ExifMnoteData *n, unsigned int o)
336 {
337 if (n) ((ExifMnoteDataFuji *) n)->offset = o;
338 }
339
340 int
exif_mnote_data_fuji_identify(const ExifData * ed,const ExifEntry * e)341 exif_mnote_data_fuji_identify (const ExifData *ed, const ExifEntry *e)
342 {
343 (void) ed; /* unused */
344 return ((e->size >= 12) && !memcmp (e->data, "FUJIFILM", 8));
345 }
346
347 ExifMnoteData *
exif_mnote_data_fuji_new(ExifMem * mem)348 exif_mnote_data_fuji_new (ExifMem *mem)
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 */
360 d->methods.free = exif_mnote_data_fuji_free;
361 d->methods.set_byte_order = exif_mnote_data_fuji_set_byte_order;
362 d->methods.set_offset = exif_mnote_data_fuji_set_offset;
363 d->methods.load = exif_mnote_data_fuji_load;
364 d->methods.save = exif_mnote_data_fuji_save;
365 d->methods.count = exif_mnote_data_fuji_count;
366 d->methods.get_id = exif_mnote_data_fuji_get_id;
367 d->methods.get_name = exif_mnote_data_fuji_get_name;
368 d->methods.get_title = exif_mnote_data_fuji_get_title;
369 d->methods.get_description = exif_mnote_data_fuji_get_description;
370 d->methods.get_value = exif_mnote_data_fuji_get_value;
371
372 return d;
373 }
374