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 /* Remove any old entries */
187 exif_mnote_data_fuji_clear (n);
188
189 /* Reserve enough space for all the possible MakerNote tags */
190 n->entries = exif_mem_alloc (en->mem, sizeof (MnoteFujiEntry) * c);
191 if (!n->entries) {
192 EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteDataFuji", sizeof (MnoteFujiEntry) * c);
193 return;
194 }
195
196 /* Parse all c entries, storing ones that are successfully parsed */
197 tcount = 0;
198 for (i = c, o = datao; i; --i, o += 12) {
199 size_t s;
200
201 memset(&n->entries[tcount], 0, sizeof(MnoteFujiEntry));
202 if (CHECKOVERFLOW(o, buf_size, 12)) {
203 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
204 "ExifMnoteDataFuji", "Short MakerNote");
205 break;
206 }
207
208 n->entries[tcount].tag = exif_get_short (buf + o, n->order);
209 n->entries[tcount].format = exif_get_short (buf + o + 2, n->order);
210 n->entries[tcount].components = exif_get_long (buf + o + 4, n->order);
211 n->entries[tcount].order = n->order;
212
213 exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataFuji",
214 "Loading entry 0x%x ('%s')...", n->entries[tcount].tag,
215 mnote_fuji_tag_get_name (n->entries[tcount].tag));
216
217 /* Check if we overflow the multiplication. Use buf_size as the max size for integer overflow detection,
218 * we will check the buffer sizes closer later. */
219 if ( exif_format_get_size (n->entries[tcount].format) &&
220 buf_size / exif_format_get_size (n->entries[tcount].format) < n->entries[tcount].components
221 ) {
222 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
223 "ExifMnoteDataFuji", "Tag size overflow detected (%u * %lu)", exif_format_get_size (n->entries[tcount].format), n->entries[tcount].components);
224 continue;
225 }
226 /*
227 * Size? If bigger than 4 bytes, the actual data is not
228 * in the entry but somewhere else (offset).
229 */
230 s = exif_format_get_size (n->entries[tcount].format) * n->entries[tcount].components;
231 n->entries[tcount].size = s;
232 if (s) {
233 size_t dataofs = o + 8;
234 if (s > 4)
235 /* The data in this case is merely a pointer */
236 dataofs = exif_get_long (buf + dataofs, n->order) + 6 + n->offset;
237
238 if (CHECKOVERFLOW(dataofs, buf_size, s)) {
239 exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
240 "ExifMnoteDataFuji", "Tag data past end of "
241 "buffer (%u >= %u)", (unsigned)(dataofs + s), buf_size);
242 continue;
243 }
244
245 n->entries[tcount].data = exif_mem_alloc (en->mem, s);
246 if (!n->entries[tcount].data) {
247 EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteDataFuji", s);
248 continue;
249 }
250 memcpy (n->entries[tcount].data, buf + dataofs, s);
251 }
252
253 /* Tag was successfully parsed */
254 ++tcount;
255 }
256 /* Store the count of successfully parsed tags */
257 n->count = tcount;
258 }
259
260 static unsigned int
exif_mnote_data_fuji_count(ExifMnoteData * n)261 exif_mnote_data_fuji_count (ExifMnoteData *n)
262 {
263 return n ? ((ExifMnoteDataFuji *) n)->count : 0;
264 }
265
266 static unsigned int
exif_mnote_data_fuji_get_id(ExifMnoteData * d,unsigned int n)267 exif_mnote_data_fuji_get_id (ExifMnoteData *d, unsigned int n)
268 {
269 ExifMnoteDataFuji *note = (ExifMnoteDataFuji *) d;
270
271 if (!note) return 0;
272 if (note->count <= n) return 0;
273 return note->entries[n].tag;
274 }
275
276 static const char *
exif_mnote_data_fuji_get_name(ExifMnoteData * d,unsigned int i)277 exif_mnote_data_fuji_get_name (ExifMnoteData *d, unsigned int i)
278 {
279 ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
280
281 if (!n) return NULL;
282 if (i >= n->count) return NULL;
283 return mnote_fuji_tag_get_name (n->entries[i].tag);
284 }
285
286 static const char *
exif_mnote_data_fuji_get_title(ExifMnoteData * d,unsigned int i)287 exif_mnote_data_fuji_get_title (ExifMnoteData *d, unsigned int i)
288 {
289 ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
290
291 if (!n) return NULL;
292 if (i >= n->count) return NULL;
293 return mnote_fuji_tag_get_title (n->entries[i].tag);
294 }
295
296 static const char *
exif_mnote_data_fuji_get_description(ExifMnoteData * d,unsigned int i)297 exif_mnote_data_fuji_get_description (ExifMnoteData *d, unsigned int i)
298 {
299 ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
300
301 if (!n) return NULL;
302 if (i >= n->count) return NULL;
303 return mnote_fuji_tag_get_description (n->entries[i].tag);
304 }
305
306 static void
exif_mnote_data_fuji_set_byte_order(ExifMnoteData * d,ExifByteOrder o)307 exif_mnote_data_fuji_set_byte_order (ExifMnoteData *d, ExifByteOrder o)
308 {
309 ExifByteOrder o_orig;
310 ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
311 unsigned int i;
312
313 if (!n) return;
314
315 o_orig = n->order;
316 n->order = o;
317 for (i = 0; i < n->count; i++) {
318 if (n->entries[i].components && (n->entries[i].size/n->entries[i].components < exif_format_get_size (n->entries[i].format)))
319 continue;
320 n->entries[i].order = o;
321 exif_array_set_byte_order (n->entries[i].format, n->entries[i].data,
322 n->entries[i].components, o_orig, o);
323 }
324 }
325
326 static void
exif_mnote_data_fuji_set_offset(ExifMnoteData * n,unsigned int o)327 exif_mnote_data_fuji_set_offset (ExifMnoteData *n, unsigned int o)
328 {
329 if (n) ((ExifMnoteDataFuji *) n)->offset = o;
330 }
331
332 int
exif_mnote_data_fuji_identify(const ExifData * ed,const ExifEntry * e)333 exif_mnote_data_fuji_identify (const ExifData *ed, const ExifEntry *e)
334 {
335 (void) ed; /* unused */
336 return ((e->size >= 12) && !memcmp (e->data, "FUJIFILM", 8));
337 }
338
339 ExifMnoteData *
exif_mnote_data_fuji_new(ExifMem * mem)340 exif_mnote_data_fuji_new (ExifMem *mem)
341 {
342 ExifMnoteData *d;
343
344 if (!mem) return NULL;
345
346 d = exif_mem_alloc (mem, sizeof (ExifMnoteDataFuji));
347 if (!d) return NULL;
348
349 exif_mnote_data_construct (d, mem);
350
351 /* Set up function pointers */
352 d->methods.free = exif_mnote_data_fuji_free;
353 d->methods.set_byte_order = exif_mnote_data_fuji_set_byte_order;
354 d->methods.set_offset = exif_mnote_data_fuji_set_offset;
355 d->methods.load = exif_mnote_data_fuji_load;
356 d->methods.save = exif_mnote_data_fuji_save;
357 d->methods.count = exif_mnote_data_fuji_count;
358 d->methods.get_id = exif_mnote_data_fuji_get_id;
359 d->methods.get_name = exif_mnote_data_fuji_get_name;
360 d->methods.get_title = exif_mnote_data_fuji_get_title;
361 d->methods.get_description = exif_mnote_data_fuji_get_description;
362 d->methods.get_value = exif_mnote_data_fuji_get_value;
363
364 return d;
365 }
366