/src/libexif/libexif/olympus/exif-mnote-data-olympus.c
Line | Count | Source |
1 | | /* exif-mnote-data-olympus.c |
2 | | * |
3 | | * Copyright (c) 2002, 2003 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 | | * SPDX-License-Identifier: LGPL-2.0-or-later |
21 | | */ |
22 | | |
23 | | #include <config.h> |
24 | | #include "exif-mnote-data-olympus.h" |
25 | | |
26 | | #include <stdlib.h> |
27 | | #include <string.h> |
28 | | #include <stdio.h> |
29 | | |
30 | | #include <libexif/exif-utils.h> |
31 | | #include <libexif/exif-data.h> |
32 | | |
33 | | /* Uncomment this to fix a problem with Sanyo MakerNotes. It's probably best |
34 | | * not to in most cases because it seems to only affect the thumbnail tag |
35 | | * which is duplicated in IFD 1, and fixing the offset could actually cause |
36 | | * problems with other software that expects the broken form. |
37 | | */ |
38 | | /*#define EXIF_OVERCOME_SANYO_OFFSET_BUG */ |
39 | | |
40 | 148k | #define CHECKOVERFLOW(offset,datasize,structsize) (( (offset) >= (datasize)) || ((structsize) > (datasize)) || ((offset) > (datasize) - (structsize) )) |
41 | | |
42 | | static enum OlympusVersion |
43 | | exif_mnote_data_olympus_identify_variant (const unsigned char *buf, |
44 | | unsigned int buf_size); |
45 | | |
46 | | |
47 | | static void |
48 | | exif_mnote_data_olympus_clear (ExifMnoteDataOlympus *n) |
49 | 7.33k | { |
50 | 7.33k | ExifMnoteData *d = (ExifMnoteData *) n; |
51 | 7.33k | unsigned int i; |
52 | | |
53 | 7.33k | if (!n) return; |
54 | | |
55 | 7.33k | if (n->entries) { |
56 | 95.4k | for (i = 0; i < n->count; i++) |
57 | 91.8k | if (n->entries[i].data) { |
58 | 35.4k | exif_mem_free (d->mem, n->entries[i].data); |
59 | 35.4k | n->entries[i].data = NULL; |
60 | 35.4k | } |
61 | 3.57k | exif_mem_free (d->mem, n->entries); |
62 | 3.57k | n->entries = NULL; |
63 | 3.57k | n->count = 0; |
64 | 3.57k | } |
65 | 7.33k | } |
66 | | |
67 | | static void |
68 | | exif_mnote_data_olympus_free (ExifMnoteData *n) |
69 | 3.76k | { |
70 | 3.76k | if (!n) return; |
71 | | |
72 | 3.76k | exif_mnote_data_olympus_clear ((ExifMnoteDataOlympus *) n); |
73 | 3.76k | } |
74 | | |
75 | | static char * |
76 | | exif_mnote_data_olympus_get_value (ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen) |
77 | 52.0k | { |
78 | 52.0k | ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d; |
79 | | |
80 | 52.0k | if (!d || !val) return NULL; |
81 | 52.0k | if (i >= n->count) return NULL; |
82 | | /* |
83 | | exif_log (d->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus", |
84 | | "Querying value for tag '%s'...", |
85 | | mnote_olympus_tag_get_name (n->entries[i].tag)); |
86 | | */ |
87 | 52.0k | return mnote_olympus_entry_get_value (&n->entries[i], val, maxlen); |
88 | 52.0k | } |
89 | | |
90 | | |
91 | | |
92 | | |
93 | | /** |
94 | | * @brief save the MnoteData from ne to buf |
95 | | * |
96 | | * @param ne extract the data from this structure |
97 | | * @param *buf write the mnoteData to this buffer (buffer will be allocated) |
98 | | * @param buf_size the size of the buffer |
99 | | */ |
100 | | static void |
101 | | exif_mnote_data_olympus_save (ExifMnoteData *ne, |
102 | | unsigned char **buf, unsigned int *buf_size) |
103 | 0 | { |
104 | 0 | ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) ne; |
105 | 0 | size_t i, o, s, doff, base = 0, o2 = 6 + 2; |
106 | 0 | size_t datao = 0; |
107 | 0 | unsigned char *t; |
108 | 0 | size_t ts; |
109 | |
|
110 | 0 | if (!n || !buf || !buf_size) return; |
111 | | |
112 | | /* |
113 | | * Allocate enough memory for all entries and the number of entries. |
114 | | */ |
115 | 0 | *buf_size = 6 + 2 + 2 + n->count * 12; |
116 | 0 | switch (n->version) { |
117 | 0 | case olympusV1: |
118 | 0 | case sanyoV1: |
119 | 0 | case epsonV1: |
120 | 0 | *buf = exif_mem_alloc (ne->mem, *buf_size); |
121 | 0 | if (!*buf) { |
122 | 0 | EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size); |
123 | 0 | return; |
124 | 0 | } |
125 | | |
126 | | /* Write the header and the number of entries. */ |
127 | 0 | strcpy ((char *)*buf, n->version==sanyoV1?"SANYO": |
128 | 0 | (n->version==epsonV1?"EPSON":"OLYMP")); |
129 | 0 | exif_set_short (*buf + 6, n->order, (ExifShort) 1); |
130 | 0 | datao = n->offset; |
131 | 0 | break; |
132 | | |
133 | 0 | case olympusV2: |
134 | 0 | *buf_size += 8-6 + 4; |
135 | 0 | *buf = exif_mem_alloc (ne->mem, *buf_size); |
136 | 0 | if (!*buf) { |
137 | 0 | EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size); |
138 | 0 | return; |
139 | 0 | } |
140 | | |
141 | | /* Write the header and the number of entries. */ |
142 | 0 | strcpy ((char *)*buf, "OLYMPUS"); |
143 | 0 | exif_set_short (*buf + 8, n->order, (ExifShort) ( |
144 | 0 | (n->order == EXIF_BYTE_ORDER_INTEL) ? |
145 | 0 | ('I' << 8) | 'I' : |
146 | 0 | ('M' << 8) | 'M')); |
147 | 0 | exif_set_short (*buf + 10, n->order, (ExifShort) 3); |
148 | 0 | o2 += 4; |
149 | 0 | break; |
150 | | |
151 | 0 | case nikonV1: |
152 | 0 | base = MNOTE_NIKON1_TAG_BASE; |
153 | | |
154 | | /* v1 has offsets based to main IFD, not makernote IFD */ |
155 | 0 | datao += n->offset + 10; |
156 | | /* subtract the size here, so the increment in the next case will not harm us */ |
157 | 0 | *buf_size -= 8 + 2; |
158 | | /* fall through */ |
159 | | /* Fall through to nikonV2 handler */ |
160 | 0 | case nikonV2: |
161 | | /* Write out V0 files in V2 format */ |
162 | 0 | case nikonV0: |
163 | 0 | *buf_size += 8 + 2; |
164 | 0 | *buf_size += 4; /* Next IFD pointer */ |
165 | 0 | *buf = exif_mem_alloc (ne->mem, *buf_size); |
166 | 0 | if (!*buf) { |
167 | 0 | EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", *buf_size); |
168 | 0 | return; |
169 | 0 | } |
170 | | |
171 | | /* Write the header and the number of entries. */ |
172 | 0 | strcpy ((char *)*buf, "Nikon"); |
173 | 0 | (*buf)[6] = (unsigned char)n->version; |
174 | |
|
175 | 0 | if (n->version != nikonV1) { |
176 | 0 | exif_set_short (*buf + 10, n->order, (ExifShort) ( |
177 | 0 | (n->order == EXIF_BYTE_ORDER_INTEL) ? |
178 | 0 | ('I' << 8) | 'I' : |
179 | 0 | ('M' << 8) | 'M')); |
180 | 0 | exif_set_short (*buf + 12, n->order, (ExifShort) 0x2A); |
181 | 0 | exif_set_long (*buf + 14, n->order, (ExifShort) 8); |
182 | 0 | o2 += 2 + 8; |
183 | 0 | } |
184 | 0 | datao -= 10; |
185 | | /* Reset next IFD pointer */ |
186 | 0 | exif_set_long (*buf + o2 + 2 + n->count * 12, n->order, 0); |
187 | 0 | break; |
188 | | |
189 | 0 | default: |
190 | 0 | return; |
191 | 0 | } |
192 | | |
193 | 0 | exif_set_short (*buf + o2, n->order, (ExifShort) n->count); |
194 | 0 | o2 += 2; |
195 | | |
196 | | /* Save each entry */ |
197 | 0 | for (i = 0; i < n->count; i++) { |
198 | 0 | o = o2 + i * 12; |
199 | 0 | exif_set_short (*buf + o + 0, n->order, |
200 | 0 | (ExifShort) (n->entries[i].tag - base)); |
201 | 0 | exif_set_short (*buf + o + 2, n->order, |
202 | 0 | (ExifShort) n->entries[i].format); |
203 | 0 | exif_set_long (*buf + o + 4, n->order, |
204 | 0 | n->entries[i].components); |
205 | 0 | o += 8; |
206 | 0 | s = exif_format_get_size (n->entries[i].format) * |
207 | 0 | n->entries[i].components; |
208 | 0 | if (s > 65536) { |
209 | | /* Corrupt data: EXIF data size is limited to the |
210 | | * maximum size of a JPEG segment (64 kb). |
211 | | */ |
212 | 0 | continue; |
213 | 0 | } |
214 | 0 | if (s > 4) { |
215 | 0 | doff = *buf_size; |
216 | 0 | ts = *buf_size + s; |
217 | 0 | t = exif_mem_realloc (ne->mem, *buf, |
218 | 0 | sizeof (char) * ts); |
219 | 0 | if (!t) { |
220 | 0 | EXIF_LOG_NO_MEMORY(ne->log, "ExifMnoteDataOlympus", ts); |
221 | 0 | return; |
222 | 0 | } |
223 | 0 | *buf = t; |
224 | 0 | *buf_size = ts; |
225 | 0 | exif_set_long (*buf + o, n->order, datao + doff); |
226 | 0 | } else |
227 | 0 | doff = o; |
228 | | |
229 | | /* Write the data. */ |
230 | 0 | if (n->entries[i].data) { |
231 | 0 | memcpy (*buf + doff, n->entries[i].data, s); |
232 | 0 | } else { |
233 | | /* Most certainly damaged input file */ |
234 | 0 | memset (*buf + doff, 0, s); |
235 | 0 | } |
236 | 0 | } |
237 | 0 | } |
238 | | |
239 | | static void |
240 | | exif_mnote_data_olympus_load (ExifMnoteData *en, |
241 | | const unsigned char *buf, unsigned int buf_size) |
242 | 3.76k | { |
243 | 3.76k | ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) en; |
244 | 3.76k | ExifShort c; |
245 | 3.76k | size_t i, tcount, o, o2, datao = 6, base = 0; |
246 | | |
247 | 3.76k | if (!n) return; |
248 | | |
249 | 3.76k | if (!buf || !buf_size) { |
250 | 0 | exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, |
251 | 0 | "ExifMnoteDataOlympus", "Short MakerNote"); |
252 | 0 | return; |
253 | 0 | } |
254 | 3.76k | o2 = 6 + n->offset; /* Start of interesting data */ |
255 | 3.76k | if (CHECKOVERFLOW(o2,buf_size,10)) { |
256 | 4 | exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, |
257 | 4 | "ExifMnoteDataOlympus", "Short MakerNote"); |
258 | 4 | return; |
259 | 4 | } |
260 | | |
261 | | /* |
262 | | * Olympus headers start with "OLYMP" and need to have at least |
263 | | * a size of 22 bytes (6 for 'OLYMP', 2 other bytes, 2 for the |
264 | | * number of entries, and 12 for one entry. |
265 | | * |
266 | | * Sanyo format is identical and uses identical tags except that |
267 | | * header starts with "SANYO". |
268 | | * |
269 | | * Epson format is identical and uses identical tags except that |
270 | | * header starts with "EPSON". |
271 | | * |
272 | | * Nikon headers start with "Nikon" (6 bytes including '\0'), |
273 | | * version number (1 or 2). |
274 | | * |
275 | | * Version 1 continues with 0, 1, 0, number_of_tags, |
276 | | * or just with number_of_tags (models D1H, D1X...). |
277 | | * |
278 | | * Version 2 continues with an unknown byte (0 or 10), |
279 | | * two unknown bytes (0), "MM" or "II", another byte 0 and |
280 | | * lastly 0x2A. |
281 | | */ |
282 | 3.75k | n->version = exif_mnote_data_olympus_identify_variant(buf+o2, buf_size-o2); |
283 | 3.75k | switch (n->version) { |
284 | 1.20k | case olympusV1: |
285 | 2.44k | case sanyoV1: |
286 | 3.08k | case epsonV1: |
287 | 3.08k | exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus", |
288 | 3.08k | "Parsing Olympus/Sanyo/Epson maker note v1..."); |
289 | | |
290 | | /* The number of entries is at position 8. */ |
291 | 3.08k | if (buf[o2 + 6] == 1) |
292 | 172 | n->order = EXIF_BYTE_ORDER_INTEL; |
293 | 2.91k | else if (buf[o2 + 6 + 1] == 1) |
294 | 33 | n->order = EXIF_BYTE_ORDER_MOTOROLA; |
295 | 3.08k | o2 += 8; |
296 | 3.08k | c = exif_get_short (buf + o2, n->order); |
297 | 3.08k | if ((!(c & 0xFF)) && (c > 0x500)) { |
298 | 663 | if (n->order == EXIF_BYTE_ORDER_INTEL) { |
299 | 629 | n->order = EXIF_BYTE_ORDER_MOTOROLA; |
300 | 629 | } else { |
301 | 34 | n->order = EXIF_BYTE_ORDER_INTEL; |
302 | 34 | } |
303 | 663 | } |
304 | 3.08k | break; |
305 | | |
306 | 451 | case olympusV2: |
307 | | /* Olympus S760, S770 */ |
308 | 451 | datao = o2; |
309 | 451 | o2 += 8; |
310 | 451 | if (CHECKOVERFLOW(o2,buf_size,4)) return; |
311 | 449 | exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus", |
312 | 449 | "Parsing Olympus maker note v2 (0x%02x, %02x, %02x, %02x)...", |
313 | 449 | buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3]); |
314 | | |
315 | 449 | if ((buf[o2] == 'I') && (buf[o2 + 1] == 'I')) |
316 | 2 | n->order = EXIF_BYTE_ORDER_INTEL; |
317 | 447 | else if ((buf[o2] == 'M') && (buf[o2 + 1] == 'M')) |
318 | 1 | n->order = EXIF_BYTE_ORDER_MOTOROLA; |
319 | | |
320 | | /* The number of entries is at position 8+4. */ |
321 | 449 | o2 += 4; |
322 | 449 | break; |
323 | | |
324 | 60 | case nikonV1: |
325 | 60 | o2 += 6; |
326 | 60 | exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus", |
327 | 60 | "Parsing Nikon maker note v1 (0x%02x, %02x, %02x, " |
328 | 60 | "%02x)...", |
329 | 60 | buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3]); |
330 | | |
331 | | /* Skip version number */ |
332 | 60 | o2 += 1; |
333 | | |
334 | | /* Skip an unknown byte (00 or 0A). */ |
335 | 60 | o2 += 1; |
336 | | |
337 | 60 | base = MNOTE_NIKON1_TAG_BASE; |
338 | | /* Fix endianness, if needed */ |
339 | 60 | c = exif_get_short (buf + o2, n->order); |
340 | 60 | if ((!(c & 0xFF)) && (c > 0x500)) { |
341 | 8 | if (n->order == EXIF_BYTE_ORDER_INTEL) { |
342 | 4 | n->order = EXIF_BYTE_ORDER_MOTOROLA; |
343 | 4 | } else { |
344 | 4 | n->order = EXIF_BYTE_ORDER_INTEL; |
345 | 4 | } |
346 | 8 | } |
347 | 60 | break; |
348 | | |
349 | 114 | case nikonV2: |
350 | 114 | o2 += 6; |
351 | 114 | if (CHECKOVERFLOW(o2,buf_size,12)) return; |
352 | 110 | exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus", |
353 | 110 | "Parsing Nikon maker note v2 (0x%02x, %02x, %02x, " |
354 | 110 | "%02x, %02x, %02x, %02x, %02x)...", |
355 | 110 | buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3], |
356 | 110 | buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]); |
357 | | |
358 | | /* Skip version number */ |
359 | 110 | o2 += 1; |
360 | | |
361 | | /* Skip an unknown byte (00 or 0A). */ |
362 | 110 | o2 += 1; |
363 | | |
364 | | /* Skip 2 unknown bytes (00 00). */ |
365 | 110 | o2 += 2; |
366 | | |
367 | | /* |
368 | | * Byte order. From here the data offset |
369 | | * gets calculated. |
370 | | */ |
371 | 110 | datao = o2; |
372 | 110 | if (!strncmp ((char *)&buf[o2], "II", 2)) |
373 | 59 | n->order = EXIF_BYTE_ORDER_INTEL; |
374 | 51 | else if (!strncmp ((char *)&buf[o2], "MM", 2)) |
375 | 19 | n->order = EXIF_BYTE_ORDER_MOTOROLA; |
376 | 32 | else { |
377 | 32 | exif_log (en->log, EXIF_LOG_CODE_DEBUG, |
378 | 32 | "ExifMnoteDataOlympus", "Unknown " |
379 | 32 | "byte order '%c%c'", buf[o2], |
380 | 32 | buf[o2 + 1]); |
381 | 32 | return; |
382 | 32 | } |
383 | 78 | o2 += 2; |
384 | | |
385 | | /* Skip 2 unknown bytes (00 2A). */ |
386 | 78 | o2 += 2; |
387 | | |
388 | | /* Go to where the number of entries is. */ |
389 | 78 | if (CHECKOVERFLOW(o2,buf_size,exif_get_long (buf + o2, n->order))) return; |
390 | 18 | o2 = datao + exif_get_long (buf + o2, n->order); |
391 | 18 | break; |
392 | | |
393 | 16 | case nikonV0: |
394 | 16 | exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus", |
395 | 16 | "Parsing Nikon maker note v0 (0x%02x, %02x, %02x, " |
396 | 16 | "%02x, %02x, %02x, %02x, %02x)...", |
397 | 16 | buf[o2 + 0], buf[o2 + 1], buf[o2 + 2], buf[o2 + 3], |
398 | 16 | buf[o2 + 4], buf[o2 + 5], buf[o2 + 6], buf[o2 + 7]); |
399 | | /* 00 1b is # of entries in Motorola order - the rest should also be in MM order */ |
400 | 16 | n->order = EXIF_BYTE_ORDER_MOTOROLA; |
401 | 16 | break; |
402 | | |
403 | 30 | default: |
404 | 30 | exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataOlympus", |
405 | 30 | "Unknown Olympus variant %i.", n->version); |
406 | 30 | return; |
407 | 3.75k | } |
408 | | |
409 | | /* Sanity check the offset */ |
410 | 3.63k | if (CHECKOVERFLOW(o2,buf_size,2)) { |
411 | 33 | exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, |
412 | 33 | "ExifMnoteOlympus", "Short MakerNote"); |
413 | 33 | return; |
414 | 33 | } |
415 | | |
416 | | /* Read the number of tags */ |
417 | 3.59k | c = exif_get_short (buf + o2, n->order); |
418 | 3.59k | o2 += 2; |
419 | | |
420 | | /* Just use an arbitrary max tag limit here to avoid needing to much memory or time. There are 150 named tags currently. |
421 | | * The format allows specifying the same range of memory as often as it can, so this multiplies quickly. */ |
422 | 3.59k | if (c > 300) { |
423 | 26 | exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifMnoteOlympus", "Too much tags (%d) in Olympus MakerNote", c); |
424 | 26 | return; |
425 | 26 | } |
426 | | |
427 | | /* Remove any old entries */ |
428 | 3.57k | exif_mnote_data_olympus_clear (n); |
429 | | |
430 | | /* Reserve enough space for all the possible MakerNote tags */ |
431 | 3.57k | n->entries = exif_mem_alloc (en->mem, sizeof (MnoteOlympusEntry) * c); |
432 | 3.57k | if (!n->entries) { |
433 | 0 | EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteOlympus", sizeof (MnoteOlympusEntry) * c); |
434 | 0 | return; |
435 | 0 | } |
436 | | |
437 | | /* Parse all c entries, storing ones that are successfully parsed */ |
438 | 3.57k | tcount = 0; |
439 | 102k | for (i = c, o = o2; i; --i, o += 12) { |
440 | 102k | size_t s; |
441 | 102k | memset(&n->entries[tcount], 0, sizeof(MnoteOlympusEntry)); |
442 | 102k | if (CHECKOVERFLOW(o, buf_size, 12)) { |
443 | 2.97k | exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, |
444 | 2.97k | "ExifMnoteOlympus", "Short MakerNote"); |
445 | 2.97k | break; |
446 | 2.97k | } |
447 | | |
448 | 99.3k | n->entries[tcount].tag = exif_get_short (buf + o, n->order) + base; |
449 | 99.3k | n->entries[tcount].format = exif_get_short (buf + o + 2, n->order); |
450 | 99.3k | n->entries[tcount].components = exif_get_long (buf + o + 4, n->order); |
451 | 99.3k | n->entries[tcount].order = n->order; |
452 | | |
453 | 99.3k | exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus", |
454 | 99.3k | "Loading entry 0x%x ('%s')...", n->entries[tcount].tag, |
455 | 99.3k | mnote_olympus_tag_get_name (n->entries[tcount].tag)); |
456 | | /* exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteOlympus", |
457 | | "0x%x %d %ld*(%d)", |
458 | | n->entries[tcount].tag, |
459 | | n->entries[tcount].format, |
460 | | n->entries[tcount].components, |
461 | | (int)exif_format_get_size(n->entries[tcount].format)); */ |
462 | | |
463 | | /* Check if we overflow the multiplication. Use buf_size as the max size for integer overflow detection, |
464 | | * we will check the buffer sizes closer later. */ |
465 | 99.3k | if (exif_format_get_size (n->entries[tcount].format) && |
466 | 50.7k | buf_size / exif_format_get_size (n->entries[tcount].format) < n->entries[tcount].components |
467 | 99.3k | ) { |
468 | 5.16k | exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifMnoteOlympus", "Tag size overflow detected (%u * %lu)", exif_format_get_size (n->entries[tcount].format), n->entries[tcount].components); |
469 | 5.16k | continue; |
470 | 5.16k | } |
471 | | /* |
472 | | * Size? If bigger than 4 bytes, the actual data is not |
473 | | * in the entry but somewhere else (offset). |
474 | | */ |
475 | 94.2k | s = exif_format_get_size (n->entries[tcount].format) * |
476 | 94.2k | n->entries[tcount].components; |
477 | 94.2k | n->entries[tcount].size = s; |
478 | 94.2k | if (s) { |
479 | 37.8k | size_t dataofs = o + 8; |
480 | 37.8k | if (s > 4) { |
481 | | /* The data in this case is merely a pointer */ |
482 | 19.4k | dataofs = exif_get_long (buf + dataofs, n->order) + datao; |
483 | | #ifdef EXIF_OVERCOME_SANYO_OFFSET_BUG |
484 | | /* Some Sanyo models (e.g. VPC-C5, C40) suffer from a bug when |
485 | | * writing the offset for the MNOTE_OLYMPUS_TAG_THUMBNAILIMAGE |
486 | | * tag in its MakerNote. The offset is actually the absolute |
487 | | * position in the file instead of the position within the IFD. |
488 | | */ |
489 | | if (dataofs > (buf_size - s) && n->version == sanyoV1) { |
490 | | /* fix pointer */ |
491 | | dataofs -= datao + 6; |
492 | | exif_log (en->log, EXIF_LOG_CODE_DEBUG, |
493 | | "ExifMnoteOlympus", |
494 | | "Inconsistent thumbnail tag offset; attempting to recover"); |
495 | | } |
496 | | #endif |
497 | 19.4k | } |
498 | 37.8k | if (CHECKOVERFLOW(dataofs, buf_size, s)) { |
499 | 2.36k | exif_log (en->log, EXIF_LOG_CODE_DEBUG, |
500 | 2.36k | "ExifMnoteOlympus", |
501 | 2.36k | "Tag data past end of buffer (%u > %u)", |
502 | 2.36k | (unsigned)(dataofs + s), buf_size); |
503 | 2.36k | continue; |
504 | 2.36k | } |
505 | | |
506 | 35.4k | n->entries[tcount].data = exif_mem_alloc (en->mem, s); |
507 | 35.4k | if (!n->entries[tcount].data) { |
508 | 0 | EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteOlympus", s); |
509 | 0 | continue; |
510 | 0 | } |
511 | 35.4k | memcpy (n->entries[tcount].data, buf + dataofs, s); |
512 | 35.4k | } |
513 | | |
514 | | /* Tag was successfully parsed */ |
515 | 91.8k | ++tcount; |
516 | 91.8k | } |
517 | | /* Store the count of successfully parsed tags */ |
518 | 3.57k | n->count = tcount; |
519 | 3.57k | } |
520 | | |
521 | | static unsigned int |
522 | | exif_mnote_data_olympus_count (ExifMnoteData *n) |
523 | 3.76k | { |
524 | 3.76k | return n ? ((ExifMnoteDataOlympus *) n)->count : 0; |
525 | 3.76k | } |
526 | | |
527 | | static unsigned int |
528 | | exif_mnote_data_olympus_get_id (ExifMnoteData *d, unsigned int n) |
529 | 0 | { |
530 | 0 | ExifMnoteDataOlympus *note = (ExifMnoteDataOlympus *) d; |
531 | |
|
532 | 0 | if (!note) return 0; |
533 | 0 | if (note->count <= n) return 0; |
534 | 0 | return note->entries[n].tag; |
535 | 0 | } |
536 | | |
537 | | static const char * |
538 | | exif_mnote_data_olympus_get_name (ExifMnoteData *d, unsigned int i) |
539 | 53.0k | { |
540 | 53.0k | ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d; |
541 | | |
542 | 53.0k | if (!n) return NULL; |
543 | 53.0k | if (i >= n->count) return NULL; |
544 | 53.0k | return mnote_olympus_tag_get_name (n->entries[i].tag); |
545 | 53.0k | } |
546 | | |
547 | | static const char * |
548 | | exif_mnote_data_olympus_get_title (ExifMnoteData *d, unsigned int i) |
549 | 52.0k | { |
550 | 52.0k | ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d; |
551 | | |
552 | 52.0k | if (!n) return NULL; |
553 | 52.0k | if (i >= n->count) return NULL; |
554 | 52.0k | return mnote_olympus_tag_get_title (n->entries[i].tag); |
555 | 52.0k | } |
556 | | |
557 | | static const char * |
558 | | exif_mnote_data_olympus_get_description (ExifMnoteData *d, unsigned int i) |
559 | 52.0k | { |
560 | 52.0k | ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d; |
561 | | |
562 | 52.0k | if (!n) return NULL; |
563 | 52.0k | if (i >= n->count) return NULL; |
564 | 52.0k | return mnote_olympus_tag_get_description (n->entries[i].tag); |
565 | 52.0k | } |
566 | | |
567 | | static void |
568 | | exif_mnote_data_olympus_set_byte_order (ExifMnoteData *d, ExifByteOrder o) |
569 | 3.76k | { |
570 | 3.76k | ExifByteOrder o_orig; |
571 | 3.76k | ExifMnoteDataOlympus *n = (ExifMnoteDataOlympus *) d; |
572 | 3.76k | unsigned int i; |
573 | | |
574 | 3.76k | if (!n) return; |
575 | | |
576 | 3.76k | o_orig = n->order; |
577 | 3.76k | n->order = o; |
578 | 3.76k | for (i = 0; i < n->count; i++) { |
579 | 0 | if (n->entries[i].components && (n->entries[i].size/n->entries[i].components < exif_format_get_size (n->entries[i].format))) |
580 | 0 | continue; |
581 | 0 | n->entries[i].order = o; |
582 | 0 | exif_array_set_byte_order (n->entries[i].format, n->entries[i].data, |
583 | 0 | n->entries[i].components, o_orig, o); |
584 | 0 | } |
585 | 3.76k | } |
586 | | |
587 | | static void |
588 | | exif_mnote_data_olympus_set_offset (ExifMnoteData *n, unsigned int o) |
589 | 3.76k | { |
590 | 3.76k | if (n) ((ExifMnoteDataOlympus *) n)->offset = o; |
591 | 3.76k | } |
592 | | |
593 | | static enum OlympusVersion |
594 | | exif_mnote_data_olympus_identify_variant (const unsigned char *buf, |
595 | | unsigned int buf_size) |
596 | 10.5k | { |
597 | | /* Olympus, Nikon, Sanyo, Epson */ |
598 | 10.5k | if (buf_size >= 8) { |
599 | | /* Match the terminating NUL character, too */ |
600 | 10.3k | if (!memcmp (buf, "OLYMPUS", 8)) |
601 | 908 | return olympusV2; |
602 | 9.44k | else if (!memcmp (buf, "OLYMP", 6)) |
603 | 2.44k | return olympusV1; |
604 | 6.99k | else if (!memcmp (buf, "SANYO", 6)) |
605 | 2.48k | return sanyoV1; |
606 | 4.51k | else if (!memcmp (buf, "EPSON", 6)) |
607 | 1.29k | return epsonV1; |
608 | 3.21k | else if (!memcmp (buf, "Nikon", 6)) { |
609 | 345 | switch (buf[6]) { |
610 | 123 | case 1: return nikonV1; |
611 | 214 | case 2: return nikonV2; |
612 | 8 | default: return 0; /* Unrecognized Nikon variant */ |
613 | 345 | } |
614 | 345 | } |
615 | 10.3k | } |
616 | | |
617 | | /* Another variant of Nikon */ |
618 | 3.08k | if ((buf_size >= 2) && (buf[0] == 0x00) && (buf[1] == 0x1b)) { |
619 | 456 | return nikonV0; |
620 | 456 | } |
621 | | |
622 | 2.62k | return unrecognized; |
623 | 3.08k | } |
624 | | |
625 | | int |
626 | | exif_mnote_data_olympus_identify (const ExifData *ed, const ExifEntry *e) |
627 | 6.80k | { |
628 | 6.80k | int variant = exif_mnote_data_olympus_identify_variant(e->data, e->size); |
629 | | |
630 | 6.80k | if (variant == nikonV0) { |
631 | | /* This variant needs some extra checking with the Make */ |
632 | 440 | char value[5]; |
633 | 440 | ExifEntry *em = exif_data_get_entry (ed, EXIF_TAG_MAKE); |
634 | 440 | variant = unrecognized; |
635 | | |
636 | 440 | if (em) { |
637 | 58 | const char *v = exif_entry_get_value (em, value, sizeof(value)); |
638 | 58 | if (v && (!strncmp (v, "Nikon", sizeof(value)) || |
639 | 58 | !strncmp (v, "NIKON", sizeof(value)) )) |
640 | | /* When saved, this variant will be written out like the |
641 | | * alternative nikonV2 form above instead |
642 | | */ |
643 | 0 | variant = nikonV0; |
644 | 58 | } |
645 | 440 | } |
646 | | |
647 | 6.80k | return variant; |
648 | 6.80k | } |
649 | | |
650 | | |
651 | | ExifMnoteData * |
652 | | exif_mnote_data_olympus_new (ExifMem *mem) |
653 | 3.76k | { |
654 | 3.76k | ExifMnoteData *d; |
655 | | |
656 | 3.76k | if (!mem) return NULL; |
657 | | |
658 | 3.76k | d = exif_mem_alloc (mem, sizeof (ExifMnoteDataOlympus)); |
659 | 3.76k | if (!d) return NULL; |
660 | | |
661 | 3.76k | exif_mnote_data_construct (d, mem); |
662 | | |
663 | | /* Set up function pointers */ |
664 | 3.76k | d->methods.free = exif_mnote_data_olympus_free; |
665 | 3.76k | d->methods.set_byte_order = exif_mnote_data_olympus_set_byte_order; |
666 | 3.76k | d->methods.set_offset = exif_mnote_data_olympus_set_offset; |
667 | 3.76k | d->methods.load = exif_mnote_data_olympus_load; |
668 | 3.76k | d->methods.save = exif_mnote_data_olympus_save; |
669 | 3.76k | d->methods.count = exif_mnote_data_olympus_count; |
670 | 3.76k | d->methods.get_id = exif_mnote_data_olympus_get_id; |
671 | 3.76k | d->methods.get_name = exif_mnote_data_olympus_get_name; |
672 | 3.76k | d->methods.get_title = exif_mnote_data_olympus_get_title; |
673 | 3.76k | d->methods.get_description = exif_mnote_data_olympus_get_description; |
674 | 3.76k | d->methods.get_value = exif_mnote_data_olympus_get_value; |
675 | | |
676 | 3.76k | return d; |
677 | 3.76k | } |