Coverage Report

Created: 2025-12-28 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libexif/libexif/exif-loader.c
Line
Count
Source
1
/* exif-loader.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 <config.h>
24
25
#include <libexif/exif-loader.h>
26
#include <libexif/exif-utils.h>
27
#include <libexif/i18n.h>
28
29
#include <sys/types.h>
30
#include <stdlib.h>
31
#include <string.h>
32
#include <stdio.h>
33
34
#undef JPEG_MARKER_DCT
35
319
#define JPEG_MARKER_DCT  0xc0
36
#undef JPEG_MARKER_DHT
37
517
#define JPEG_MARKER_DHT  0xc4
38
#undef JPEG_MARKER_SOI
39
832k
#define JPEG_MARKER_SOI  0xd8
40
#undef JPEG_MARKER_DQT
41
727
#define JPEG_MARKER_DQT  0xdb
42
#undef JPEG_MARKER_APP0
43
1.87k
#define JPEG_MARKER_APP0 0xe0
44
#undef JPEG_MARKER_APP1
45
1.62k
#define JPEG_MARKER_APP1 0xe1
46
#undef JPEG_MARKER_APP2
47
2.56k
#define JPEG_MARKER_APP2 0xe2
48
#undef JPEG_MARKER_APP4
49
2.96k
#define JPEG_MARKER_APP4 0xe4
50
#undef JPEG_MARKER_APP5
51
3.22k
#define JPEG_MARKER_APP5 0xe5
52
#undef JPEG_MARKER_APP10
53
3.76k
#define JPEG_MARKER_APP10 0xea
54
#undef JPEG_MARKER_APP11
55
4.16k
#define JPEG_MARKER_APP11 0xeb
56
#undef JPEG_MARKER_APP13
57
4.38k
#define JPEG_MARKER_APP13 0xed
58
#undef JPEG_MARKER_APP14
59
4.65k
#define JPEG_MARKER_APP14 0xee
60
#undef JPEG_MARKER_COM
61
4.92k
#define JPEG_MARKER_COM 0xfe
62
63
typedef enum {
64
  EL_READ = 0,
65
  EL_READ_SIZE_BYTE_24,
66
  EL_READ_SIZE_BYTE_16,
67
  EL_READ_SIZE_BYTE_08,
68
  EL_READ_SIZE_BYTE_00,
69
  EL_SKIP_BYTES,
70
  EL_EXIF_FOUND
71
} ExifLoaderState;
72
73
typedef enum {
74
  EL_DATA_FORMAT_UNKNOWN,
75
  EL_DATA_FORMAT_EXIF,
76
  EL_DATA_FORMAT_JPEG,
77
  EL_DATA_FORMAT_FUJI_RAW
78
} ExifLoaderDataFormat;
79
80
/*! \internal */
81
struct _ExifLoader {
82
  ExifLoaderState state;
83
  ExifLoaderDataFormat data_format;
84
85
  /*! Small buffer used for detection of format */
86
  unsigned char b[12];
87
88
  /*! Number of bytes in the small buffer \c b */
89
  unsigned char b_len;
90
91
  unsigned int size;
92
  unsigned char *buf;
93
  unsigned int bytes_read;
94
95
  unsigned int ref_count;
96
97
  ExifLog *log;
98
  ExifMem *mem;
99
};
100
101
/*! Magic number for EXIF header */
102
static const unsigned char ExifHeader[] = {0x45, 0x78, 0x69, 0x66, 0x00, 0x00};
103
104
static void *
105
exif_loader_alloc (ExifLoader *l, unsigned int i)
106
10.9k
{
107
10.9k
  void *d;
108
109
10.9k
  if (!l || !i) 
110
0
    return NULL;
111
112
10.9k
  d = exif_mem_alloc (l->mem, i);
113
10.9k
  if (d) 
114
10.9k
    return d;
115
116
0
  EXIF_LOG_NO_MEMORY (l->log, "ExifLog", i);
117
0
  return NULL;
118
10.9k
}
119
120
void
121
exif_loader_write_file (ExifLoader *l, const char *path)
122
0
{
123
0
  FILE *f;
124
0
  int size;
125
0
  unsigned char data[1024];
126
127
0
  if (!l || !path)
128
0
    return;
129
130
0
  f = fopen (path, "rb");
131
0
  if (!f) {
132
0
    exif_log (l->log, EXIF_LOG_CODE_NONE, "ExifLoader",
133
0
        _("The file '%s' could not be opened."), path);
134
0
    return;
135
0
  }
136
0
  while (1) {
137
0
    size = fread (data, 1, sizeof (data), f);
138
0
    if (size <= 0) 
139
0
      break;
140
0
    if (!exif_loader_write (l, data, size)) 
141
0
      break;
142
0
  }
143
0
  fclose (f);
144
0
}
145
146
static unsigned int
147
exif_loader_copy (ExifLoader *eld, unsigned char *buf, unsigned int len)
148
21.6k
{
149
21.6k
  if (!eld || (len && !buf) || (eld->bytes_read >= eld->size)) 
150
2
    return 0;
151
152
  /* If needed, allocate the buffer. */
153
21.6k
  if (!eld->buf) 
154
10.9k
    eld->buf = exif_loader_alloc (eld, eld->size);
155
21.6k
  if (!eld->buf) 
156
0
    return 0;
157
158
  /* Copy memory */
159
21.6k
  len = MIN (len, eld->size - eld->bytes_read);
160
21.6k
  memcpy (eld->buf + eld->bytes_read, buf, len);
161
21.6k
  eld->bytes_read += len;
162
163
21.6k
  return (eld->bytes_read >= eld->size) ? 0 : 1;
164
21.6k
}
165
166
unsigned char
167
exif_loader_write (ExifLoader *eld, unsigned char *buf, unsigned int len)
168
11.2k
{
169
11.2k
  unsigned int i;
170
171
82.4k
begin:
172
82.4k
  if (!eld || (len && !buf)) 
173
0
    return 0;
174
175
82.4k
  switch (eld->state) {
176
187
  case EL_EXIF_FOUND:
177
187
    return exif_loader_copy (eld, buf, len);
178
997
  case EL_SKIP_BYTES:
179
997
    if (eld->size > len) { 
180
179
      eld->size -= len; 
181
179
      return 1; 
182
179
    }
183
818
    len -= eld->size;
184
818
    buf += eld->size;
185
818
    eld->size = 0;
186
818
    eld->b_len = 0;
187
818
    switch (eld->data_format) {
188
66
    case EL_DATA_FORMAT_FUJI_RAW:
189
66
      eld->state = EL_READ_SIZE_BYTE_24;
190
66
      break;
191
752
    default:
192
752
      eld->state = EL_READ;
193
752
      break;
194
818
    }
195
818
    break;
196
197
80.8k
  case EL_READ:
198
81.3k
  default:
199
81.3k
    break;
200
82.4k
  }
201
202
82.1k
  if (!len)
203
49
    return 1;
204
82.0k
  exif_log (eld->log, EXIF_LOG_CODE_DEBUG, "ExifLoader",
205
82.0k
      "Scanning %i byte(s) of data...", len);
206
207
  /*
208
   * First fill the small buffer. Only continue if the buffer
209
   * is filled. Note that EXIF data contains at least 12 bytes.
210
   */
211
82.0k
  i = MIN (len, sizeof (eld->b) - eld->b_len);
212
82.0k
  if (i) {
213
82.0k
    memcpy (&eld->b[eld->b_len], buf, i);
214
82.0k
    eld->b_len += i;
215
82.0k
    if (eld->b_len < sizeof (eld->b)) 
216
23
      return 1;
217
82.0k
    buf += i;
218
82.0k
    len -= i;
219
82.0k
  }
220
221
82.0k
  switch (eld->data_format) {
222
11.5k
  case EL_DATA_FORMAT_UNKNOWN:
223
224
    /* Check the small buffer against known formats. */
225
11.5k
    if (!memcmp (eld->b, "FUJIFILM", 8)) {
226
227
      /* Skip to byte 84. There is another offset there. */
228
67
      eld->data_format = EL_DATA_FORMAT_FUJI_RAW;
229
67
      eld->size = 84;
230
67
      eld->state = EL_SKIP_BYTES;
231
67
      eld->size = 84;
232
233
11.4k
    } else if (!memcmp (eld->b + 2, ExifHeader, sizeof (ExifHeader))) {
234
235
      /* Read the size (2 bytes). */
236
10.6k
      eld->data_format = EL_DATA_FORMAT_EXIF;
237
10.6k
      eld->state = EL_READ_SIZE_BYTE_08;
238
10.6k
    }
239
82.0k
  default:
240
82.0k
    break;
241
82.0k
  }
242
243
963k
  for (i = 0; i < sizeof (eld->b); i++) {
244
891k
    switch (eld->state) {
245
10.7k
    case EL_EXIF_FOUND:
246
10.7k
      if (!exif_loader_copy (eld, eld->b + i,
247
10.7k
          sizeof (eld->b) - i)) 
248
7
        return 0;
249
10.7k
      return exif_loader_copy (eld, buf, len);
250
7.42k
    case EL_SKIP_BYTES:
251
7.42k
      switch (eld->size) {
252
4.20k
                            case 0:
253
4.20k
              eld->state = EL_READ;
254
4.20k
        i--;   /* reprocess this byte */
255
4.20k
        break;
256
1.13k
                            case 1:
257
1.13k
                                eld->size = 0;
258
1.13k
              eld->state = EL_READ;
259
1.13k
        break;
260
2.08k
                            default:
261
2.08k
                                eld->size--;
262
2.08k
        break;
263
7.42k
      }
264
7.42k
      break;
265
266
7.42k
    case EL_READ_SIZE_BYTE_24:
267
65
      eld->size |= (unsigned int)eld->b[i] << 24;
268
65
      eld->state = EL_READ_SIZE_BYTE_16;
269
65
      break;
270
65
    case EL_READ_SIZE_BYTE_16:
271
65
      eld->size |= (unsigned int)eld->b[i] << 16;
272
65
      eld->state = EL_READ_SIZE_BYTE_08;
273
65
      break;
274
17.2k
    case EL_READ_SIZE_BYTE_08:
275
17.2k
      eld->size |= (unsigned int)eld->b[i] << 8;
276
17.2k
      eld->state = EL_READ_SIZE_BYTE_00;
277
17.2k
      break;
278
17.1k
    case EL_READ_SIZE_BYTE_00:
279
17.1k
      eld->size |= eld->b[i] << 0;
280
17.1k
      switch (eld->data_format) {
281
6.20k
      case EL_DATA_FORMAT_JPEG:
282
6.20k
        eld->state = EL_SKIP_BYTES;
283
6.20k
        if (eld->size < 2) {
284
            /* Actually it's malformed... */
285
2.63k
            eld->size = 0;
286
2.63k
        } else
287
3.56k
            eld->size -= 2;
288
6.20k
        break;
289
65
      case EL_DATA_FORMAT_FUJI_RAW:
290
65
        eld->data_format = EL_DATA_FORMAT_EXIF;
291
65
        eld->state = EL_SKIP_BYTES;
292
65
        if (eld->size < 86) {
293
            /* Actually it's malformed... */
294
7
            eld->size = 0;
295
7
        } else
296
58
            eld->size -= 86; /* and put this in an else */
297
65
        break;
298
10.9k
      case EL_DATA_FORMAT_EXIF:
299
10.9k
        eld->state = EL_EXIF_FOUND;
300
10.9k
        break;
301
0
      default:
302
0
        break;
303
17.1k
      }
304
17.1k
      break;
305
306
839k
    default:
307
839k
      switch (eld->b[i]) {
308
1.62k
      case JPEG_MARKER_APP1:
309
1.62k
        if (!memcmp (eld->b + i + 3, ExifHeader, MIN((ssize_t)(sizeof(ExifHeader)), MAX(0, ((ssize_t)(sizeof(eld->b))) - ((ssize_t)i) - 3)))) {
310
321
          eld->data_format = EL_DATA_FORMAT_EXIF;
311
1.30k
        } else {
312
1.30k
          eld->data_format = EL_DATA_FORMAT_JPEG; /* Probably JFIF - keep searching for APP1 EXIF*/
313
1.30k
        }
314
1.62k
        eld->size = 0;
315
1.62k
        eld->state = EL_READ_SIZE_BYTE_08;
316
1.62k
        break;
317
319
      case JPEG_MARKER_DCT:
318
517
      case JPEG_MARKER_DHT:
319
727
      case JPEG_MARKER_DQT:
320
1.87k
      case JPEG_MARKER_APP0:
321
2.56k
      case JPEG_MARKER_APP2:
322
2.96k
      case JPEG_MARKER_APP4:
323
3.22k
      case JPEG_MARKER_APP5:
324
3.76k
      case JPEG_MARKER_APP10:
325
4.16k
      case JPEG_MARKER_APP11:
326
4.38k
      case JPEG_MARKER_APP13:
327
4.65k
      case JPEG_MARKER_APP14:
328
4.92k
      case JPEG_MARKER_COM:
329
4.92k
        eld->data_format = EL_DATA_FORMAT_JPEG;
330
4.92k
        eld->size = 0;
331
4.92k
        eld->state = EL_READ_SIZE_BYTE_08;
332
4.92k
        break;
333
832k
      case 0xff:
334
832k
      case JPEG_MARKER_SOI:
335
832k
        break;
336
93
      default:
337
93
        exif_log (eld->log,
338
93
          EXIF_LOG_CODE_CORRUPT_DATA,
339
93
          "ExifLoader", _("The data supplied "
340
93
            "does not seem to contain "
341
93
            "EXIF data."));
342
93
        exif_loader_reset (eld);
343
93
        return 0;
344
839k
      }
345
891k
    }
346
891k
  }
347
348
  /*
349
   * If we reach this point, the buffer has not been big enough
350
   * to read all data we need. Fill it with new data.
351
   */
352
71.2k
  eld->b_len = 0;
353
71.2k
  goto begin;
354
82.0k
}
355
356
ExifLoader *
357
exif_loader_new (void)
358
11.2k
{
359
11.2k
  ExifMem *mem = exif_mem_new_default ();
360
11.2k
  ExifLoader *l = exif_loader_new_mem (mem);
361
362
11.2k
  exif_mem_unref (mem);
363
364
11.2k
  return l;
365
11.2k
}
366
367
ExifLoader *
368
exif_loader_new_mem (ExifMem *mem)
369
11.2k
{
370
11.2k
  ExifLoader *loader;
371
372
11.2k
  if (!mem) 
373
0
    return NULL;
374
  
375
11.2k
  loader = exif_mem_alloc (mem, sizeof (ExifLoader));
376
11.2k
  if (!loader) 
377
0
    return NULL;
378
11.2k
  loader->ref_count = 1;
379
380
11.2k
  loader->mem = mem;
381
11.2k
  exif_mem_ref (mem);
382
383
11.2k
  return loader;
384
11.2k
}
385
386
void
387
exif_loader_ref (ExifLoader *loader)
388
0
{
389
0
  if (loader) 
390
0
    loader->ref_count++;
391
0
}
392
393
static void
394
exif_loader_free (ExifLoader *loader)
395
11.2k
{
396
11.2k
  ExifMem *mem;
397
398
11.2k
  if (!loader) 
399
0
    return;
400
401
11.2k
  mem = loader->mem;
402
11.2k
  exif_loader_reset (loader);
403
11.2k
  exif_log_unref (loader->log);
404
11.2k
  exif_mem_free (mem, loader);
405
11.2k
  exif_mem_unref (mem);
406
11.2k
}
407
  
408
void
409
exif_loader_unref (ExifLoader *loader)
410
11.2k
{
411
11.2k
  if (!loader) 
412
0
    return;
413
11.2k
  if (!--loader->ref_count)
414
11.2k
    exif_loader_free (loader);
415
11.2k
}
416
417
void
418
exif_loader_reset (ExifLoader *loader)
419
11.3k
{
420
11.3k
  if (!loader) 
421
0
    return;
422
11.3k
  exif_mem_free (loader->mem, loader->buf); loader->buf = NULL;
423
11.3k
  loader->size = 0;
424
11.3k
  loader->bytes_read = 0;
425
11.3k
  loader->state = 0;
426
11.3k
  loader->b_len = 0;
427
11.3k
  loader->data_format = EL_DATA_FORMAT_UNKNOWN;
428
11.3k
}
429
430
ExifData *
431
exif_loader_get_data (ExifLoader *loader)
432
11.2k
{
433
11.2k
  ExifData *ed;
434
435
11.2k
  if (!loader || (loader->data_format == EL_DATA_FORMAT_UNKNOWN) ||
436
11.1k
      !loader->bytes_read)
437
363
    return NULL;
438
439
10.9k
  ed = exif_data_new_mem (loader->mem);
440
10.9k
  exif_data_log (ed, loader->log);
441
10.9k
  exif_data_load_data (ed, loader->buf, loader->bytes_read);
442
443
10.9k
  return ed;
444
11.2k
}
445
446
void
447
exif_loader_get_buf (ExifLoader *loader, const unsigned char **buf,
448
              unsigned int *buf_size)
449
0
{
450
0
  const unsigned char* b = NULL;
451
0
  unsigned int s = 0;
452
453
0
  if (loader) {
454
0
    if (loader->data_format == EL_DATA_FORMAT_UNKNOWN) {
455
0
      exif_log (loader->log, EXIF_LOG_CODE_DEBUG, "ExifLoader",
456
0
            "Loader format unknown");
457
0
    } else {
458
0
      b = loader->buf;
459
0
      s = loader->bytes_read;
460
0
    }
461
0
  }
462
463
0
  if (buf)
464
0
    *buf = b;
465
0
  if (buf_size)
466
0
    *buf_size = s;
467
0
}
468
469
void
470
exif_loader_log (ExifLoader *loader, ExifLog *log)
471
0
{
472
0
  if (!loader) 
473
0
    return;
474
0
  exif_log_unref (loader->log);
475
0
  loader->log = log;
476
0
  exif_log_ref (log);
477
0
}