• 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  * SPDX-License-Identifier: LGPL-2.0-or-later
21  */
22 
23 #include <stdlib.h>
24 #include <string.h>
25 
26 
27 #include <config.h>
28 #include <libexif/exif-byte-order.h>
29 #include <libexif/exif-utils.h>
30 
31 #include "exif-mnote-data-fuji.h"
32 
33 #define CHECKOVERFLOW(offset,datasize,structsize) (( (offset) >= (datasize)) || ((structsize) > (datasize)) || ((offset) > (datasize) - (structsize) ))
34 
35 struct _MNoteFujiDataPrivate {
36 	ExifByteOrder order;
37 };
38 
39 static void
exif_mnote_data_fuji_clear(ExifMnoteDataFuji * n)40 exif_mnote_data_fuji_clear (ExifMnoteDataFuji *n)
41 {
42 	ExifMnoteData *d = (ExifMnoteData *) n;
43 	unsigned int i;
44 
45 	if (!n) return;
46 
47 	if (n->entries) {
48 		for (i = 0; i < n->count; i++)
49 			if (n->entries[i].data) {
50 				exif_mem_free (d->mem, n->entries[i].data);
51 				n->entries[i].data = NULL;
52 			}
53 		exif_mem_free (d->mem, n->entries);
54 		n->entries = NULL;
55 		n->count = 0;
56 	}
57 }
58 
59 static void
exif_mnote_data_fuji_free(ExifMnoteData * n)60 exif_mnote_data_fuji_free (ExifMnoteData *n)
61 {
62 	if (!n) return;
63 
64 	exif_mnote_data_fuji_clear ((ExifMnoteDataFuji *) n);
65 }
66 
67 static char *
exif_mnote_data_fuji_get_value(ExifMnoteData * d,unsigned int i,char * val,unsigned int maxlen)68 exif_mnote_data_fuji_get_value (ExifMnoteData *d, unsigned int i, char *val, unsigned int maxlen)
69 {
70 	ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
71 
72 	if (!d || !val) return NULL;
73 	if (i > n->count -1) return NULL;
74 /*
75 	exif_log (d->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataFuji",
76 		  "Querying value for tag '%s'...",
77 		  mnote_fuji_tag_get_name (n->entries[i].tag));
78 */
79 	return mnote_fuji_entry_get_value (&n->entries[i], val, maxlen);
80 }
81 
82 static void
exif_mnote_data_fuji_save(ExifMnoteData * ne,unsigned char ** buf,unsigned int * buf_size)83 exif_mnote_data_fuji_save (ExifMnoteData *ne, unsigned char **buf,
84 			   unsigned int *buf_size)
85 {
86 	ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) ne;
87 	size_t i, o, s, doff;
88 	unsigned char *t;
89 	size_t ts;
90 
91 	if (!n || !buf || !buf_size) return;
92 
93 	/*
94 	 * Allocate enough memory for all entries and the number
95 	 * of entries.
96 	 */
97 	*buf_size = 8 + 4 + 2 + n->count * 12 + 4;
98 	*buf = exif_mem_alloc (ne->mem, *buf_size);
99 	if (!*buf) {
100 		*buf_size = 0;
101 		return;
102 	}
103 
104 	/*
105 	 * Header: "FUJIFILM" and 4 bytes offset to the first entry.
106 	 * As the first entry will start right thereafter, the offset is 12.
107 	 */
108 	memcpy (*buf, "FUJIFILM", 8);
109 	exif_set_long (*buf + 8, n->order, 12);
110 
111 	/* Save the number of entries */
112 	exif_set_short (*buf + 8 + 4, n->order, (ExifShort) n->count);
113 
114 	/* Save each entry */
115 	for (i = 0; i < n->count; i++) {
116 		o = 8 + 4 + 2 + i * 12;
117 		exif_set_short (*buf + o + 0, n->order, (ExifShort) n->entries[i].tag);
118 		exif_set_short (*buf + o + 2, n->order, (ExifShort) n->entries[i].format);
119 		exif_set_long  (*buf + o + 4, n->order, n->entries[i].components);
120 		o += 8;
121 		s = exif_format_get_size (n->entries[i].format) *
122 						n->entries[i].components;
123 		if (s > 65536) {
124 			/* Corrupt data: EXIF data size is limited to the
125 			 * maximum size of a JPEG segment (64 kb).
126 			 */
127 			continue;
128 		}
129 		if (s > 4) {
130 			ts = *buf_size + s;
131 
132 			/* Ensure even offsets. Set padding bytes to 0. */
133 			if (s & 1) ts += 1;
134 			t = exif_mem_realloc (ne->mem, *buf, ts);
135 			if (!t) {
136 				return;
137 			}
138 			*buf = t;
139 			*buf_size = ts;
140 			doff = *buf_size - s;
141 			if (s & 1) { doff--; *(*buf + *buf_size - 1) = '\0'; }
142 			exif_set_long (*buf + o, n->order, doff);
143 		} else
144 			doff = o;
145 
146 		/*
147 		 * Write the data. Fill unneeded bytes with 0. Do not
148 		 * crash if data is NULL.
149 		 */
150 		if (!n->entries[i].data) memset (*buf + doff, 0, s);
151 		else memcpy (*buf + doff, n->entries[i].data, s);
152 	}
153 }
154 
155 static void
exif_mnote_data_fuji_load(ExifMnoteData * en,const unsigned char * buf,unsigned int buf_size)156 exif_mnote_data_fuji_load (ExifMnoteData *en,
157 	const unsigned char *buf, unsigned int buf_size)
158 {
159 	ExifMnoteDataFuji *n = (ExifMnoteDataFuji*) en;
160 	ExifLong c;
161 	size_t i, tcount, o, datao;
162 
163 	if (!n) return;
164 
165 	if (!buf || !buf_size) {
166 		exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
167 			  "ExifMnoteDataFuji", "Short MakerNote");
168 		return;
169 	}
170 	if (CHECKOVERFLOW(n->offset, buf_size, 6+8+4)) {
171 		exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
172 			  "ExifMnoteDataFuji", "Short MakerNote");
173 		return;
174 	}
175 	datao = 6 + n->offset;
176 
177 	n->order = EXIF_BYTE_ORDER_INTEL;
178 
179 	datao += exif_get_long (buf + datao + 8, EXIF_BYTE_ORDER_INTEL);
180 	if (CHECKOVERFLOW(datao, buf_size, 2)) {
181 		exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
182 			  "ExifMnoteDataFuji", "Short MakerNote");
183 		return;
184 	}
185 
186 	/* Read the number of tags */
187 	c = exif_get_short (buf + datao, EXIF_BYTE_ORDER_INTEL);
188 	datao += 2;
189 
190 	/* Just use an arbitrary max tag limit here to avoid needing to much memory or time. There are 50 named tags currently.
191 	 * Fuji XT2 had 56 entries or so, GFX500 has 68. 150 seems a safe upper bound currently.
192 	 * The format allows specifying the same range of memory as often as it can, so this multiplies quickly. */
193 	if (c > 150) {
194 		exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA, "ExifMnoteDataFuji", "Too much tags (%d) in Fuji MakerNote", c);
195 		return;
196 	}
197 
198 	/* Remove any old entries */
199 	exif_mnote_data_fuji_clear (n);
200 
201 	/* Reserve enough space for all the possible MakerNote tags */
202 	n->entries = exif_mem_alloc (en->mem, sizeof (MnoteFujiEntry) * c);
203 	if (!n->entries) {
204 		EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteDataFuji", sizeof (MnoteFujiEntry) * c);
205 		return;
206 	}
207 
208 	/* Parse all c entries, storing ones that are successfully parsed */
209 	tcount = 0;
210 	for (i = c, o = datao; i; --i, o += 12) {
211 		size_t s;
212 
213 		memset(&n->entries[tcount], 0, sizeof(MnoteFujiEntry));
214 		if (CHECKOVERFLOW(o, buf_size, 12)) {
215 			exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
216 				  "ExifMnoteDataFuji", "Short MakerNote");
217 			break;
218 		}
219 
220 		n->entries[tcount].tag        = exif_get_short (buf + o, n->order);
221 		n->entries[tcount].format     = exif_get_short (buf + o + 2, n->order);
222 		n->entries[tcount].components = exif_get_long (buf + o + 4, n->order);
223 		n->entries[tcount].order      = n->order;
224 
225 		exif_log (en->log, EXIF_LOG_CODE_DEBUG, "ExifMnoteDataFuji",
226 			  "Loading entry 0x%x ('%s')...", n->entries[tcount].tag,
227 			  mnote_fuji_tag_get_name (n->entries[tcount].tag));
228 
229 		/* Check if we overflow the multiplication. Use buf_size as the max size for integer overflow detection,
230 		 * we will check the buffer sizes closer later. */
231 		if (	exif_format_get_size (n->entries[tcount].format) &&
232 			buf_size / exif_format_get_size (n->entries[tcount].format) < n->entries[tcount].components
233 		) {
234 			exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
235 					  "ExifMnoteDataFuji", "Tag size overflow detected (%u * %lu)", exif_format_get_size (n->entries[tcount].format), n->entries[tcount].components);
236 			continue;
237 		}
238 		/*
239 		 * Size? If bigger than 4 bytes, the actual data is not
240 		 * in the entry but somewhere else (offset).
241 		 */
242 		s = exif_format_get_size (n->entries[tcount].format) * n->entries[tcount].components;
243 		n->entries[tcount].size = s;
244 		if (s) {
245 			size_t dataofs = o + 8;
246 			if (s > 4)
247 				/* The data in this case is merely a pointer */
248 				dataofs = exif_get_long (buf + dataofs, n->order) + 6 + n->offset;
249 
250 			if (CHECKOVERFLOW(dataofs, buf_size, s)) {
251 				exif_log (en->log, EXIF_LOG_CODE_CORRUPT_DATA,
252 						  "ExifMnoteDataFuji", "Tag data past end of "
253 					  "buffer (%u >= %u)", (unsigned)(dataofs + s), buf_size);
254 				continue;
255 			}
256 
257 			n->entries[tcount].data = exif_mem_alloc (en->mem, s);
258 			if (!n->entries[tcount].data) {
259 				EXIF_LOG_NO_MEMORY(en->log, "ExifMnoteDataFuji", s);
260 				continue;
261 			}
262 			memcpy (n->entries[tcount].data, buf + dataofs, s);
263 		}
264 
265 		/* Tag was successfully parsed */
266 		++tcount;
267 	}
268 	/* Store the count of successfully parsed tags */
269 	n->count = tcount;
270 }
271 
272 static unsigned int
exif_mnote_data_fuji_count(ExifMnoteData * n)273 exif_mnote_data_fuji_count (ExifMnoteData *n)
274 {
275 	return n ? ((ExifMnoteDataFuji *) n)->count : 0;
276 }
277 
278 static unsigned int
exif_mnote_data_fuji_get_id(ExifMnoteData * d,unsigned int n)279 exif_mnote_data_fuji_get_id (ExifMnoteData *d, unsigned int n)
280 {
281 	ExifMnoteDataFuji *note = (ExifMnoteDataFuji *) d;
282 
283 	if (!note) return 0;
284 	if (note->count <= n) return 0;
285 	return note->entries[n].tag;
286 }
287 
288 static const char *
exif_mnote_data_fuji_get_name(ExifMnoteData * d,unsigned int i)289 exif_mnote_data_fuji_get_name (ExifMnoteData *d, unsigned int i)
290 {
291 	ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
292 
293 	if (!n) return NULL;
294 	if (i >= n->count) return NULL;
295 	return mnote_fuji_tag_get_name (n->entries[i].tag);
296 }
297 
298 static const char *
exif_mnote_data_fuji_get_title(ExifMnoteData * d,unsigned int i)299 exif_mnote_data_fuji_get_title (ExifMnoteData *d, unsigned int i)
300 {
301 	ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
302 
303 	if (!n) return NULL;
304 	if (i >= n->count) return NULL;
305         return mnote_fuji_tag_get_title (n->entries[i].tag);
306 }
307 
308 static const char *
exif_mnote_data_fuji_get_description(ExifMnoteData * d,unsigned int i)309 exif_mnote_data_fuji_get_description (ExifMnoteData *d, unsigned int i)
310 {
311 	ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
312 
313 	if (!n) return NULL;
314 	if (i >= n->count) return NULL;
315         return mnote_fuji_tag_get_description (n->entries[i].tag);
316 }
317 
318 static void
exif_mnote_data_fuji_set_byte_order(ExifMnoteData * d,ExifByteOrder o)319 exif_mnote_data_fuji_set_byte_order (ExifMnoteData *d, ExifByteOrder o)
320 {
321 	ExifByteOrder o_orig;
322 	ExifMnoteDataFuji *n = (ExifMnoteDataFuji *) d;
323 	unsigned int i;
324 
325 	if (!n) return;
326 
327 	o_orig = n->order;
328 	n->order = o;
329 	for (i = 0; i < n->count; i++) {
330 		if (n->entries[i].components && (n->entries[i].size/n->entries[i].components < exif_format_get_size (n->entries[i].format)))
331 			continue;
332 		n->entries[i].order = o;
333 		exif_array_set_byte_order (n->entries[i].format, n->entries[i].data,
334 				n->entries[i].components, o_orig, o);
335 	}
336 }
337 
338 static void
exif_mnote_data_fuji_set_offset(ExifMnoteData * n,unsigned int o)339 exif_mnote_data_fuji_set_offset (ExifMnoteData *n, unsigned int o)
340 {
341 	if (n) ((ExifMnoteDataFuji *) n)->offset = o;
342 }
343 
344 int
exif_mnote_data_fuji_identify(const ExifData * ed,const ExifEntry * e)345 exif_mnote_data_fuji_identify (const ExifData *ed, const ExifEntry *e)
346 {
347 	(void) ed;  /* unused */
348 	return ((e->size >= 12) && !memcmp (e->data, "FUJIFILM", 8));
349 }
350 
351 ExifMnoteData *
exif_mnote_data_fuji_new(ExifMem * mem)352 exif_mnote_data_fuji_new (ExifMem *mem)
353 {
354 	ExifMnoteData *d;
355 
356 	if (!mem) return NULL;
357 
358 	d = exif_mem_alloc (mem, sizeof (ExifMnoteDataFuji));
359 	if (!d) return NULL;
360 
361 	exif_mnote_data_construct (d, mem);
362 
363 	/* Set up function pointers */
364 	d->methods.free            = exif_mnote_data_fuji_free;
365 	d->methods.set_byte_order  = exif_mnote_data_fuji_set_byte_order;
366 	d->methods.set_offset      = exif_mnote_data_fuji_set_offset;
367 	d->methods.load            = exif_mnote_data_fuji_load;
368 	d->methods.save            = exif_mnote_data_fuji_save;
369 	d->methods.count           = exif_mnote_data_fuji_count;
370 	d->methods.get_id          = exif_mnote_data_fuji_get_id;
371 	d->methods.get_name        = exif_mnote_data_fuji_get_name;
372 	d->methods.get_title       = exif_mnote_data_fuji_get_title;
373 	d->methods.get_description = exif_mnote_data_fuji_get_description;
374 	d->methods.get_value       = exif_mnote_data_fuji_get_value;
375 
376 	return d;
377 }
378