• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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